Annotation of 43BSD/contrib/notes/src/bnewshead.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.