|
|
1.1 ! root 1: /* ! 2: * header.c - header functions plus some other goodies ! 3: * ! 4: * TAKEN FROM BNEWS 2.10 6/24/83 ! 5: * ! 6: */ ! 7: ! 8: #ifdef RCSIDENT ! 9: static char *SccsId = "@(#)header.c 2.20 6/24/83"; ! 10: static char *RCSid = "$Header: bnewshead.c,v 1.7.0.1 85/03/06 20:03:00 notes Rel $"; ! 11: #endif RCSIDENT ! 12: ! 13: #include <stdio.h> ! 14: #include <sys/types.h> ! 15: #include "parms.h" /* from notes */ ! 16: #include "structs.h" /* ditto */ ! 17: /* above maybe unused */ ! 18: #include "newsgate.h" ! 19: ! 20: ! 21: char *hfgets (); ! 22: ! 23: static int seenrelay; ! 24: static char bfr[PATHLEN]; /* header buffer */ ! 25: ! 26: /* ! 27: * Read header from file fp into *hp. If wholething is FALSE, ! 28: * it's an incremental read, otherwise start from scratch. ! 29: * Return (FILE *) if header okay, else NULL. ! 30: */ ! 31: ! 32: newsheader (hp, fp, wholething) ! 33: register struct hbuf *hp; ! 34: FILE * fp; ! 35: int wholething; ! 36: { ! 37: register int len; ! 38: ! 39: if (wholething) /* from scratch */ ! 40: bclear ((char *) hp, sizeof (*hp)); ! 41: ! 42: seenrelay = 0; ! 43: ! 44: /* ! 45: * Check that it's a B news style header. ! 46: */ ! 47: if (((hfgets (bfr, PATHLEN, fp) != NULL && ! 48: *bfr >= 'A' && *bfr <= 'Z') && index (bfr, ':'))) ! 49: if (frmread (fp, hp)) ! 50: goto strip; ! 51: ! 52: /* ! 53: * It's not. Try A news (begins with PROTO). ! 54: */ ! 55: if (*bfr != PROTO) ! 56: return (0); ! 57: ! 58: /* ! 59: * Read in an A news format article. ! 60: */ ! 61: strncpy (hp -> oident, &(bfr[1]), NAMELEN); /* file name */ ! 62: if (!nstrip (hp -> oident)) ! 63: return (0); ! 64: hfgets (hp -> nbuf, BUFLEN, fp); /* newsgroup list */ ! 65: if (!nstrip (hp -> nbuf)) ! 66: return (0); ! 67: ngcat (hp -> nbuf); /* trailing delim */ ! 68: hfgets (hp -> path, PATHLEN, fp); /* source path */ ! 69: if (!nstrip (hp -> path)) ! 70: return (0); ! 71: hfgets (hp -> subdate, DATELEN, fp); /* date */ ! 72: if (!nstrip (hp -> subdate)) ! 73: return (0); ! 74: hfgets (hp -> title, BUFLEN, fp); /* title */ ! 75: if (!nstrip (hp -> title)) ! 76: return (0); ! 77: ! 78: /* ! 79: * strip off sys! from front of path. ! 80: */ ! 81: strip: ! 82: strcpy (bfr, System); ! 83: if (strncmp (bfr, hp -> path, (len = strlen (bfr))) == 0 ! 84: && index (NETCHRS, hp -> path[len])) ! 85: strcpy (hp -> path, &(hp -> path[len + 1])); ! 86: ! 87: if (wholething && hp -> from[0] == '\0') /* intuit the from: */ ! 88: intuitfrom (hp); /* if wasn't there */ ! 89: ! 90: if (wholething) /* Get message ID's. */ ! 91: fixid (hp); ! 92: return (1); ! 93: } ! 94: ! 95: ! 96: /* ! 97: * Get header info from mail-format file. ! 98: * Return non-zero on success. ! 99: */ ! 100: ! 101: #include <ctype.h> ! 102: #define FROM 1 ! 103: #define NEWSGROUP 2 ! 104: #define TITLE 3 ! 105: #define SUBMIT 4 ! 106: #define RECEIVE 5 ! 107: #define EXPIRE 6 ! 108: #define ARTICLEID 7 ! 109: #define MESSAGEID 8 ! 110: #define REPLYTO 9 ! 111: #define FOLLOWID 10 ! 112: #define CONTROL 11 ! 113: #define SENDER 12 ! 114: #define FOLLOWTO 13 ! 115: #define PATH 14 ! 116: #define POSTVERSION 15 ! 117: #define RELAYVERSION 16 ! 118: #define DISTRIBUTION 17 ! 119: #define ORGANIZATION 18 ! 120: #define NUMLINES 19 ! 121: #define KEYWORDS 20 ! 122: #define APPROVED 21 ! 123: ! 124: #define NLINE1 22 ! 125: #define NLINE2 23 ! 126: ! 127: #define OTHER 99 ! 128: ! 129: ! 130: char *malloc (); ! 131: ! 132: frmread (fp, hp) ! 133: register FILE * fp; ! 134: register struct hbuf *hp; ! 135: { ! 136: int unreccnt = 0; ! 137: register int i; ! 138: long curpos; ! 139: int hdrlineno = 0; ! 140: int iu; ! 141: ! 142: for (iu = 0; iu < NUNREC; iu++) ! 143: hp -> unrec[iu] = NULL; ! 144: ! 145: i = type (bfr); ! 146: do ! 147: { ! 148: curpos = ftell (fp); ! 149: hdrlineno++; ! 150: switch (i) ! 151: { ! 152: case PATH: ! 153: getfield (hp -> path); ! 154: break; ! 155: case FROM: ! 156: getfield (hp -> from); ! 157: break; ! 158: case NEWSGROUP: ! 159: getfield (hp -> nbuf); ! 160: break; ! 161: case TITLE: ! 162: getfield (hp -> title); ! 163: break; ! 164: case SUBMIT: ! 165: getfield (hp -> subdate); ! 166: break; ! 167: case RECEIVE: ! 168: getfield (hp -> recdate); ! 169: break; ! 170: case EXPIRE: ! 171: getfield (hp -> expdate); ! 172: break; ! 173: case ARTICLEID: ! 174: getfield (hp -> oident); ! 175: break; ! 176: case MESSAGEID: ! 177: getfield (hp -> ident); ! 178: break; ! 179: case REPLYTO: ! 180: getfield (hp -> replyto); ! 181: break; ! 182: case FOLLOWID: ! 183: getfield (hp -> followid); ! 184: break; ! 185: case SENDER: ! 186: getfield (hp -> sender); ! 187: break; ! 188: case FOLLOWTO: ! 189: getfield (hp -> followto); ! 190: break; ! 191: case CONTROL: ! 192: getfield (hp -> ctlmsg); ! 193: break; ! 194: case POSTVERSION: ! 195: getfield (hp -> postversion); ! 196: break; ! 197: case DISTRIBUTION: ! 198: getfield (hp -> distribution); ! 199: break; ! 200: case ORGANIZATION: ! 201: getfield (hp -> organization); ! 202: break; ! 203: case NUMLINES: ! 204: getfield (hp -> numlines); ! 205: hp -> intnumlines = atoi (hp -> numlines); ! 206: break; ! 207: case KEYWORDS: ! 208: getfield (hp -> keywords); ! 209: break; ! 210: case APPROVED: ! 211: getfield (hp -> approved); ! 212: break; ! 213: case NLINE1: /* notes-specific */ ! 214: getfield (hp -> nline1); ! 215: break; ! 216: case NLINE2: /* notes-specific */ ! 217: getfield (hp -> nline2); ! 218: break; ! 219: case RELAYVERSION: ! 220: /* ! 221: * Only believe a relay version if it's the first ! 222: * line, otherwise it probably got passed through ! 223: * by some old neighbor. ! 224: */ ! 225: if (hdrlineno == 1) ! 226: { ! 227: getfield (hp -> relayversion); ! 228: seenrelay = 1; ! 229: } ! 230: break; ! 231: case OTHER: ! 232: if (unreccnt < NUNREC) ! 233: { ! 234: hp -> unrec[unreccnt] = malloc (strlen (bfr) + 1); ! 235: strcpy (hp -> unrec[unreccnt], bfr); ! 236: unreccnt++; ! 237: } ! 238: break; ! 239: } ! 240: } while ((i = type (hfgets (bfr, LBUFLEN, fp))) > 0); ! 241: ! 242: if (*bfr != '\n') ! 243: { ! 244: printf ("Bizzaro header line: %s\n", bfr); ! 245: return (0); ! 246: } ! 247: ! 248: /* ! 249: * Check to see if the REQUIRED headers are present. If so, return ! 250: * that we found a message. Otherwise barf. ! 251: */ ! 252: if ((hp -> from[0] || hp -> path[0]) && ! 253: hp -> subdate[0] && ! 254: (hp -> ident[0] || hp -> oident[0])) ! 255: { ! 256: return TRUE; ! 257: } ! 258: return FALSE; ! 259: } ! 260: ! 261: /* ! 262: * There was no From: line in the message (because it was generated by ! 263: * an old news program). Guess what it should have been and create it. ! 264: */ ! 265: ! 266: intuitfrom (hp) ! 267: register struct hbuf *hp; ! 268: { ! 269: char *tp; ! 270: char *user, ! 271: *host, ! 272: *fullname; ! 273: char *tailpath (); ! 274: char *at, ! 275: *dot; ! 276: ! 277: tp = tailpath (hp); ! 278: user = rindex (tp, '!'); ! 279: if (user == NULL) ! 280: user = tp; ! 281: else ! 282: *user++ = '\0'; ! 283: ! 284: /* Check for an existing Internet address on the end. */ ! 285: at = index (user, '@'); ! 286: if (at) ! 287: { ! 288: dot = index (at, '.'); ! 289: if (dot) ! 290: { ! 291: strcpy (hp -> from, user); ! 292: return; ! 293: } ! 294: /* @ signs are illegal except for the biggie, so */ ! 295: *at = '%'; ! 296: } ! 297: ! 298: if (tp[0] == '.') ! 299: host = index (tp, '!') + 1; ! 300: else ! 301: if (user == tp) ! 302: host = System; ! 303: else ! 304: host = tp; ! 305: ! 306: tp = index (host, '@'); ! 307: if (tp != NULL) ! 308: *tp = 0; ! 309: sprintf (hp -> from, "%s@%s.%s", user, host, DFLTDOMAIN); ! 310: ! 311: fullname = index (hp -> path, '('); ! 312: if (fullname != NULL) ! 313: { ! 314: fullname--; ! 315: strcat (hp -> from, fullname); ! 316: *fullname = 0; ! 317: } ! 318: } ! 319: ! 320: /* ! 321: * If the message has only one of ident/oident, guess what ! 322: * the other one should be and fill them both in. ! 323: */ ! 324: ! 325: fixid (hp) ! 326: register struct hbuf *hp; ! 327: { ! 328: char lbuf[100]; ! 329: char *p; ! 330: #ifdef OLD ! 331: char *q; ! 332: #endif OLD ! 333: ! 334: if (hp -> ident[0] == '\0' && hp -> oident[0] != '\0') ! 335: { ! 336: strcpy (lbuf, hp -> oident); ! 337: p = index (lbuf, '.'); ! 338: if (p == 0) ! 339: { ! 340: strcpy (hp -> ident, hp -> oident); ! 341: return; ! 342: } ! 343: *p++ = '\0'; ! 344: /* ! 345: * It may seem strange that we hardwire ".UUCP" in ! 346: * here instead of DFLTDOMAIN. However, we are trying ! 347: * to guess what the domain was on the posting system, ! 348: * not the local system. Since we don't really know ! 349: * what the posting system does, we just go with the ! 350: * majority - almost everyone will be a .UUCP if they ! 351: * didn't fill in their Message-ID. ! 352: */ ! 353: sprintf (hp -> ident, "<%s@%s%s>", p, lbuf, ".UUCP"); ! 354: } ! 355: ! 356: #ifdef OLD ! 357: if (hp -> oident[0] == '\0' && hp -> ident[0] != '\0') ! 358: { ! 359: strcpy (lbuf, hp -> ident); ! 360: p = index (lbuf, '@'); ! 361: if (p == 0) ! 362: { ! 363: strcpy (hp -> oident, hp -> ident); ! 364: return; ! 365: } ! 366: *p++ = '\0'; ! 367: q = index (p, '.'); ! 368: if (!q) ! 369: q = index (p, '>'); ! 370: if (q) ! 371: *q++ = '\0'; ! 372: p[SNLN] = '\0'; ! 373: sprintf (hp -> oident, "%s.%s", p, lbuf + 1); ! 374: } ! 375: #endif ! 376: } ! 377: ! 378: /* ! 379: * Get the given field of a header (char * parm) from bfr, but only ! 380: * if there's something actually there (after the colon). Don't ! 381: * bother if we already have an entry for this field. ! 382: */ ! 383: ! 384: getfield (hpfield) ! 385: char *hpfield; ! 386: { ! 387: char *ptr; ! 388: ! 389: if (hpfield[0]) ! 390: return; ! 391: for (ptr = index (bfr, ':'); isspace (*++ptr);) ! 392: ; ! 393: if (*ptr != '\0') ! 394: { ! 395: strcpy (hpfield, ptr); ! 396: nstrip (hpfield); ! 397: } ! 398: return; ! 399: } ! 400: ! 401: ! 402: /* ! 403: * Determine the type of the header ! 404: */ ! 405: ! 406: #define its(type) (!strncmp(ptr,type,strlen(type))) ! 407: ! 408: type (ptr) ! 409: char *ptr; ! 410: { ! 411: char *colon, ! 412: *space; ! 413: ! 414: if (!isalpha (*ptr) && strncmp (ptr, "From ", 5)) ! 415: return FALSE; ! 416: colon = index (ptr, ':'); ! 417: space = index (ptr, ' '); ! 418: if (!colon || colon + 1 != space) ! 419: return FALSE; ! 420: if (its ("From: ")) ! 421: if (index (ptr, '@') && !index (ptr, '!') && seenrelay) ! 422: return FROM; ! 423: else ! 424: return PATH; ! 425: if (its ("Path: ")) ! 426: return PATH; ! 427: if (its ("Newsgroups: ")) ! 428: return NEWSGROUP; ! 429: if (its ("Subject: ") || its ("Title: ")) ! 430: return TITLE; ! 431: if (its ("Posted: ") || its ("Date: ")) ! 432: return SUBMIT; ! 433: if (its ("Date-Received: ") || its ("Received: ")) ! 434: return RECEIVE; ! 435: if (its ("Expires: ")) ! 436: return EXPIRE; ! 437: if (its ("Article-I.D.: ")) ! 438: return ARTICLEID; ! 439: if (its ("Message-ID: ")) ! 440: return MESSAGEID; ! 441: if (its ("Reply-To: ")) ! 442: return REPLYTO; ! 443: if (its ("References: ")) ! 444: return FOLLOWID; ! 445: if (its ("Control: ")) ! 446: return CONTROL; ! 447: if (its ("Sender: ")) ! 448: return SENDER; ! 449: if (its ("Followup-To: ")) ! 450: return FOLLOWTO; ! 451: if (its ("Posting-Version: ")) ! 452: return POSTVERSION; ! 453: if (its ("Relay-Version: ")) ! 454: return RELAYVERSION; ! 455: if (its ("Distribution: ")) ! 456: return DISTRIBUTION; ! 457: if (its ("Organization: ")) ! 458: return ORGANIZATION; ! 459: if (its ("Lines: ")) ! 460: return NUMLINES; ! 461: if (its ("Keywords: ")) ! 462: return KEYWORDS; ! 463: if (its ("Approved: ")) ! 464: return APPROVED; ! 465: if (its ("Nf-ID: ")) ! 466: return NLINE1; ! 467: if (its ("Nf-From: ")) ! 468: return NLINE2; ! 469: return OTHER; ! 470: } ! 471: ! 472: /* ! 473: * Set nc bytes, starting at cp, to zero. ! 474: */ ! 475: ! 476: bclear (cp, nc) ! 477: register char *cp; ! 478: register int nc; ! 479: { ! 480: while (nc--) ! 481: *cp++ = 0; ! 482: } ! 483: ! 484: /* ! 485: * Strip trailing newlines, blanks, and tabs from 's'. ! 486: * Return TRUE if newline was found, else FALSE. ! 487: */ ! 488: ! 489: nstrip (s) ! 490: register char *s; ! 491: { ! 492: register char *p; ! 493: register int rc; ! 494: ! 495: rc = FALSE; ! 496: p = s; ! 497: while (*p) ! 498: if (*p++ == '\n') ! 499: rc = TRUE; ! 500: while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t')); ! 501: *++p = '\0'; ! 502: return (rc); ! 503: } ! 504: ! 505: /* ! 506: * Append NGDELIM to string. ! 507: */ ! 508: ! 509: ngcat (s) ! 510: register char *s; ! 511: { ! 512: if (*s) ! 513: { ! 514: while (*s++); ! 515: s -= 2; ! 516: if (*s++ == NGDELIM) ! 517: return; ! 518: } ! 519: *s++ = NGDELIM; ! 520: *s = '\0'; ! 521: } ! 522: ! 523: /* ! 524: * Return a compact representation of the person who posted the given ! 525: * message. A sender or internet name will be used, otherwise ! 526: * the last part of the path is used preceeded by an optional ".." ! 527: */ ! 528: char * ! 529: tailpath (hp) ! 530: struct hbuf *hp; ! 531: { ! 532: char *p, ! 533: *r; ! 534: static char resultbuf[BUFLEN]; ! 535: char pathbuf[PATHLEN]; ! 536: char *malloc (); ! 537: ! 538: /* ! 539: * This only happens for articles posted by old news software ! 540: * in non-internet format. ! 541: */ ! 542: resultbuf[0] = '\0'; ! 543: strcpy (pathbuf, hp -> path); ! 544: p = index (pathbuf, ' '); ! 545: if (p) ! 546: *p = '\0'; /* Chop off trailing " (name)" */ ! 547: r = rindex (pathbuf, '!'); ! 548: if (r == 0) ! 549: { ! 550: r = pathbuf; ! 551: } ! 552: else ! 553: { ! 554: while (r > pathbuf && *--r != '!') ! 555: ; ! 556: if (r > pathbuf) ! 557: { ! 558: r++; ! 559: strcpy (resultbuf, "..!"); ! 560: } ! 561: } ! 562: strcat (resultbuf, r); ! 563: return resultbuf; ! 564: } ! 565: ! 566: ! 567: ! 568: /* ! 569: * hfgets is like fgets, but deals with continuation lines. ! 570: * It also ensures that even if a line that is too long is ! 571: * received, the remainder of the line is thrown away ! 572: * instead of treated like a second line. ! 573: */ ! 574: ! 575: char *hfgets (buf, len, fp) ! 576: char *buf; ! 577: int len; ! 578: FILE * fp; ! 579: { ! 580: register int c; ! 581: register char *cp, ! 582: *tp; ! 583: ! 584: cp = fgets (buf, len, fp); ! 585: if (cp == NULL) ! 586: return NULL; ! 587: ! 588: tp = cp + strlen (cp); ! 589: if (tp[-1] != '\n') ! 590: { ! 591: /* ! 592: * Line too long - part read didn't fit into a newline ! 593: */ ! 594: while ((c = getc (fp)) != '\n' && c != EOF) ! 595: ; ! 596: } ! 597: else ! 598: *--tp = '\0'; /* clobber newline */ ! 599: ! 600: while ((c = getc (fp)) == ' ' || c == '\t') /* continuation */ ! 601: { ! 602: /* ! 603: * Continuation line. ! 604: */ ! 605: while ((c = getc (fp)) == ' ' || c == '\t') /* skip white space */ ! 606: ; ! 607: if (tp - cp < len) ! 608: { ! 609: *tp++ = ' '; ! 610: *tp++ = c; ! 611: } ! 612: while ((c = getc (fp)) != '\n' && c != EOF) ! 613: if (tp - cp < len) ! 614: *tp++ = c; ! 615: } ! 616: *tp++ = '\n'; ! 617: *tp++ = '\0'; ! 618: if (c != EOF) ! 619: ungetc (c, fp); /* push back char */ ! 620: return cp; ! 621: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.