1: /*
   2: ** Get header info from mail-format file.
   3: ** Return non-zero on success.
   4: */
   5: 
   6: #include "defs.h"
   7: #include <ctype.h>
   8: #include <sys/types.h>
   9: #include <stdio.h>
  10: #include "header.h"
  11: #include "llist.h"
  12: 
  13: #ifndef isblank
  14: #define isblank(c)  ((c) == ' ' || (c) == '\t')
  15: #endif
  16: 
  17: char    *hfgets();
  18: char    *arpadate();
  19: char    *errmsg();
  20: char    *strpbrk();
  21: time_t  cgtdate();
  22: extern  char    *index();
  23: extern unsigned strlen();
  24: extern  time_t  time();
  25: 
  26: #define FROM        1
  27: #define NEWSGROUP   2
  28: #define TITLE       3
  29: #define SUBMIT      4
  30: #define RECEIVE     5
  31: #define EXPIRE      6
  32: #define ARTICLEID   7
  33: #define MESSAGEID   8
  34: #define REPLYTO     9
  35: #define FOLLOWID    10
  36: #define CONTROL     11
  37: #define SENDER      12
  38: #define FOLLOWTO    13
  39: #define PATH        14
  40: #define POSTVERSION 15
  41: #define RELAYVERSION    16
  42: #define DISTRIBUTION    17
  43: #define ORGANIZATION    18
  44: #define NUMLINES    19
  45: #define KEYWORDS    20
  46: #define APPROVED    21
  47: #define NFID        22
  48: #define NFFROM      23
  49: #define XREF        24
  50: #define SUMMARY     25
  51: #define FULLNAME    26
  52: #define OTHER       99
  53: 
  54: /*
  55: ** This is the list of headers we recognize.
  56: ** All others get stripped before they get to inews.
  57: */
  58: struct htype    {
  59:     char    *hname;
  60:     int hid;
  61: } htype[] = {
  62:     {"Approved:",       APPROVED},
  63:     {"Article-I.D.:",   ARTICLEID},
  64:     {"Control:",        CONTROL},
  65:     {"Date-Received:",  RECEIVE},
  66:     {"Date:",       SUBMIT},
  67:     {"Distribution:",   DISTRIBUTION},
  68:     {"Expires:",        EXPIRE},
  69:     {"Followup-To:",    FOLLOWTO},
  70:     {"From:",       FROM},
  71: /*	{"Full-Name:",		FULLNAME},	*/
  72:     {"In-Reply-To:",    FOLLOWID},
  73:     {"Keywords:",       KEYWORDS},
  74:     {"Lines:",      NUMLINES},
  75:     {"Message-ID:",     MESSAGEID},
  76:     {"Newsgroups:",     NEWSGROUP},
  77:     {"Nf-From:",        NFFROM},
  78:     {"Nf-ID:",      NFID},
  79:     {"Organization:",   ORGANIZATION},
  80:     {"Path:",       PATH},
  81:     {"Posted:",     SUBMIT},
  82:     {"Posting-Version:",    POSTVERSION},
  83: /*	{"Received:",		RECEIVE},	a bad name w.r.t. RFC822 */
  84:     {"References:",     FOLLOWID},
  85:     {"Relay-Version:",  RELAYVERSION},
  86:     {"Reply-To:",       REPLYTO},
  87:     {"Sender:",     SENDER},
  88:     {"Subject:",        TITLE},
  89:     {"Summary:",        SUMMARY},
  90:     {"Title:",      TITLE},
  91:     {"Xref:",       XREF},
  92:     {(char *)NULL,      NULL}
  93: };
  94: 
  95: char *malloc();
  96: 
  97: rfc822read(hp, fp, bfr)
  98: register struct hbuf *hp;
  99: register FILE *fp;
 100: char    *bfr;
 101: {
 102:     register int    i = type(bfr);
 103:     long    curpos;
 104: 
 105:     do {
 106:         curpos = ftell(fp);
 107:         switch (i) {
 108:         case FROM:
 109:             getfield(bfr, hp->from, sizeof(hp->from));
 110:             break;
 111:         case NEWSGROUP:
 112:             getfield(bfr, hp->nbuf, sizeof(hp->nbuf));
 113:             break;
 114:         case TITLE:
 115:             getfield(bfr, hp->title, sizeof(hp->title));
 116:             break;
 117:         case SUBMIT:
 118:             getfield(bfr, hp->subdate, sizeof(hp->subdate));
 119:             break;
 120:         case EXPIRE:
 121:             getfield(bfr, hp->expdate, sizeof(hp->expdate));
 122:             break;
 123:         case MESSAGEID:
 124:             getfield(bfr, hp->ident, sizeof(hp->ident));
 125:             break;
 126:         case REPLYTO:
 127:             getfield(bfr, hp->replyto, sizeof(hp->replyto));
 128:             break;
 129:         case FOLLOWID:
 130:             getfield(bfr, hp->followid, sizeof(hp->followid));
 131:             break;
 132:         case SENDER:
 133:             getfield(bfr, hp->sender, sizeof(hp->sender));
 134:             break;
 135:         case FOLLOWTO:
 136:             getfield(bfr, hp->followto, sizeof(hp->followto));
 137:             break;
 138:         case CONTROL:
 139:             getfield(bfr, hp->ctlmsg, sizeof(hp->ctlmsg));
 140:             break;
 141:         case DISTRIBUTION:
 142:             getfield(bfr, hp->distribution, sizeof(hp->distribution));
 143:             break;
 144:         case ORGANIZATION:
 145:             getfield(bfr, hp->organization, sizeof(hp->organization));
 146:             break;
 147:         case KEYWORDS:
 148:             getfield(bfr, hp->keywords, sizeof(hp->keywords));
 149:             break;
 150:         case APPROVED:
 151:             getfield(bfr, hp->approved, sizeof(hp->approved));
 152:             break;
 153:         case SUMMARY:
 154:             getfield(bfr, hp->summary, sizeof(hp->summary));
 155:             break;
 156:         }
 157:     } while ((i = type(hfgets(bfr, LBUFLEN, fp))) > 0);
 158: 
 159:     if (*bfr != '\n')
 160:         fseek(fp, curpos, 0);
 161:     return(TRUE);
 162: }
 163: 
 164: #define its(type) (prefix(ptr, type))
 165: 
 166: type(ptr)
 167: register char   *ptr;
 168: {
 169:     register struct htype   *hp;
 170:     register char   *colon, *space;
 171:     static int  lasthdr = FALSE;    /* for continuation headers */
 172: 
 173:     /*
 174: 	** some consistency checks (i.e. is this really a header line?)
 175: 	*/
 176:     if ((ptr == NULL) || !isascii(*ptr) || (*ptr == '\n'))
 177:         return(lasthdr = FALSE);
 178: 
 179:     if (isblank(*ptr))      /* continuation line? */
 180:         return(lasthdr);
 181: 
 182:     colon = index(ptr, ':');
 183:     space = index(ptr, ' ');
 184:     if (!colon || space && space < colon)
 185:         return(lasthdr = FALSE);
 186: 
 187:     for(hp = htype; hp->hname; hp++) {
 188:         if (its(hp->hname))
 189:             return(lasthdr = hp->hid);
 190:     }
 191:     return(lasthdr = OTHER);
 192: }
 193: 
 194: /*
 195: ** Get the contents of the field of the header line, appending it,
 196: ** with a space delimeter if it's a continuation line.
 197: ** If there is already something in the header storage, skip this
 198: ** header line and the continuations.
 199: */
 200: getfield(src, dest, size)
 201: register char   *src, *dest;
 202: int size;           /* of dest (total bytes) */
 203: {
 204:     static int  skip = FALSE;   /* skip the continuation lines */
 205: 
 206:     if (src == (char *)NULL || dest == (char *)NULL)
 207:         return(FALSE);
 208: 
 209:     if (isblank(*src)) {                /* continuation line? */
 210:         if (skip)
 211:             return(TRUE);
 212:         if ((size -= strlen(dest)) <= 0)    /* any space left? */
 213:             return(FALSE);
 214:         while(*src && isblank(*src))        /* eat whitespace */
 215:             src++;
 216:         *--src = ' ';               /* backup & add one */
 217:         (void) strncat(dest, src, size - 1);    /* append to hdr */
 218:     } else {
 219:         skip = FALSE;
 220:         if (*dest)              /* already got one? */
 221:             return(skip = TRUE);        /* skip continuation */
 222:         if ((src = index(src, ':')) == (char *)NULL)    /* impossible */
 223:             return(FALSE);
 224:         src++;                  /* skip colon */
 225:         while(*src && isblank(*src))        /* eat whitespace */
 226:             src++;
 227:         (void) strncpy(dest, src, size - 1);
 228:     }
 229:     (void) nstrip(dest);
 230:     return(TRUE);
 231: }
 232: 
 233: /*
 234: ** Write out an RFC822 header, paying no attention to line limits.
 235: ** Ideally, we should do continuations in here...
 236: */
 237: rfc822write(hp, fp)
 238: register struct hbuf *hp;
 239: register FILE *fp;
 240: {
 241:     time_t t;
 242: 
 243:     if (hp->path[0])
 244:         fprintf(fp, "Path: %s\n", hp->path);
 245:     if (hp->from[0])
 246:         fprintf(fp, "From: %s\n", hp->from);
 247:     if (hp->nbuf[0])
 248:         fprintf(fp, "Newsgroups: %s\n", hp->nbuf);
 249:     if (hp->title[0])
 250:         fprintf(fp, "Subject: %s\n", hp->title);
 251:     if (hp->ident[0])
 252:         fprintf(fp, "Message-ID: %s\n", hp->ident);
 253:     if (hp->subdate[0])
 254:         t = cgtdate(hp->subdate);
 255:     else
 256:         time(&t);
 257:     fprintf(fp, "Date: %s\n", arpadate(&t));
 258:     if (*hp->expdate)
 259:         fprintf(fp, "Expires: %s\n", hp->expdate);
 260:     if (*hp->followid)
 261:         fprintf(fp, "References: %s\n", hp->followid);
 262:     if (*hp->ctlmsg)
 263:         fprintf(fp, "Control: %s\n", hp->ctlmsg);
 264:     if (*hp->sender)
 265:         fprintf(fp, "Sender: %s\n", hp->sender);
 266:     if (*hp->replyto)
 267:         fprintf(fp, "Reply-To: %s\n", hp->replyto);
 268:     if (*hp->followto)
 269:         fprintf(fp, "Followup-To: %s\n", hp->followto);
 270:     if (*hp->distribution)
 271:         fprintf(fp, "Distribution: %s\n", hp->distribution);
 272:     if (*hp->organization)
 273:         fprintf(fp, "Organization: %s\n", hp->organization);
 274:     if (*hp->keywords)
 275:         fprintf(fp, "Keywords: %s\n", hp->keywords);
 276:     if (*hp->summary)
 277:         fprintf(fp, "Summary: %s\n", hp->summary);
 278:     if (*hp->approved)
 279:         fprintf(fp, "Approved: %s\n", hp->approved);
 280:     putc('\n', fp);
 281:     return(!ferror(fp));
 282: }
 283: 
 284: /*
 285: ** strip leading and trailing spaces
 286: */
 287: char *
 288: sp_strip(s)
 289: register char   *s;
 290: {
 291:     register char   *cp;
 292: 
 293:     if (s == NULL)
 294:         return(NULL);
 295: 
 296:     if (*s == '\0')
 297:         return(s);
 298: 
 299:     cp = &s[strlen(s) - 1];
 300:     while(cp > s && isspace(*cp))
 301:         cp--;
 302: 
 303:     *++cp = '\0';   /* zap trailing spaces */
 304: 
 305:     for(cp = s; *cp && isspace(*cp); cp++)
 306:         continue;
 307: 
 308:     return(cp); /* return pointer to first non-space */
 309: }
 310: 
 311: /*
 312: ** crack an RFC822 from header field into address and fullname.
 313: */
 314: crackfrom(addr,name,field)
 315: char    *addr, *name, *field;
 316: {
 317:     char    commbuf[LBUFLEN];
 318:     char    addrbuf[LBUFLEN];
 319:     register char   *p;
 320:     register char   *ap = addrbuf;
 321:     register char   *np;
 322:     short   commfound = 0, comment = 0;
 323:     short   addrfound = 0, address = 0;
 324:     struct llist    comm, *cp = &comm;
 325: 
 326:     *name = '\0';   /* just make sure */
 327:     *addr = '\0';
 328: 
 329:     if ((p = field) == NULL)
 330:         return(FALSE);
 331: 
 332:     while(*p && isspace(*p))    /* eat leading white space */
 333:         p++;
 334: 
 335:     while(*p) {
 336:         switch(*p) {
 337:         case '(':
 338:             if (comment == 0) {
 339:                 np = commbuf;
 340:                 *np = '\0';
 341:             }
 342:             comment++;
 343:             break;
 344:         case ')':
 345:             if (comment > 0 && --comment == 0) {
 346:                 *np++ = *p++;   /* note incr; skip `)' */
 347:                 *np++ = '\0';
 348:                 if ((cp = l_alloc(cp, commbuf, strlen(commbuf) + 1)) == NULL) {
 349:                     if (commfound)
 350:                         l_free(comm);
 351:                     return(FALSE);
 352:                 }
 353:                 commfound++;
 354:                 np = NULL;
 355:                 continue;
 356:             }
 357:             break;
 358:         case '<':
 359:             if (address) {
 360:                 if (commfound)
 361:                     l_free(comm);
 362:                 return(FALSE);  /* AWK! Abort! */
 363:             }
 364:             if (!comment) {
 365:                 address++;
 366:                 *ap = '\0';
 367:                 ap = addr;
 368:             }
 369:             break;
 370:         case '>':
 371:             if (!comment && address) {
 372:                 address--;
 373:                 addrfound++;
 374:                 *ap = '\0';
 375:                 ap = &addrbuf[strlen(addrbuf)];
 376:                 p++;    /* skip the `>' */
 377:             }
 378:             break;
 379:         }
 380: 
 381:         if (comment) {
 382:             *np++ = *p;
 383:         } else if (address) {
 384:             if (*p != '<')
 385:                 *ap++ = *p;
 386:         } else {
 387:             *ap++ = *p;
 388:         }
 389:         if (*p)
 390:             p++;
 391:         else
 392:             break;
 393:     }
 394: 
 395:     *ap++ = '\0';
 396: 
 397:     if (addrfound) {
 398:         (void) strcpy(name, sp_strip(addrbuf));
 399:         (void) strcpy(addr, strcpy(commbuf, sp_strip(addr)));
 400:     } else {
 401:         (void) strcpy(addr, sp_strip(addrbuf));
 402:         *name = '\0';
 403:     }
 404:     /*
 405: 	** Just to be sure that we got the full name,
 406: 	** we'll take all of the comments!
 407: 	*/
 408:     if (commfound) {
 409:         register int    len;
 410:         register int    flag = (*name != '\0' ? TRUE : FALSE);
 411: 
 412:         for(cp = &comm; cp->l_item; cp = cp->l_next) {
 413:             if (flag)
 414:                 (void)strcat(name, ", ");
 415:             flag = TRUE;
 416:             if (cp->l_item[cp->l_len - 2] == ')')
 417:                 cp->l_item[cp->l_len - 2] = '\0';
 418:             (void)strcat(name, sp_strip(&cp->l_item[1]));
 419:         }
 420:         l_free(comm);
 421:     }
 422:     return(TRUE);
 423: }
 424: 
 425: /*
 426: ** Check on the validity of an RFC822 message-id.
 427: ** Check for enclosing `<>', an `@', and a `.' after
 428: ** the `@'. Also make sure that everything is ASCII,
 429: ** and non-control characters.
 430: */
 431: msgid_ok(id)
 432: register char   *id;
 433: {
 434:     register atdot = FALSE;
 435:     register closure = FALSE;
 436: 
 437:     if (id == NULL)
 438:         return(FALSE);      /* don't waste my time! */
 439: 
 440:     if (*id != '<')
 441:         return(FALSE);
 442: 
 443:     /* skip the first `<', cause we check for more */
 444:     for(id++; *id; id++) {
 445:         switch(*id) {
 446:         case '<':
 447:             return(FALSE);  /* we've already got one */
 448:         case '>':
 449:             closure = TRUE;
 450:             goto end;   /* djikstra is a wimp! */
 451:             break;
 452:         case '.':
 453:         case '@':       /* should be a domain spec */
 454:             atdot = TRUE;
 455:             break;
 456:         default:
 457:             if (!isascii(*id) || iscntrl(*id) || isspace(*id))
 458:                 return(FALSE);  /* quit immediately */
 459:             break;
 460:         }
 461:     }
 462: end:
 463:     return(atdot && closure);
 464: }
 465: 
 466: /*
 467: ** hfgets is like fgets, but deals with continuation lines.
 468: ** It also ensures that even if a line that is too long is
 469: ** received, the remainder of the line is thrown away
 470: ** instead of treated like a second line.
 471: */
 472: char *
 473: hfgets(buf, len, fp)
 474: char *buf;
 475: int len;
 476: FILE *fp;
 477: {
 478:     register int c;
 479:     register int n = 0;
 480:     register char *cp;
 481: 
 482:     cp = buf;
 483:     while (n < len && (c = getc(fp)) != EOF) {
 484:         if (c == '\n')
 485:             break;
 486:         if (!iscntrl(c) || c == '\b' || c == '\t') {
 487:             *cp++ = c;
 488:             n++;
 489:         }
 490:     }
 491:     if (c == EOF && cp == buf)
 492:         return NULL;
 493:     *cp = '\0';
 494: 
 495:     if (c != '\n') {
 496:         /* Line too long - part read didn't fit into a newline */
 497:         while ((c = getc(fp)) != '\n' && c != EOF)
 498:             ;
 499:     } else if (cp == buf) {
 500:         /* Don't look for continuation of blank lines */
 501:         *cp++ = '\n';
 502:         *cp = '\0';
 503:         return buf;
 504:     }
 505: 
 506:     while ((c = getc(fp)) == ' ' || c == '\t') {    /* for each cont line */
 507:         /* Continuation line. */
 508:         if ((n += 2) < len) {
 509:             *cp++ = '\n';
 510:             *cp++ = c;
 511:         }
 512:         while ((c = getc(fp)) != '\n' && c != EOF)
 513:             if ((!iscntrl(c) || c == '\b' || c == '\t') && n++ < len)
 514:                 *cp++ = c;
 515:     }
 516:     if (n >= len - 1)
 517:         cp = buf + len - 2;
 518:     *cp++ = '\n';
 519:     *cp = '\0';
 520:     if (c != EOF)
 521:         (void) ungetc(c, fp); /* push back first char of next header */
 522:     return buf;
 523: }
 524: 
 525: /*
 526:  * arpadate is like ctime(3) except that the time is returned in
 527:  * an acceptable ARPANET time format instead of ctime format.
 528:  */
 529: char *
 530: arpadate(longtime)
 531: time_t *longtime;
 532: {
 533:     register char *p, *q, *ud;
 534:     register int i;
 535:     static char b[40];
 536:     extern struct tm *gmtime();
 537:     extern char *asctime();
 538: 
 539:     /*  Get current time. This will be used resolve the timezone. */
 540:     ud = asctime(gmtime(longtime));
 541: 
 542:     /*  Crack the UNIX date line in a singularly unoriginal way. */
 543:     q = b;
 544: 
 545: #ifdef notdef
 546: /* until every site installs the fix to getdate.y, the day
 547:    of the week can cause time warps */
 548:     p = &ud[0];     /* Mon */
 549:     *q++ = *p++;
 550:     *q++ = *p++;
 551:     *q++ = *p++;
 552:     *q++ = ','; *q++ = ' ';
 553: #endif
 554: 
 555:     p = &ud[8];     /* 16 */
 556:     if (*p == ' ')
 557:         p++;
 558:     else
 559:         *q++ = *p++;
 560:     *q++ = *p++; *q++ = ' ';
 561: 
 562:     p = &ud[4];     /* Sep */
 563:     *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = ' ';
 564: 
 565:     p = &ud[22];        /* 1979 */
 566:     *q++ = *p++; *q++ = *p++; *q++ = ' ';
 567: 
 568:     p = &ud[11];        /* 01:03:52 */
 569:     for (i = 8; i > 0; i--)
 570:         *q++ = *p++;
 571: 
 572:     *q++ = ' ';
 573:     *q++ = 'G';     /* GMT */
 574:     *q++ = 'M';
 575:     *q++ = 'T';
 576:     *q = '\0';
 577: 
 578:     return b;
 579: }
 580: 
 581: time_t
 582: cgtdate(datestr)
 583: char *datestr;
 584: {
 585:     char    junk[40], month[40], day[30], tod[60], year[50], buf[BUFLEN];
 586:     static time_t   lasttime;
 587:     static char lastdatestr[BUFLEN] = "";
 588:     extern time_t   getdate();
 589: 
 590:     if (lastdatestr[0] && strcmp(datestr, lastdatestr) == 0)
 591:         return(lasttime);
 592:     lasttime = getdate(datestr, (struct timeb *)NULL);
 593:     if (lasttime < 0 &&
 594:       sscanf(datestr, "%s %s %s %s %s", junk, month, day, tod, year) == 5) {
 595:         (void) sprintf(buf, "%s %s, %s %s", month, day, year, tod);
 596:         lasttime = getdate(buf, (struct timeb *)NULL);
 597:     }
 598:     strncpy(lastdatestr, datestr, BUFLEN);
 599:     return(lasttime);
 600: }
 601: 
 602: char *
 603: errmsg(code)
 604: int code;
 605: {
 606:     extern int sys_nerr;
 607:     extern char *sys_errlist[];
 608:     static char ebuf[6+5+1];
 609: 
 610:     if (code > sys_nerr) {
 611:         (void) sprintf(ebuf, "Error %d", code);
 612:         return ebuf;
 613:     } else
 614:         return sys_errlist[code];
 615: }
 616: 
 617: /*
 618:  * Strip trailing newlines, blanks, and tabs from 's'.
 619:  * Return TRUE if newline was found, else FALSE.
 620:  */
 621: nstrip(s)
 622: register char *s;
 623: {
 624:     register char *p;
 625:     register int rc;
 626: 
 627:     rc = FALSE;
 628:     p = s;
 629:     while (*p)
 630:         if (*p++ == '\n')
 631:             rc = TRUE;
 632:     while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
 633:     *++p = '\0';
 634:     return rc;
 635: }
 636: 
 637: prefix(full, pref)
 638: register char *full, *pref;
 639: {
 640:     register char fc, pc;
 641: 
 642:     while ((pc = *pref++) != '\0') {
 643:         fc = *full++;
 644:         if (isupper(fc))
 645:             fc = tolower(fc);
 646:         if (isupper(pc))
 647:             pc = tolower(pc);
 648:         if (fc != pc)
 649:             return FALSE;
 650:     }
 651:     return TRUE;
 652: }
 653: 
 654: #ifndef USG
 655: char *
 656: strpbrk(str, chars)
 657: register char *str, *chars;
 658: {
 659:     register char *cp;
 660: 
 661:     do {
 662:         cp = chars - 1;
 663:         while (*++cp) {
 664:             if (*str == *cp)
 665:                 return str;
 666:         }
 667:     } while (*str++);
 668:     return NULL;
 669: }
 670: #endif /* !USG */

Defined functions

arpadate defined in line 529; used 2 times
cgtdate defined in line 581; used 2 times
crackfrom defined in line 314; never used
errmsg defined in line 602; used 9 times
getfield defined in line 200; used 16 times
hfgets defined in line 472; used 2 times
msgid_ok defined in line 431; never used
nstrip defined in line 621; used 1 times
prefix defined in line 637; used 1 times
rfc822read defined in line 97; used 1 times
rfc822write defined in line 237; never used
sp_strip defined in line 287; used 4 times
strpbrk defined in line 655; used 1 times
  • in line 20
type defined in line 166; used 4 times

Defined variables

htype defined in line 61; used 1 times

Defined struct's

htype defined in line 58; used 2 times
  • in line 169(2)

Defined macros

APPROVED defined in line 46; used 1 times
  • in line 62
ARTICLEID defined in line 32; used 1 times
  • in line 63
CONTROL defined in line 36; used 1 times
  • in line 64
DISTRIBUTION defined in line 42; used 1 times
  • in line 67
EXPIRE defined in line 31; used 1 times
  • in line 68
FOLLOWID defined in line 35; used 2 times
FOLLOWTO defined in line 38; used 1 times
  • in line 69
FROM defined in line 26; used 1 times
  • in line 70
FULLNAME defined in line 51; never used
KEYWORDS defined in line 45; used 1 times
  • in line 73
MESSAGEID defined in line 33; used 1 times
  • in line 75
NEWSGROUP defined in line 27; used 1 times
  • in line 76
NFFROM defined in line 48; used 1 times
  • in line 77
NFID defined in line 47; used 1 times
  • in line 78
NUMLINES defined in line 44; used 1 times
  • in line 74
ORGANIZATION defined in line 43; used 1 times
  • in line 79
OTHER defined in line 52; used 1 times
PATH defined in line 39; used 1 times
  • in line 80
POSTVERSION defined in line 40; used 1 times
  • in line 82
RECEIVE defined in line 30; used 1 times
  • in line 65
RELAYVERSION defined in line 41; used 1 times
  • in line 85
REPLYTO defined in line 34; used 1 times
  • in line 86
SENDER defined in line 37; used 1 times
  • in line 87
SUBMIT defined in line 29; used 2 times
SUMMARY defined in line 50; used 1 times
  • in line 89
TITLE defined in line 28; used 2 times
XREF defined in line 49; used 1 times
  • in line 91
isblank defined in line 14; used 5 times
its defined in line 164; used 1 times
Last modified: 1986-03-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2241
Valid CSS Valid XHTML 1.0 Strict