# 2.11BSD#431 - /usr/src/new/notes/src/newsinput.c

##### Functions

    bnewsgen          X
    main              X
    nfgen             X

##### Macros

    MAINLINE          X
    dprintf           X
    fprintf           X
    stderr            X

       1: #define MAINLINE
       2: #include "parms.h"
       3: #include "structs.h"
       4: #include "newsgate.h"
       5: #ifdef  SYSLOG
       6: # include <syslog.h>
       7: # undef stderr
       8: # define    fprintf     syslog
       9: # define    stderr      LOG_NOTICE
      10: #endif	SYSLOG
      11:
      12: #ifdef  RCSIDENT
      13: static char rcsid[] = "$Header: /usr/local/src/usenet/notes/src/RCS/newsinput.c,v 1.8 88/11/11 00:58:33 paul Exp $";
      14: #endif	RCSIDENT
      15:
      16: /*
      17:  *	newsinput
      18:  *
      19:  *	A total re-coding of the original.  Makes use of the
      20:  *	work that Lou Salkind and Tw Cook have done.  Lou rearranged
      21:  *	a bunch of stuff and Tw put the notes headers into the
      22:  *	news header.
      23:  */
      24:
      25: static char title[TITLEN + 1];              /* hold titles */
      26: extern char fromsys[SYSSZ + 1];             /* gave it to us */
      27: static struct when_f    entered;            /* date written */
      28: extern char origsys[SYSSZ + 1];             /* originator */
      29: extern char authname[NAMESZ + 1];           /* author */
      30: static int  has_suffix = 0;             /* had -(nf) suffix */
      31: static int  ShowTruncated = 1;              /* log truncated id's */
      32: static int  JustFirstGroup = 0;             /* into only 1 group */
      33:
      34: #define dprintf     if (0) printf
      35:
      36:
      37: main (argc, argv)
      38: int     argc;
      39: char  **argv;
      40: {
      41:     FILE * rawnews;
      42:     FILE * body;
      43:     char    pathname[BUFSIZ];
      44:     struct io_f io;
      45:     struct hbuf header;
      46:     char    nf[WDLEN];
      47:     struct nflist_f *nfptr;             /* expand newsgroups */
      48:     int     c;
      49:     int     onechar;
      50:     char   *tail;
      51:     int     fid;                    /* for close */
      52:     int     i;                      /* scratch */
      53:
      54:
      55: #ifdef  SYSLOG
      56:     openlog ("newsinput", LOG_PID, SYSLOG);
      57: #endif	SYSLOG
      58:     setuid (geteuid ());                /* force to "notes" */
      59:     startup (argc, argv);               /* common init */
      60:     rawnews = stdin;                    /* usually here */
      61:     for (fid = 3; fid < 20; fid++)          /* close all extras */
      62:     close (fid);
      63:
      64: /*
      65:  *	run down the arg vector. looking for various procesing options.
      66:  *
      67:  *	-t	do not log "truncated message id" situations in nfmaint.
      68:  *	-1	for multi-newsgroup articles, save this in the first
      69:  *		group listed and none of the others.
      70:  */
      71:
      72:     for (i = 1; i < argc; i++)
      73:     {
      74:     if (argv[i] == (char *) NULL)           /* done */
      75:         break;
      76:     if (strcmp (argv[i], "-t") == 0)        /* suppress truncation msgs */
      77:     {
      78:         ShowTruncated = 0;
      79:         continue;
      80:     }
      81:     if (strcmp (argv[i], "-1") == 0)        /* just first group */
      82:     {
      83:         JustFirstGroup++;
      84:         continue;
      85:     }
      86:     }
      87:
      88: /*
      89:  *	Parse the Header.  Follow all the USENET standards
      90:  *	for doing this.  Result is left in a fun little
      91:  *	structure.
      92:  *	Internalize some of the information to help us figure out
      93:  *	some things quickly.
      94:  */
      95:
      96:     if (!newsheader (&header, rawnews, TRUE))       /* read the headers */
      97:     {
      98:     fprintf (stderr, "Incoming News mangled more than usual\n");
      99:     exit (BAD);
     100:     }
     101:
     102: /*
     103:  *	Parse things like origsys, fromsys, author, date written
     104:  */
     105:     parsepath (header.path, header.from);       /* systems, authors */
     106:     parsetime (header.subdate, &entered);       /* submitted */
     107:     sprintf (pathname, "/tmp/nfxx%d", getpid ());
     108:     dprintf ("Origsys: %s\n", origsys);
     109:     dprintf ("fromsys: %s\n", fromsys);
     110:     dprintf ("Date Written:");
     111: #ifdef  notdef
     112:     prdate (&entered);
     113: #endif
     114:     dprintf ("\nauthor: %s\n", authname);
     115: /*
     116:  *	See if this might be a control message. Notes readers don't
     117:  *	care to see these.
     118:  *
     119:  *	News code also recognizes titles with first 5 characters set
     120:  *	to "cmsg " as control messages. We should clean them up too.
     121:  */
     122:     if (header.ctlmsg[0] != '\0')           /* is control */
     123:     {
     124:     fprintf (stderr, "Control message (ignored): %s\n", header.ctlmsg);
     125:     exit (0);                   /* "success" */
     126:     }
     127: /*
     128:  *	Save the body of the article somewhere safe (like not in
     129:  *	memory).
     130:  */
     131:     if ((body = fopen (pathname, "w")) == NULL)     /* failed */
     132:     {
     133:     fprintf (stderr, "Had problems creating/opening file %s\n", pathname);
     134:     exit (BAD);                 /* die */
     135:     }
     136:     while ((onechar = getc (rawnews)) != EOF)       /* save it */
     137:     putc (onechar, body);
     138:     fflush (body);                  /* make sure */
     139:     fclose (body);                  /* and close it */
     140:
     141: /*
     142:  *	Now run through the specified list of newsgroups,
     143:  *	re-scan the body and such each time.
     144:  */
     145:
     146:     expand (header.nbuf);               /* expand groups */
     147:     while ((nfptr = nextgroup ()) != (struct nflist_f *) NULL)
     148:     {
     149:
     150:     newsgroup (nfptr -> nf_name, nf, NEWSNF);   /* map it */
     151:     dprintf ("Newsgroup %s maps to notesfile %s\n", nfptr -> nf_name, nf);
     152:     tail = rindex (nfptr -> nf_name, '.');      /* catch ctl msgs */
     153:     if (tail != (char *) NULL && !strcmp (tail, CTL))/* it is one */
     154:     {
     155:         char    pbuf[256];              /* for title fixing */
     156:
     157:         /*
     158: 	     * re-route the control message to NFMAINT.
     159: 	     */
     160:         strcpy (nf, NFMAINT);           /* map it */
     161:         dprintf ("Control newsgroup %s mapped to %s\n",
     162:             nfptr -> nf_name, nf);
     163:         sprintf (pbuf, "%s:%s", nfptr -> nf_name, header.title);
     164:         strncpy (header.title, pbuf, BUFLEN);   /* prefix title */
     165:         header.title[BUFLEN - 1] = '\0';        /* ensure terminater */
     166:     }
     167:
     168:     if ((body = fopen (pathname, "r")) == NULL)
     169:     {
     170:         goto failed;                /* shit */
     171:     }
     172:     if (init (&io, nf) < 0)             /* open the nf */
     173:     {
     174:         char    pbuf[512];
     175:         char    tbuf[128];
     176: #ifdef AUTOCREATE
     177:         /*
     178: 	     * create the notesfile; we are allowed to do this.
     179: 	     */
     180:         sprintf (pbuf,
     181:             "Notesfile: %s\nNewsgroup: %s\n\nCreated by newsinput\n",
     182:             nf, nfptr -> nf_name);
     183:         if (strlen (nf) >= 14)
     184:         {
     185:         /*
     186: 		 * could be a truncation error; mark that in the message
     187: 		 */
     188:         sprintf (tbuf, "\n'%s' >= 14 characters long; check for abbreviations\n",
     189:             nf);
     190:         strcat (pbuf, tbuf);
     191:         }
     192:         sprintf (tbuf, "New NF: %s", nf);
     193:         nfcomment (NFMAINT, pbuf, tbuf, TRUE, 0);
     194:         buildnf (nf, Mstdir, 0, 1, 1);      /* open and networked */
     195:         x (init (&io, nf) < 0, "newsinput: open newly created notesfile");
     196: #else
     197:         /*
     198: 	     * drop the article, log it in nfmaint
     199: 	     */
     200:         sprintf (pbuf,
     201:             "Notesfile: %s\nNewsgroup %s\n\nNOT created by newsinput\n",
     202:             nf, nfptr -> nf_name);
     203:         sprintf (tbuf, "No Such NF: %s", nf);
     204:         nfcomment (NFMAINT, pbuf, tbuf, 0, 0);
     205:         fclose (body);              /* close article */
     206:         goto nextstep;
     207: #endif AUTOCREATE
     208:     }
     209:
     210:     if (nfgen (&io, &header, body, pathname) < 0)   /* not from notes */
     211:     {
     212:         dprintf ("Nfgen returns failure\n");
     213:         fclose (body);              /* give bnewsgen */
     214:         body = fopen (pathname, "r");       /* a clean copy */
     215:         if (bnewsgen (&io, &header, body) < 0)  /* or news */
     216:         {
     217:         dprintf ("bnewsgen returns failure\n");
     218:         goto failed;                /* drop out */
     219:         }
     220:     }
     221:     fclose (body);                  /* ready for loop */
     222:     finish (&io);
     223: nextstep:
     224:     if (JustFirstGroup)             /* only wanted 1 */
     225:     {
     226:         break;                  /* so exit this loop */
     227:     }
     228:     }
     229:
     230:     unlink (pathname);
     231:     exit (GOOD);
     232:
     233: /*
     234:  *	jump here on totally screwed up article.
     235:  */
     236: failed:
     237:     dprintf ("Jumped to failed\n");
     238:     unlink (pathname);                  /* body of article */
     239:     exit (BAD);
     240: }
     241:
     242: /*
     243:  *	nfgen(&io,&header,&FILE,pathname)
     244:  *
     245:  *	parse a notesfile-generated article.  Check the fields of
     246:  *	header and look for # lines in the body of the article to
     247:  *	determine if it came from notes.
     248:  *
     249:  *	returns:	0 no permission for author
     250:  *			> 0 signifies note or response where it wound up
     251:  *			-1 if the article wasn't generated by notes
     252:  */
     253:
     254: nfgen (io, header, body, pathname)
     255: struct io_f *io;
     256: struct hbuf *header;
     257: FILE * body;
     258: char   *pathname;
     259: {
     260:     register int    i;
     261:     register char  *p;
     262:     struct note_f   note;
     263:     struct note_f   note2;
     264:     struct id_f respid;
     265:     struct daddr_f  where;
     266:     struct when_f   whentime;
     267:     struct auth_f   auth;               /* author */
     268:     int     oldstyle = 0;
     269:     int     found;
     270:     char    line[CMDLEN];               /* scratch */
     271:     char   *suffix;
     272:     int     notenum;
     273:     int     status;
     274:     int     fosterstat;                 /* for foster parents */
     275:     int     count;
     276:     char    hline1[BUFLEN];             /* in-text header */
     277:     char    hline2[BUFLEN];             /* in-text header 2 */
     278:     int     onechar;                    /* scratch character */
     279:     char    field1[100],                /* scanf tmps */
     280:             field2[100];
     281:
     282: /*
     283:  * Check for titles ending in "- nf".
     284:  * We always remove these.
     285:  */
     286:     suffix = rindex (header -> title, '-');     /* find last */
     287:     if (suffix != (char *) NULL &&          /* have suffix */
     288:         (!strcmp (suffix, NFSUFFIX) || !strcmp (suffix, OLDSUFFIX)))
     289:     {                           /* and it matches */
     290:     if (--suffix > header -> title)         /* if we can */
     291:         *suffix = '\0';             /* strip "- (nf)" */
     292:     has_suffix++;                   /* flag it */
     293:     }
     294: /*
     295:  *	at this point we should check for embodied #N.... lines and
     296:  *	remove them.  This is conditional on having a "- (nf)" in the
     297:  *	title of the note.
     298:  */
     299:
     300:     strcpy (hline1, "");                /* empty these */
     301:     strcpy (hline2, "");
     302:     if (has_suffix)                 /* look for embedded */
     303:     {
     304:     long    position,               /* place marker */
     305:             ftell ();               /* for types */
     306:
     307:     position = ftell (body);            /* save it */
     308:     while (fgets (hline1, sizeof hline1, body) != NULL)
     309:     {
     310:         if (hline1[0] == '#' &&
     311:             (hline1[1] == 'N' || hline1[1] == 'R'))
     312:         {
     313:         break;                  /* found one */
     314:         }
     315:     }
     316:     /*
     317: 	 * could probably have looked for "#N:" and "#R:". i
     318: 	 * think that the old style lines had those colons.
     319: 	 * ok; we either EOF'ed or found an appropriate line
     320: 	 */
     321:     if (hline1[0] != '#' ||
     322:         (hline1[1] != 'N' && hline1[1] != 'R')) /* actually didn't */
     323:     {                       /* it wasn't really a #N or #R line */
     324:         fseek (body, position, 0);          /* rewind */
     325:         strcpy (hline1, "");            /* empty it */
     326:     }
     327:     else
     328:     {                       /* grab line 2 */
     329:         fgets (hline2, sizeof hline2, body);
     330:         while ((onechar = getc (body)) != '\n' && onechar != EOF)
     331:         ;                   /* zap separator line */
     332:     }
     333:     }
     334:
     335:     if (strlen (header -> nline1) == 0)         /* no new headers */
     336:     {
     337:     /*
     338: 	 * No notes header in the B news article header...
     339: 	 * If title ends with "- nf", look for the
     340: 	 * header in the body of the text.
     341: 	 * (for backwards compatability)
     342: 	 */
     343:     if (has_suffix == 0)                /* not from notes */
     344:     {
     345:         dprintf ("No NFSUFFIX and no header lines\n");
     346:         return (-1);
     347:     }
     348:     oldstyle = 1;
     349:     found = 0;
     350:     if (hline1[0] == '#')               /* got them earlier */
     351:     {
     352:         strcpy (header -> nline1, hline1);      /* first line */
     353:         strcpy (header -> nline2, hline2);      /* second line */
     354:         found++;                    /* and mark it */
     355:     }
     356:     while (!found &&                /* search body */
     357:         fgets (header -> nline1, sizeof header -> nline1, body))
     358:     {
     359:         if (header -> nline1[0] == '#')     /* bingo */
     360:         {
     361:         found++;
     362:         break;
     363:         }
     364:     }
     365:     if (!found ||
     366:         fgets (header -> nline2, sizeof header -> nline2, body) == NULL)
     367:     {
     368:         dprintf ("no header lines in text body\n");
     369:         return (-1);                /* not from notes */
     370:     }
     371:     }
     372:
     373: /*
     374:  * We now have the header lines.
     375:  * Check validity and do the appropriate action.
     376:  */
     377:     if (header -> nline1[0] != '#')
     378:     {
     379:     dprintf ("Invalid first header line\n");
     380:     return (-1);
     381:     }
     382:     dprintf ("First line is: %s\n", header -> nline1);
     383:     dprintf ("Second line is: %s\n", header -> nline2);
     384:     strncpy (title, header -> title, TITLEN);       /* get title */
     385:     title[TITLEN - 1] = '\0';               /* terminate for sure */
     386:
     387:     switch (header -> nline1[1])            /* parse it */
     388:     {
     389:     case 'N':                   /* base note */
     390:         if (sscanf (header -> nline1, "#N:%99[^:]:%ld:%o:%d", field1,
     391:             &note.n_id.uniqid, &status, &count) != 4)
     392:         {
     393:         return (-1);                /* no good */
     394:         }
     395:         strncpy (note.n_id.sys, field1, SYSSZ); /* copy */
     396:         note.n_id.sys[SYSSZ - 1] = '\0';        /* and terminate */
     397:         status |= FRMNEWS;              /* it's been there */
     398:
     399:         /*
     400: 	     * parse the second header line
     401: 	     */
     402:
     403:         p = header -> nline2;
     404:         for (i = 0; (i < HOMESYSSZ - 1) && (*p != '!' && *p != '\0'); i++)
     405:         auth.asystem[i] = *p++;         /* get the author */
     406:         auth.asystem[i] = '\0';         /* terminate */
     407:         while (*p != '!' && *p != '\0')
     408:         p++;                    /* skip to end of system */
     409:         if (*p == '!')
     410:         p++;                    /* skip the ! */
     411:         for (i = 0; (i < NAMESZ - 1) && (*p != ' ' && *p != '\0'); i++)
     412:         auth.aname[i] = *p++;           /* get the author */
     413:         auth.aname[i] = '\0';           /* terminate */
     414:         auth.aid = Anonuid;
     415:
     416:         while (*p != ' ' && *p)
     417:         p++;                    /* drop rest of author */
     418:         while (*p == ' ')               /* find the date */
     419:         p++;
     420:         parsetime (p, &note.n_date);        /* and parse it */
     421:
     422:         getperms (io, 1, note.n_id.sys);        /* check permissions */
     423:         if (allow (io, WRITOK) == 0)        /* not a chance */
     424:         return (0);             /* sort of success */
     425:
     426:         locknf (io, DSCRLOCK);          /* MUTEX */
     427:         if ((notenum = chknote (io, &note.n_id, &note2)) == 0)
     428:         {                       /* not in data base */
     429:         pagein (io, body, &where);      /* grab text */
     430:         status |= FRMNEWS;          /* through news */
     431:         strcpy (note.n_from, fromsys);      /* who gave it to us */
     432:         i = putnote (io, &where, title, status, &note, &auth,
     433:             NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME);
     434:         io -> nnotrcvd++;           /* count it */
     435:         unlocknf (io, DSCRLOCK);        /* MUTEX done */
     436:         return (i);             /* return notenum */
     437:         }
     438:         if ((note2.n_stat & ORPHND) && (status & ORPHND) == 0)
     439:         {                       /* replace foster */
     440:                             /* with true parent */
     441:         pagein (io, body, &note2.n_addr);   /* the text */
     442:         gettime (&note2.n_rcvd);        /* update timestamp */
     443:         gettime (&note2.n_lmod);        /* time stamp it */
     444:         copyauth (&auth, &note2.n_auth);    /* correct author */
     445:         note2.n_stat = status | FRMNEWS;    /* and status bits */
     446:         strncpy (note2.ntitle, title, TITLEN);
     447:         note2.n_date = entered;
     448:         strcpy (note2.n_from, fromsys);
     449:         putnrec (io, notenum, &note2);      /* and replace */
     450:         io -> adopted++;            /* count adoption */
     451:         io -> nnotrcvd++;           /* count in */
     452:         unlocknf (io, DSCRLOCK);
     453:         dprintf ("Orphaned response chain adopted\n");
     454:         return (notenum);           /* note number */
     455:         }
     456:         else
     457:         dprintf ("Duplicate note handed back by news\n");
     458:         unlocknf (io, DSCRLOCK);
     459:         return (0);                 /* mark resolved */
     460:
     461:     case 'R':                   /* response */
     462:         if (sscanf (header -> nline1, "#R:%99[^:]:%ld:%99[^:]:%ld:%o:%d",
     463:             field1, &note.n_id.uniqid, field2,
     464:             &respid.uniqid, &status, &count) != 6)
     465:         {
     466:         return (-1);                /* no good */
     467:         }
     468:         strncpy (note.n_id.sys, field1, SYSSZ); /* copy them */
     469:         strncpy (respid.sys, field2, SYSSZ);    /* both and */
     470:         note.n_id.sys[SYSSZ - 1] = respid.sys[SYSSZ - 1] = '\0';/* stop */
     471:         status |= FRMNEWS;              /* it's been there */
     472:
     473:         getperms (io, 1, respid.sys);       /* check modes */
     474:         if (allow (io, RESPOK) == 0)        /* not a chance */
     475:         return (0);             /* resolved */
     476:
     477:         p = header -> nline2;           /* second line */
     478:         for (i = 0; (i < HOMESYSSZ - 1) && (*p != '!' && *p != '\0'); i++)
     479:         auth.asystem[i] = *p++;         /* get the author */
     480:         auth.asystem[i] = '\0';         /* terminate */
     481:         while (*p != '!' && *p != '\0')
     482:         p++;                    /* skip to end of system */
     483:         if (*p == '!')
     484:         p++;                    /* skip the ! */
     485:         for (i = 0; (i < NAMESZ - 1) && (*p != ' ' && *p != '\0'); i++)
     486:         auth.aname[i] = *p++;           /* parse author */
     487:         auth.aname[i] = '\0';           /* terminate */
     488:         auth.aid = Anonuid;             /* default */
     489:         while (*p != ' ' && *p)
     490:         p++;                    /* rest of author */
     491:         while (*p == ' ')               /* find the date */
     492:         p++;
     493:         parsetime (p, &entered);            /* and parse it */
     494:
     495:         locknf (io, DSCRLOCK);          /* MUTEX */
     496:         notenum = chknote (io, &note.n_id, &note2);
     497:         if (notenum == 0)               /* found parent? */
     498:         {                       /* build foster */
     499:         dprintf ("Orphaned response handed in by news\n");
     500:         strcpy (note.n_from, fromsys);      /* make basic info */
     501:         note.n_nresp = 0;
     502:         note.n_auth.aid = Anonuid;
     503:         strcpy (note.n_auth.aname, "Unknown");
     504:         strcpy (note.n_auth.asystem, note.n_id.sys);/* system */
     505:         note.n_date = entered;
     506:         gettime (&whentime);            /* current time */
     507:         fosterstat = ORPHND | FRMNEWS;      /* combo there */
     508: #ifdef  notdef
     509:         strcpy (note.ntitle, "(Orphan) ");  /* prefix */
     510: #else
     511:         strcpy (note.ntitle, "");       /* empty */
     512: #endif
     513:         i = strlen (note.ntitle);       /* index */
     514:         for (p = header -> title; i < TITLEN && *p; i++, p++)/* rest of title */
     515:             note.ntitle[i] = *p;        /* basic title */
     516:         if (i < TITLEN)
     517:             note.ntitle[i] = '\0';      /* null it */
     518:         else
     519:             note.ntitle[TITLEN - 1] = '\0'; /* null */
     520:         where.addr = 0;             /* no text */
     521:         where.textlen = 0;          /* still no text */
     522:         notenum = putnote (io, &where, note.ntitle, fosterstat,
     523:             &note, &note.n_auth, NOPOLICY, NOLOCKIT, NOADDID,
     524:             fromsys, ADDTIME);      /* insert him */
     525:         io -> norphans++;           /* orphan census */
     526:         getnrec (io, notenum, &note2);      /* get good one */
     527:         }
     528: /*
     529:  *	At this point we know we have a parent because if there wasn't
     530:  *	one before, we built a foster parent.
     531:  */
     532:         if (chkresp (io, &respid, &note2, notenum) == 0)
     533:         {                       /* none, insert it */
     534:         status |= FRMNEWS;
     535:         pagein (io, body, &where);
     536:         i = putresp (io, &where, status, notenum, &entered, &auth,
     537:             &note, NOLOCKIT, &respid, NOADDID, fromsys,
     538:             ADDTIME, &whentime);
     539:         io -> nrsprcvd++;           /* count him in */
     540:         unlocknf (io, DSCRLOCK);        /* UNMUTEX */
     541:         return (i);             /* resp number */
     542:         }
     543:         else
     544:         dprintf ("Duplicate response handed back by news\n");
     545:         unlocknf (io, DSCRLOCK);
     546:         return (0);                 /* resolved */
     547:
     548:     default:                    /* bad news */
     549:         return (-1);
     550:     }                           /* NOTREACHED */
     551:     return (0);
     552: }
     553:
     554: /*
     555:  *	bnewsgen(&io,&header,&FILE)
     556:  *
     557:  *	parse an article that came through B-news.  We've already
     558:  *	checked to see if it was a notesfile generated article
     559:  *	so all we have to do is decide if it's a note/response
     560:  *	and put it in the appropriate place.
     561:  */
     562:
     563: bnewsgen (io, header, body)
     564: struct io_f *io;
     565: struct hbuf *header;
     566: FILE * body;
     567: {
     568:     register int    i;
     569:     char   *p;
     570:     struct note_f   note;
     571:     struct note_f   note2;
     572:     struct when_f   whentime;
     573:     struct daddr_f  where;
     574:     int     notenum;
     575:     int     status;
     576:     char    pbuf[BUFLEN];               /* scratch */
     577:     long    newsseq;
     578:     char    newssys[SYSSZ];
     579:     struct id_f newsid;
     580:     struct auth_f   auth;
     581:     char   *lead,
     582:            *trail;                  /* references */
     583:     char    basesys[SYSSZ];             /* references */
     584:     long    baseseq;                    /* ditto */
     585:     struct id_f baseid;                 /* ditto ditto */
     586:     char    field1[100],                /* scanf tmps */
     587:             field2[100];
     588:
     589:     getperms (io, 1, origsys);
     590:     if (allow (io, WRITOK) == 0)            /* let him* */
     591:     {
     592:     fprintf (stderr, "System %s not allowed to write notes\n", origsys);
     593:     return (0);                 /* NO! */
     594:     }
     595:
     596:     i = sscanf (header -> ident, "<%ld@%99[^>]>", &newsseq, field1, pbuf);
     597:     if (i < 2)                      /* try old */
     598:     {
     599:     i = sscanf (header -> ident, "%99[^.].%ld", field1, &newsseq);
     600:     }
     601:     /*
     602:      * new tricks with saving the entire message id in the
     603:      * system portion of the id_f structure
     604:      */
     605:     if (i < 2 && index (header -> ident, ':') == (char *) NULL)
     606:     {                           /* not unpacked yet */
     607:     newsseq = strlen (header -> ident);     /* save length */
     608:     if (newsseq < SYSSZ)                /* all fits */
     609:     {
     610:         strcpy (field1, header -> ident);       /* entire id */
     611:     }
     612:     else
     613:     {                       /* too long */
     614: #ifdef  NFMAINT
     615:         char    pbuf[BUFSIZ];
     616: #endif	NFMAINT
     617:
     618:         strncpy (field1, header -> ident, SYSSZ);
     619:         field1[SYSSZ - 1] = '\0';           /* truncate */
     620:         dprintf ("Chopped %d byte message id '%s' to '%s'\n",
     621:             newsseq, header -> ident, field1);
     622: #ifdef  NFMAINT
     623:         if (ShowTruncated)              /* log it */
     624:         {
     625:         sprintf (pbuf,
     626:             "%d byte Message-ID: '%s' truncated to '%s'\nPath: %s\nFrom: %s\nNewsgroups: %s\n",
     627:             newsseq, header -> ident, field1,
     628:             header -> path, header -> from, header -> nbuf);
     629:         nfcomment (NFMAINT, pbuf, "Truncated Message-ID", 0, 0);
     630:         }
     631: #endif	NFMAINT
     632:     }
     633:     newsseq = -newsseq;             /* make it < 0 */
     634:     i = 2;                      /* mark done */
     635:     }
     636:     if (i < 2)                      /* no id */
     637:     {
     638: #ifdef  NFMAINT
     639:     char    pbuf[BUFSIZ];
     640:
     641:     sprintf (pbuf,
     642:         "Message-ID: %s\nPath: %s\nFrom: %s\nNewsgroups: %s\n",
     643:         header -> ident, header -> path,
     644:         header -> from, header -> nbuf);
     645:     nfcomment (NFMAINT, pbuf, "UnManageable Message-ID", 0, 0);
     646: #endif	NFMAINT
     647:     dprintf ("can't fathom Message-ID: %s\n", header -> ident);
     648:     return (-1);                    /* mark bogus */
     649:     }
     650:     strncpy (newssys, field1, SYSSZ);           /* copy */
     651:     newssys[SYSSZ - 1] = '\0';              /* and truncate */
     652:
     653:     note.n_date = entered;
     654:     strcpy (note.n_from, fromsys);
     655:     strncpy (auth.aname, authname, NAMESZ);     /* fill in author */
     656:     strncpy (auth.asystem, origsys, HOMESYSSZ);     /* system */
     657:     auth.asystem[HOMESYSSZ - 1] = auth.aname[NAMESZ - 1] = '\0';
     658:     auth.aid = Anonuid;
     659:     status = FRMNEWS;                   /* came through news */
     660:     strncpy (title, header -> title, TITLEN);       /* move new title */
     661:     title[TITLEN - 1] = '\0';               /* sure it stops */
     662:
     663:     locknf (io, DSCRLOCK);              /* MUTEX */
     664: /*
     665:  *	first thing is to see if it's a base note somewhere.
     666:  */
     667:     strcpy (newsid.sys, newssys);           /* build uniq id */
     668:     strcpy (note.n_id.sys, newssys);            /* build descriptor */
     669:     note.n_id.uniqid = newsid.uniqid = newsseq;
     670:     notenum = chknote (io, &note.n_id, &note2);     /* try normal */
     671:     if (notenum == 0)                   /* try -100 trick */
     672:     {
     673:     note.n_id.uniqid = newsid.uniqid = newsseq * -100;
     674:     notenum = chknote (io, &note.n_id, &note2);
     675:     if (notenum == 0)               /* restore number */
     676:     {
     677:         note.n_id.uniqid = newsid.uniqid = newsseq;
     678:     }
     679:     }
     680:     if (notenum != 0)
     681:     {
     682:     if (!(note2.n_stat & ORPHND))
     683:     {
     684:         dprintf ("Duplicate news article received\n");
     685:         io -> nnotdrop++;               /* count as dropped */
     686:         unlocknf (io, DSCRLOCK);
     687:         return (0);                 /* done with it */
     688:     }
     689:     /*
     690: 	 *	 replace foster parent
     691: 	 */
     692:     pagein (io, body, &note2.n_addr);       /* collect text */
     693:     gettime (&note2.n_rcvd);            /* current tod */
     694:     gettime (&note2.n_lmod);            /* last touched */
     695:     copyauth (&auth, note2.n_auth);         /* fill in author */
     696:     note2.n_stat |= FRMNEWS;            /* brand it */
     697:     strncpy (note2.ntitle, title, TITLEN);      /* move title */
     698:     note2.n_date = entered;
     699:     strcpy (note2.n_from, fromsys);         /* who sent it to us */
     700:     putnrec (io, notenum, &note2);          /* and replace */
     701:     io -> adopted++;                /* count it */
     702:     io -> nnotrcvd++;               /* count in */
     703:     unlocknf (io, DSCRLOCK);
     704:     dprintf ("Orphaned Response Chain adopted\n");
     705:     return (notenum);               /* correctly placed */
     706:     }
     707:
     708: /*
     709:  *	See if we can turn this into a response to some base note.
     710:  *	First priority is to match it to any of the articles listed
     711:  *	in a References field if there is one.
     712:  */
     713:
     714:     notenum = 0;                    /* init to not found */
     715:     if (header -> followid[0])              /* references */
     716:     {
     717:     trail = header -> followid;
     718:     while ((lead = index (trail, '<')) && (trail = index (lead, '>')))
     719:     {                       /* delimited id */
     720:         i = sscanf (lead, "<%ld@%99[^>]>", &baseseq, field1, pbuf);
     721:         if (i < 2)                  /* try old format */
     722:         i = sscanf (lead, "%99[^.].%ld", field1, &baseseq);
     723:         if (i < 2)
     724:         continue;               /* try next one */
     725:         strncpy (basesys, field1, SYSSZ);
     726:         basesys[SYSSZ - 1] = '\0';          /* and truncate */
     727:
     728:         strcpy (baseid.sys, basesys);       /* build goal */
     729:         baseid.uniqid = baseseq;            /* try notes source */
     730:         if ((notenum = chknote (io, &baseid, &note2)))/* WANT ASSIGN */
     731:         break;                  /* yes! */
     732:
     733:         baseid.uniqid = baseseq * -100;     /* try news source */
     734:         if ((notenum = chknote (io, &baseid, &note2)))/* WANT ASSIGN */
     735:         break;                  /* yes! */
     736:
     737:         notenum = 0;                /* ensure "unfound" */
     738:     }
     739:     }
     740:
     741: /*
     742:  *	If References did any good, "notenum" is positive non-zero.
     743:  *	Otherwise it didn't help out at all and we have to resort to
     744:  *	parsing the title for "re:" prefixes
     745:  *	If we can find a base title, use the title search code to
     746:  *	scan for it.
     747:  */
     748:
     749:     if (notenum == 0 &&                 /* not found */
     750:         !strncmp (header -> title, "re: ", 4) ||    /* and looks like */
     751:         !strncmp (header -> title, "Re: ", 4) ||    /* a response */
     752:         !strncmp (header -> title, "RE: ", 4))
     753:     {
     754:     dprintf ("Looking at titles\n");
     755:     p = header -> title;
     756:     do
     757:     {
     758:         for (p += 3; *p == ' ' || *p == '\t'; p++); /* drop spaces */
     759:     } while (!strncmp (p, "re: ", 4) ||
     760:         !strncmp (p, "Re: ", 4) ||
     761:         !strncmp (p, "RE: ", 4));
     762:     strncpy (io -> xstring, p, TITLEN);     /* load it */
     763:     io -> xstring[TITLEN - 1] = '\0';       /* and terminate it */
     764:     notenum = findtitle (io, io -> descr.d_nnote, FALSE);/* start at back */
     765:     if (notenum > 0)                /* found one */
     766:         getnrec (io, notenum, &note2);      /* get a ptr to it */
     767:     }
     768:
     769: /*
     770:  *	OK. By now, we have a "notenum" if the article can be pegged
     771:  *	as a response to one of our notes.
     772:  *	Otherwise, notenum==0 and we'll have to turn it into
     773:  *	a base note.
     774:  */
     775:
     776:     if (notenum > 0)
     777:     {
     778:     dprintf ("Looking in response chain for note %d\n", notenum);
     779:     if (!chkresp (io, &newsid, &note2, notenum))
     780:     {                       /* no copy here */
     781:         pagein (io, body, &where);
     782:         gettime (&whentime);
     783:         i = putresp (io, &where, status, notenum, &entered, &auth, &note,
     784:             NOLOCKIT, &newsid, NOADDID, fromsys, ADDTIME, &whentime);
     785:         unlocknf (io, DSCRLOCK);            /* un-MUTEX */
     786:         return (i);
     787:     }
     788:     else
     789:     {                       /* copy there */
     790:         unlocknf (io, DSCRLOCK);            /* all done */
     791:         dprintf ("Duplicate Response handed back by news\n");
     792:         io -> nrspdrop++;               /* bong it */
     793:         return (0);                 /* count as done */
     794:     }
     795:     }
     796: /*
     797:  *	If we are going to do things this way, here is the point
     798:  *	where we should check about turning a news-generated
     799:  *	article into an orphaned response.
     800:  *
     801:  *	Basically, look for a non-empty references line and
     802:  *	make a foster parent with the first article id on that
     803:  *	line.
     804:  */
     805:
     806: /*
     807:  *	by this point, it's obvious that we can't turn the note into
     808:  *	a response.  We can skip the check to see if it is already
     809:  *	there because we did that at the very top of this loop
     810:  *	and since we've locked the notesfile up while we're doing this,
     811:  *	we know that nobody added a note.
     812:  */
     813:     dprintf ("Processing article as a base note\n");
     814:     pagein (io, body, &where);
     815:     notenum = putnote (io, &where, title, status, &note,
     816:         &auth, NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME);
     817:     io -> nnotrcvd++;                   /* count it */
     818:     unlocknf (io, DSCRLOCK);
     819:     return (notenum);
     820: }

#### Defined functions

bnewsgen defined in line 563; used 1 times

- in line 215

main defined in line 37; never used
nfgen defined in line 254; used 1 times

- in line 210

#### Defined variables

JustFirstGroup defined in line 32; used 2 times

- in line 83, 224

ShowTruncated defined in line 31; used 2 times

- in line 78, 623

entered defined in line 27; used 9 times

- in line 106, 112, 447, 493, 505, 536, 653, 698, 783

has_suffix defined in line 30; used 3 times

- in line 292, 302, 343

rcsid defined in line 13; never used
title defined in line 25; used 20 times

- in line 163-165(3), 286-290(2), 384-385(3), 432, 446, 514, 660-661(3), 697, 750-755(4), 815

#### Defined macros

MAINLINE defined in line 1; never used
dprintf defined in line 34; used 26 times

- in line 108-114(4), 151, 161, 212-217(2), 237, 345, 368, 379-383(3), 453-457(2), 499, 544, 620, 647, 684, 704, 754, 778, 791, 813

fprintf defined in line 8; used 4 times

- in line 98, 124, 133, 592

stderr defined in line 9; used 5 times

- in line 7, 98, 124, 133, 592

Last modified: 1989-01-12 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2233 |