Annotation of researchv10no/cmd/netnews/src/header.c, revision 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.