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