Annotation of 43BSD/contrib/nntp/xmit/rfc822.c, revision 1.1

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

unix.superglobalmegacorp.com

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