Annotation of researchv10dc/cmd/netnews/src/header.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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