Annotation of 43BSDTahoe/ucb/Mail/aux.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that this notice is preserved and that due credit is given
        !             7:  * to the University of California at Berkeley. The name of the University
        !             8:  * may not be used to endorse or promote products derived from this
        !             9:  * software without specific prior written permission. This software
        !            10:  * is provided ``as is'' without express or implied warranty.
        !            11:  */
        !            12: 
        !            13: #ifdef notdef
        !            14: static char sccsid[] = "@(#)aux.c      5.7 (Berkeley) 2/18/88";
        !            15: #endif /* notdef */
        !            16: 
        !            17: #include "rcv.h"
        !            18: #include <sys/stat.h>
        !            19: 
        !            20: /*
        !            21:  * Mail -- a mail program
        !            22:  *
        !            23:  * Auxiliary functions.
        !            24:  */
        !            25: 
        !            26: /*
        !            27:  * Return a pointer to a dynamic copy of the argument.
        !            28:  */
        !            29: 
        !            30: char *
        !            31: savestr(str)
        !            32:        char *str;
        !            33: {
        !            34:        register char *cp, *cp2, *top;
        !            35: 
        !            36:        for (cp = str; *cp; cp++)
        !            37:                ;
        !            38:        top = salloc(cp-str + 1);
        !            39:        if (top == NOSTR)
        !            40:                return(NOSTR);
        !            41:        for (cp = str, cp2 = top; *cp; cp++)
        !            42:                *cp2++ = *cp;
        !            43:        *cp2 = 0;
        !            44:        return(top);
        !            45: }
        !            46: 
        !            47: /*
        !            48:  * Announce a fatal error and die.
        !            49:  */
        !            50: 
        !            51: /*VARARGS1*/
        !            52: panic(fmt, a, b)
        !            53:        char *fmt;
        !            54: {
        !            55:        fprintf(stderr, "panic: ");
        !            56:        fprintf(stderr, fmt, a, b);
        !            57:        putc('\n', stderr);
        !            58:        exit(1);
        !            59: }
        !            60: 
        !            61: /*
        !            62:  * Touch the named message by setting its MTOUCH flag.
        !            63:  * Touched messages have the effect of not being sent
        !            64:  * back to the system mailbox on exit.
        !            65:  */
        !            66: 
        !            67: touch(mesg)
        !            68: {
        !            69:        register struct message *mp;
        !            70: 
        !            71:        if (mesg < 1 || mesg > msgCount)
        !            72:                return;
        !            73:        mp = &message[mesg-1];
        !            74:        mp->m_flag |= MTOUCH;
        !            75:        if ((mp->m_flag & MREAD) == 0)
        !            76:                mp->m_flag |= MREAD|MSTATUS;
        !            77: }
        !            78: 
        !            79: /*
        !            80:  * Test to see if the passed file name is a directory.
        !            81:  * Return true if it is.
        !            82:  */
        !            83: 
        !            84: isdir(name)
        !            85:        char name[];
        !            86: {
        !            87:        struct stat sbuf;
        !            88: 
        !            89:        if (stat(name, &sbuf) < 0)
        !            90:                return(0);
        !            91:        return((sbuf.st_mode & S_IFMT) == S_IFDIR);
        !            92: }
        !            93: 
        !            94: /*
        !            95:  * Count the number of arguments in the given string raw list.
        !            96:  */
        !            97: 
        !            98: argcount(argv)
        !            99:        char **argv;
        !           100: {
        !           101:        register char **ap;
        !           102: 
        !           103:        for (ap = argv; *ap++ != NOSTR;)
        !           104:                ;       
        !           105:        return ap - argv - 1;
        !           106: }
        !           107: 
        !           108: /*
        !           109:  * Return the desired header line from the passed message
        !           110:  * pointer (or NOSTR if the desired header field is not available).
        !           111:  */
        !           112: 
        !           113: char *
        !           114: hfield(field, mp)
        !           115:        char field[];
        !           116:        struct message *mp;
        !           117: {
        !           118:        register FILE *ibuf;
        !           119:        char linebuf[LINESIZE];
        !           120:        register int lc;
        !           121:        register char *hfield;
        !           122:        char *colon;
        !           123: 
        !           124:        ibuf = setinput(mp);
        !           125:        if ((lc = mp->m_lines - 1) < 0)
        !           126:                return NOSTR;
        !           127:        if (readline(ibuf, linebuf) < 0)
        !           128:                return NOSTR;
        !           129:        while (lc > 0) {
        !           130:                if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
        !           131:                        return NOSTR;
        !           132:                if (hfield = ishfield(linebuf, colon, field))
        !           133:                        return savestr(hfield);
        !           134:        }
        !           135:        return NOSTR;
        !           136: }
        !           137: 
        !           138: /*
        !           139:  * Return the next header field found in the given message.
        !           140:  * Return >= 0 if something found, < 0 elsewise.
        !           141:  * "colon" is set to point to the colon in the header.
        !           142:  * Must deal with \ continuations & other such fraud.
        !           143:  */
        !           144: 
        !           145: gethfield(f, linebuf, rem, colon)
        !           146:        register FILE *f;
        !           147:        char linebuf[];
        !           148:        register int rem;
        !           149:        char **colon;
        !           150: {
        !           151:        char line2[LINESIZE];
        !           152:        register char *cp, *cp2;
        !           153:        register int c;
        !           154: 
        !           155:        for (;;) {
        !           156:                if (--rem < 0)
        !           157:                        return -1;
        !           158:                if ((c = readline(f, linebuf)) <= 0)
        !           159:                        return -1;
        !           160:                for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':';
        !           161:                     cp++)
        !           162:                        ;
        !           163:                if (*cp != ':' || cp == linebuf)
        !           164:                        continue;
        !           165:                /*
        !           166:                 * I guess we got a headline.
        !           167:                 * Handle wraparounding
        !           168:                 */
        !           169:                *colon = cp;
        !           170:                cp = linebuf + c;
        !           171:                for (;;) {
        !           172:                        while (--cp >= linebuf && (*cp == ' ' || *cp == '\t'))
        !           173:                                ;
        !           174:                        cp++;
        !           175:                        if (rem <= 0)
        !           176:                                break;
        !           177:                        ungetc(c = getc(f), f);
        !           178:                        if (c != ' ' && c != '\t')
        !           179:                                break;
        !           180:                        if ((c = readline(f, line2)) < 0)
        !           181:                                break;
        !           182:                        rem--;
        !           183:                        for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++)
        !           184:                                ;
        !           185:                        c -= cp2 - line2;
        !           186:                        if (cp + c >= linebuf + LINESIZE - 2)
        !           187:                                break;
        !           188:                        *cp++ = ' ';
        !           189:                        bcopy(cp2, cp, c);
        !           190:                        cp += c;
        !           191:                }
        !           192:                *cp = 0;
        !           193:                return rem;
        !           194:        }
        !           195:        /* NOTREACHED */
        !           196: }
        !           197: 
        !           198: /*
        !           199:  * Check whether the passed line is a header line of
        !           200:  * the desired breed.  Return the field body, or 0.
        !           201:  */
        !           202: 
        !           203: char*
        !           204: ishfield(linebuf, colon, field)
        !           205:        char linebuf[], field[];
        !           206:        char *colon;
        !           207: {
        !           208:        register char *cp = colon;
        !           209: 
        !           210:        *cp = 0;
        !           211:        if (!icequal(linebuf, field)) {
        !           212:                *cp = ':';
        !           213:                return 0;
        !           214:        }
        !           215:        *cp = ':';
        !           216:        for (cp++; *cp == ' ' || *cp == '\t'; cp++)
        !           217:                ;
        !           218:        return cp;
        !           219: }
        !           220: 
        !           221: /*
        !           222:  * Compare two strings, ignoring case.
        !           223:  */
        !           224: 
        !           225: icequal(s1, s2)
        !           226:        register char *s1, *s2;
        !           227: {
        !           228:        register c1, c2;
        !           229: 
        !           230:        for (;;) {
        !           231:                if ((c1 = (unsigned char)*s1++) !=
        !           232:                    (c2 = (unsigned char)*s2++)) {
        !           233:                        if (isupper(c1))
        !           234:                                c1 = tolower(c1);
        !           235:                        if (c1 != c2)
        !           236:                                return 0;
        !           237:                }
        !           238:                if (c1 == 0)
        !           239:                        return 1;
        !           240:        }
        !           241:        /*NOTREACHED*/
        !           242: }
        !           243: 
        !           244: /*
        !           245:  * Copy a string, lowercasing it as we go.
        !           246:  */
        !           247: istrcpy(dest, src)
        !           248:        register char *dest, *src;
        !           249: {
        !           250: 
        !           251:        do {
        !           252:                if (isupper(*src))
        !           253:                        *dest++ = tolower(*src);
        !           254:                else
        !           255:                        *dest++ = *src;
        !           256:        } while (*src++ != 0);
        !           257: }
        !           258: 
        !           259: /*
        !           260:  * The following code deals with input stacking to do source
        !           261:  * commands.  All but the current file pointer are saved on
        !           262:  * the stack.
        !           263:  */
        !           264: 
        !           265: static int     ssp = -1;               /* Top of file stack */
        !           266: struct sstack {
        !           267:        FILE    *s_file;                /* File we were in. */
        !           268:        int     s_cond;                 /* Saved state of conditionals */
        !           269:        int     s_loading;              /* Loading .mailrc, etc. */
        !           270: } sstack[NOFILE];
        !           271: 
        !           272: /*
        !           273:  * Pushdown current input file and switch to a new one.
        !           274:  * Set the global flag "sourcing" so that others will realize
        !           275:  * that they are no longer reading from a tty (in all probability).
        !           276:  */
        !           277: 
        !           278: source(name)
        !           279:        char name[];
        !           280: {
        !           281:        register FILE *fi;
        !           282:        register char *cp;
        !           283: 
        !           284:        if ((cp = expand(name)) == NOSTR)
        !           285:                return(1);
        !           286:        if ((fi = fopen(cp, "r")) == NULL) {
        !           287:                perror(cp);
        !           288:                return(1);
        !           289:        }
        !           290:        if (ssp >= NOFILE - 2) {
        !           291:                printf("Too much \"sourcing\" going on.\n");
        !           292:                fclose(fi);
        !           293:                return(1);
        !           294:        }
        !           295:        sstack[++ssp].s_file = input;
        !           296:        sstack[ssp].s_cond = cond;
        !           297:        sstack[ssp].s_loading = loading;
        !           298:        loading = 0;
        !           299:        cond = CANY;
        !           300:        input = fi;
        !           301:        sourcing++;
        !           302:        return(0);
        !           303: }
        !           304: 
        !           305: /*
        !           306:  * Pop the current input back to the previous level.
        !           307:  * Update the "sourcing" flag as appropriate.
        !           308:  */
        !           309: 
        !           310: unstack()
        !           311: {
        !           312:        if (ssp < 0) {
        !           313:                printf("\"Source\" stack over-pop.\n");
        !           314:                sourcing = 0;
        !           315:                return(1);
        !           316:        }
        !           317:        fclose(input);
        !           318:        if (cond != CANY)
        !           319:                printf("Unmatched \"if\"\n");
        !           320:        cond = sstack[ssp].s_cond;
        !           321:        loading = sstack[ssp].s_loading;
        !           322:        input = sstack[ssp--].s_file;
        !           323:        if (ssp < 0)
        !           324:                sourcing = loading;
        !           325:        return(0);
        !           326: }
        !           327: 
        !           328: /*
        !           329:  * Touch the indicated file.
        !           330:  * This is nifty for the shell.
        !           331:  * If we have the utime() system call, this is better served
        !           332:  * by using that, since it will work for empty files.
        !           333:  * On non-utime systems, we must sleep a second, then read.
        !           334:  */
        !           335: 
        !           336: alter(name)
        !           337:        char name[];
        !           338: {
        !           339: #ifdef UTIME
        !           340:        struct stat statb;
        !           341:        long time();
        !           342:        time_t time_p[2];
        !           343: #else
        !           344:        register int pid, f;
        !           345:        char w;
        !           346: #endif UTIME
        !           347: 
        !           348: #ifdef UTIME
        !           349:        if (stat(name, &statb) < 0)
        !           350:                return;
        !           351:        time_p[0] = time((long *) 0) + 1;
        !           352:        time_p[1] = statb.st_mtime;
        !           353:        utime(name, time_p);
        !           354: #else
        !           355:        sleep(1);
        !           356:        if ((f = open(name, 0)) < 0)
        !           357:                return;
        !           358:        read(f, &w, 1);
        !           359:        exit(0);
        !           360: #endif
        !           361: }
        !           362: 
        !           363: /*
        !           364:  * Examine the passed line buffer and
        !           365:  * return true if it is all blanks and tabs.
        !           366:  */
        !           367: 
        !           368: blankline(linebuf)
        !           369:        char linebuf[];
        !           370: {
        !           371:        register char *cp;
        !           372: 
        !           373:        for (cp = linebuf; *cp; cp++)
        !           374:                if (*cp != ' ' && *cp != '\t')
        !           375:                        return(0);
        !           376:        return(1);
        !           377: }
        !           378: 
        !           379: /*
        !           380:  * Get sender's name from this message.  If the message has
        !           381:  * a bunch of arpanet stuff in it, we may have to skin the name
        !           382:  * before returning it.
        !           383:  */
        !           384: char *
        !           385: nameof(mp, reptype)
        !           386:        register struct message *mp;
        !           387: {
        !           388:        register char *cp, *cp2;
        !           389: 
        !           390:        cp = skin(name1(mp, reptype));
        !           391:        if (reptype != 0 || charcount(cp, '!') < 2)
        !           392:                return(cp);
        !           393:        cp2 = rindex(cp, '!');
        !           394:        cp2--;
        !           395:        while (cp2 > cp && *cp2 != '!')
        !           396:                cp2--;
        !           397:        if (*cp2 == '!')
        !           398:                return(cp2 + 1);
        !           399:        return(cp);
        !           400: }
        !           401: 
        !           402: /*
        !           403:  * Skin an arpa net address according to the RFC 822 interpretation
        !           404:  * of "host-phrase."
        !           405:  */
        !           406: char *
        !           407: skin(name)
        !           408:        char *name;
        !           409: {
        !           410:        register int c;
        !           411:        register char *cp, *cp2;
        !           412:        char *bufend;
        !           413:        int gotlt, lastsp;
        !           414:        char nbuf[BUFSIZ];
        !           415:        int nesting;
        !           416: 
        !           417:        if (name == NOSTR)
        !           418:                return(NOSTR);
        !           419:        if (index(name, '(') == NOSTR && index(name, '<') == NOSTR
        !           420:            && index(name, ' ') == NOSTR)
        !           421:                return(name);
        !           422:        gotlt = 0;
        !           423:        lastsp = 0;
        !           424:        bufend = nbuf;
        !           425:        for (cp = name, cp2 = bufend; c = *cp++; ) {
        !           426:                switch (c) {
        !           427:                case '(':
        !           428:                        /*
        !           429:                         * Start of a "comment".
        !           430:                         * Ignore it.
        !           431:                         */
        !           432:                        nesting = 1;
        !           433:                        while ((c = *cp) != 0) {
        !           434:                                cp++;
        !           435:                                switch (c) {
        !           436:                                case '\\':
        !           437:                                        if (*cp == 0)
        !           438:                                                goto outcm;
        !           439:                                        cp++;
        !           440:                                        break;
        !           441:                                case '(':
        !           442:                                        nesting++;
        !           443:                                        break;
        !           444: 
        !           445:                                case ')':
        !           446:                                        --nesting;
        !           447:                                        break;
        !           448:                                }
        !           449: 
        !           450:                                if (nesting <= 0)
        !           451:                                        break;
        !           452:                        }
        !           453:                outcm:
        !           454:                        lastsp = 0;
        !           455:                        break;
        !           456: 
        !           457:                case '"':
        !           458:                        /*
        !           459:                         * Start of a "quoted-string".
        !           460:                         * Copy it in its entirety.
        !           461:                         */
        !           462:                        while ((c = *cp) != 0) {
        !           463:                                cp++;
        !           464:                                switch (c) {
        !           465:                                case '\\':
        !           466:                                        if ((c = *cp) == 0)
        !           467:                                                goto outqs;
        !           468:                                        cp++;
        !           469:                                        break;
        !           470:                                case '"':
        !           471:                                        goto outqs;
        !           472:                                }
        !           473:                                *cp2++ = c;
        !           474:                        }
        !           475:                outqs:
        !           476:                        lastsp = 0;
        !           477:                        break;
        !           478: 
        !           479:                case ' ':
        !           480:                        if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ')
        !           481:                                cp += 3, *cp2++ = '@';
        !           482:                        else
        !           483:                        if (cp[0] == '@' && cp[1] == ' ')
        !           484:                                cp += 2, *cp2++ = '@';
        !           485:                        else
        !           486:                                lastsp = 1;
        !           487:                        break;
        !           488: 
        !           489:                case '<':
        !           490:                        cp2 = bufend;
        !           491:                        gotlt++;
        !           492:                        lastsp = 0;
        !           493:                        break;
        !           494: 
        !           495:                case '>':
        !           496:                        if (gotlt) {
        !           497:                                gotlt = 0;
        !           498:                                while (*cp != ',' && *cp != 0)
        !           499:                                        cp++;
        !           500:                                if (*cp == 0 )
        !           501:                                        goto done;
        !           502:                                *cp2++ = ',';
        !           503:                                *cp2++ = ' ';
        !           504:                                bufend = cp2;
        !           505:                                break;
        !           506:                        }
        !           507: 
        !           508:                        /* Fall into . . . */
        !           509: 
        !           510:                default:
        !           511:                        if (lastsp) {
        !           512:                                lastsp = 0;
        !           513:                                *cp2++ = ' ';
        !           514:                        }
        !           515:                        *cp2++ = c;
        !           516:                        break;
        !           517:                }
        !           518:        }
        !           519: done:
        !           520:        *cp2 = 0;
        !           521: 
        !           522:        return(savestr(nbuf));
        !           523: }
        !           524: 
        !           525: /*
        !           526:  * Fetch the sender's name from the passed message.
        !           527:  * Reptype can be
        !           528:  *     0 -- get sender's name for display purposes
        !           529:  *     1 -- get sender's name for reply
        !           530:  *     2 -- get sender's name for Reply
        !           531:  */
        !           532: 
        !           533: char *
        !           534: name1(mp, reptype)
        !           535:        register struct message *mp;
        !           536: {
        !           537:        char namebuf[LINESIZE];
        !           538:        char linebuf[LINESIZE];
        !           539:        register char *cp, *cp2;
        !           540:        register FILE *ibuf;
        !           541:        int first = 1;
        !           542: 
        !           543:        if ((cp = hfield("from", mp)) != NOSTR)
        !           544:                return cp;
        !           545:        if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR)
        !           546:                return cp;
        !           547:        ibuf = setinput(mp);
        !           548:        namebuf[0] = 0;
        !           549:        if (readline(ibuf, linebuf) < 0)
        !           550:                return(savestr(namebuf));
        !           551: newname:
        !           552:        for (cp = linebuf; *cp && *cp != ' '; cp++)
        !           553:                ;
        !           554:        for (; *cp == ' ' || *cp == '\t'; cp++)
        !           555:                ;
        !           556:        for (cp2 = &namebuf[strlen(namebuf)];
        !           557:             *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;)
        !           558:                *cp2++ = *cp++;
        !           559:        *cp2 = '\0';
        !           560:        if (readline(ibuf, linebuf) < 0)
        !           561:                return(savestr(namebuf));
        !           562:        if ((cp = index(linebuf, 'F')) == NULL)
        !           563:                return(savestr(namebuf));
        !           564:        if (strncmp(cp, "From", 4) != 0)
        !           565:                return(savestr(namebuf));
        !           566:        while ((cp = index(cp, 'r')) != NULL) {
        !           567:                if (strncmp(cp, "remote", 6) == 0) {
        !           568:                        if ((cp = index(cp, 'f')) == NULL)
        !           569:                                break;
        !           570:                        if (strncmp(cp, "from", 4) != 0)
        !           571:                                break;
        !           572:                        if ((cp = index(cp, ' ')) == NULL)
        !           573:                                break;
        !           574:                        cp++;
        !           575:                        if (first) {
        !           576:                                strcpy(namebuf, cp);
        !           577:                                first = 0;
        !           578:                        } else
        !           579:                                strcpy(rindex(namebuf, '!')+1, cp);
        !           580:                        strcat(namebuf, "!");
        !           581:                        goto newname;
        !           582:                }
        !           583:                cp++;
        !           584:        }
        !           585:        return(savestr(namebuf));
        !           586: }
        !           587: 
        !           588: /*
        !           589:  * Count the occurances of c in str
        !           590:  */
        !           591: charcount(str, c)
        !           592:        char *str;
        !           593: {
        !           594:        register char *cp;
        !           595:        register int i;
        !           596: 
        !           597:        for (i = 0, cp = str; *cp; cp++)
        !           598:                if (*cp == c)
        !           599:                        i++;
        !           600:        return(i);
        !           601: }
        !           602: 
        !           603: /*
        !           604:  * Are any of the characters in the two strings the same?
        !           605:  */
        !           606: 
        !           607: anyof(s1, s2)
        !           608:        register char *s1, *s2;
        !           609: {
        !           610: 
        !           611:        while (*s1)
        !           612:                if (index(s2, *s1++))
        !           613:                        return 1;
        !           614:        return 0;
        !           615: }
        !           616: 
        !           617: /*
        !           618:  * Convert c to upper case
        !           619:  */
        !           620: 
        !           621: raise(c)
        !           622:        register c;
        !           623: {
        !           624: 
        !           625:        if (islower(c))
        !           626:                return toupper(c);
        !           627:        return c;
        !           628: }
        !           629: 
        !           630: /*
        !           631:  * Copy s1 to s2, return pointer to null in s2.
        !           632:  */
        !           633: 
        !           634: char *
        !           635: copy(s1, s2)
        !           636:        register char *s1, *s2;
        !           637: {
        !           638: 
        !           639:        while (*s2++ = *s1++)
        !           640:                ;
        !           641:        return s2 - 1;
        !           642: }
        !           643: 
        !           644: /*
        !           645:  * Add a single character onto a string.
        !           646:  */
        !           647: 
        !           648: stradd(str, c)
        !           649:        register char *str;
        !           650: {
        !           651: 
        !           652:        while (*str++)
        !           653:                ;
        !           654:        str[-1] = c;
        !           655:        *str = 0;
        !           656: }
        !           657: 
        !           658: /*
        !           659:  * See if the given header field is supposed to be ignored.
        !           660:  */
        !           661: isign(field)
        !           662:        char *field;
        !           663: {
        !           664:        char realfld[BUFSIZ];
        !           665: 
        !           666:        /*
        !           667:         * Lower-case the string, so that "Status" and "status"
        !           668:         * will hash to the same place.
        !           669:         */
        !           670:        istrcpy(realfld, field);
        !           671:        if (nretained > 0)
        !           672:                return (!member(realfld, retain));
        !           673:        else
        !           674:                return (member(realfld, ignore));
        !           675: }
        !           676: 
        !           677: member(realfield, table)
        !           678:        register char *realfield;
        !           679:        struct ignore **table;
        !           680: {
        !           681:        register struct ignore *igp;
        !           682: 
        !           683:        for (igp = table[hash(realfield)]; igp != 0; igp = igp->i_link)
        !           684:                if (*igp->i_field == *realfield &&
        !           685:                    equal(igp->i_field, realfield))
        !           686:                        return (1);
        !           687:        return (0);
        !           688: }

unix.superglobalmegacorp.com

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