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
main defined in line 37; never used
nfgen defined in line 254; used 1 times

Defined variables

JustFirstGroup defined in line 32; used 2 times
ShowTruncated defined in line 31; used 2 times
entered defined in line 27; used 9 times
has_suffix defined in line 30; used 3 times
rcsid defined in line 13; never used
title defined in line 25; used 20 times

Defined macros

MAINLINE defined in line 1; never used
dprintf defined in line 34; used 26 times
fprintf defined in line 8; used 4 times
stderr defined in line 9; used 5 times
Last modified: 1989-01-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5414
Valid CSS Valid XHTML 1.0 Strict