Annotation of 43BSD/ucb/sendbug/unixtomh.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char SccsId[] = "@(#)unixtomh.c 1.1     5/16/85";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * This program copies the mail file in standard unix format
        !             7:  * given as $1 to the file $2 in Rand Message Handler format.
        !             8:  * The change made is to bracket each message with a line
        !             9:  * containing 4 control-A's and to split the From line into
        !            10:  * a From: field and a Date: field, with the date in Arpanet
        !            11:  * standard format.
        !            12:  *
        !            13:  * This program is designed to be called from the rand mh program
        !            14:  * ``inc''
        !            15:  *
        !            16:  * Set SENDMAIL if you are running sendmail -- this guarantees that
        !            17:  * From: and Date: lines will appear already, and will put the info
        !            18:  * in the UNIX-From line into a Received-From: field.
        !            19:  */
        !            20: 
        !            21: #include <stdio.h>
        !            22: #include <sys/types.h>
        !            23: #include <sys/timeb.h>
        !            24: #include <ctype.h>
        !            25: 
        !            26: #define SENDMAIL
        !            27: 
        !            28: struct headline {
        !            29:        char    *l_from;        /* The name of the sender */
        !            30:        char    *l_tty;         /* His tty string (if any) */
        !            31:        char    *l_date;        /* The entire date string */
        !            32: };
        !            33: 
        !            34: char *savestr(), *copyin(), *copy(), *nextword(), *calloc();
        !            35: char *index();
        !            36: 
        !            37: #define        NOSTR           ((char *) 0)
        !            38: #define        UUCP                    /* Undo strange uucp naming */
        !            39: 
        !            40: main(argc, argv)
        !            41:        char **argv;
        !            42: {
        !            43:        char linebuf[BUFSIZ];
        !            44:        register int maybe;
        !            45:        register FILE *inf, *outf;
        !            46:        int inhdr, infld;
        !            47: 
        !            48:        if (argc > 3) {
        !            49:                fprintf(stderr, "Usage: unixtomh name1 name2\n");
        !            50:                exit(1);
        !            51:        }
        !            52:        outf = inf = NULL;
        !            53:        if (argc < 3)
        !            54:                outf = stdout;
        !            55:        if (argc < 2)
        !            56:                inf = stdin;
        !            57:        if (inf == NULL && (inf = fopen(argv[1], "r")) == NULL) {
        !            58:                perror(argv[1]);
        !            59:                exit(1);
        !            60:        }
        !            61:        if (outf == NULL && (outf = fopen(argv[2], "w")) == NULL) {
        !            62:                perror(argv[2]);
        !            63:                exit(1);
        !            64:        }
        !            65:        maybe = 1;
        !            66:        inhdr = 0;
        !            67:        infld = 0;
        !            68:        while (nullgets(linebuf, BUFSIZ, inf) > 0) {
        !            69:                if (maybe && ishead(linebuf)) {
        !            70:                        fputs("\1\1\1\1\n", outf);
        !            71:                        inhdr++;
        !            72:                        dohead(linebuf, inf, outf);
        !            73:                        continue;
        !            74:                }
        !            75:                if (strlen(linebuf) == 0) {
        !            76:                        maybe = 1;
        !            77:                        inhdr = 0;
        !            78:                        infld = 0;
        !            79:                        putc('\n', outf);
        !            80:                        continue;
        !            81:                }
        !            82:                else
        !            83:                        maybe = 0;
        !            84: #ifndef SENDMAIL
        !            85:                if (inhdr && strcmpn(linebuf, "Date: ", 6) == 0)
        !            86:                        continue;
        !            87:                if (inhdr && strcmpn(linebuf, "From: ", 6) == 0)
        !            88:                        continue;
        !            89: #endif SENDMAIL
        !            90:                if (infld && isspace(linebuf[0])) {
        !            91:                        fputs(linebuf, outf);
        !            92:                        putc('\n', outf);
        !            93:                        continue;
        !            94:                }
        !            95:                if (inhdr && !isspace(linebuf[0])) {
        !            96:                        char *colp, *sp;
        !            97: 
        !            98:                        colp = index(linebuf, ':');
        !            99:                        sp = index(linebuf, ' ');
        !           100:                        if (colp == NOSTR || sp == NOSTR || sp < colp) {
        !           101:                                putc('\n', outf);
        !           102:                                inhdr = 0;
        !           103:                        }
        !           104:                        else
        !           105:                                infld = 1;
        !           106:                }
        !           107:                fputs(linebuf, outf);
        !           108:                putc('\n', outf);
        !           109:        }
        !           110:        fputs("\1\1\1\1\n", outf);
        !           111:        fflush(outf);
        !           112:        if (ferror(outf)) {
        !           113:                fprintf(stderr, "unixtomh: write: ");
        !           114:                perror(argv[2]);
        !           115:                exit(1);
        !           116:        }
        !           117:        exit(0);
        !           118: }
        !           119: 
        !           120: /*
        !           121:  * Get a line from the given file descriptor, don't return the
        !           122:  * terminating newline.
        !           123:  */
        !           124: 
        !           125: nullgets(linebuf, sz, file)
        !           126:        char linebuf[];
        !           127:        register FILE *file;
        !           128: {
        !           129:        register char *cp;
        !           130:        register int c, cnt;
        !           131: 
        !           132:        cp = linebuf;
        !           133:        cnt = sz;
        !           134:        do {
        !           135:                if (--cnt <= 0) {
        !           136:                        *cp = 0;
        !           137:                        return(1);
        !           138:                }
        !           139:                c = getc(file);
        !           140:                *cp++ = c;
        !           141:        } while (c != EOF && c != '\n');
        !           142:        if (c == EOF && cp == linebuf+1)
        !           143:                return(0);
        !           144:        *--cp = 0;
        !           145:        return(1);
        !           146: }
        !           147: 
        !           148: /*
        !           149:  * Output the fields extracted from the From line --
        !           150:  * From: and Date:  Untangle UUCP stuff if appropriate.
        !           151:  */
        !           152: 
        !           153: dohead(line, infile, outfile)
        !           154:        char line[];
        !           155:        register FILE *infile, *outfile;
        !           156: {
        !           157:        register char *cp;
        !           158:        struct headline hl;
        !           159:        char parbuf[BUFSIZ];
        !           160: #ifdef UUCP
        !           161:        char *word();
        !           162:        char namebuf[BUFSIZ];
        !           163:        char linebuf[BUFSIZ];
        !           164:        int first;
        !           165:        long curoff;
        !           166: #endif UUCP
        !           167: 
        !           168:        parse(line, &hl, parbuf);
        !           169: #ifndef SENDMAIL
        !           170:        putdate(hl.l_date, outfile);
        !           171: #endif SENDMAIL
        !           172: #ifdef UUCP
        !           173:        if (strcmp(hl.l_from, "uucp") == 0) {
        !           174:                strcpy(namebuf, "");
        !           175:                first = 1;
        !           176:                for (;;) {
        !           177:                        curoff = ftell(infile);
        !           178:                        if (fgets(linebuf, BUFSIZ, infile) == NULL)
        !           179:                                break;
        !           180:                        if (strcmp(word(1, linebuf), ">From") != 0)
        !           181:                                break;
        !           182:                        if (strcmp(word(-3, linebuf), "remote") != 0)
        !           183:                                break;
        !           184:                        if (strcmp(word(-2, linebuf), "from") != 0)
        !           185:                                break;
        !           186:                        if (first) {
        !           187:                                strcpy(namebuf, word(-1, linebuf));
        !           188:                                strcat(namebuf, "!");
        !           189:                                strcat(namebuf, word(2, linebuf));
        !           190:                                first = 0;
        !           191:                        }
        !           192:                        else {
        !           193:                                strcpy(rindex(namebuf, '!')+1,
        !           194:                                    word(-1, linebuf));
        !           195:                                strcat(namebuf, "!");
        !           196:                                strcat(namebuf, word(2, linebuf));
        !           197:                        }
        !           198:                }
        !           199:                fseek(infile, curoff, 0);
        !           200: #ifdef SENDMAIL
        !           201:                if (!first)
        !           202:                        fprintf(outfile, "Return-Path: <%s>\n", namebuf);
        !           203: #else SENDMAIL
        !           204:                if (first)
        !           205:                        fprintf(outfile, "From: uucp\n");
        !           206:                else
        !           207:                        fprintf(outfile, "From: %s\n", namebuf);
        !           208: #endif SENDMAIL
        !           209:                return;
        !           210:        }
        !           211: #endif UUCP
        !           212: #ifdef SENDMAIL
        !           213:        if (hl.l_from[0] == '<')
        !           214:                fprintf(outfile, "Return-Path: %s\n", hl.l_from);
        !           215:        else
        !           216:                fprintf(outfile, "Return-Path: <%s>\n", hl.l_from);
        !           217: #else SENDMAIL
        !           218:        fprintf(outfile, "From: %s\n", hl.l_from);
        !           219: #endif SENDMAIL
        !           220: }
        !           221: 
        !           222: #ifdef UUCP
        !           223: 
        !           224: /*
        !           225:  * Return liberal word i from the given string.
        !           226:  * The words are numbered 1, 2, 3, . . .  from the left
        !           227:  * and -1, -2, . . . from the right.
        !           228:  */
        !           229: 
        !           230: char *
        !           231: word(index, str)
        !           232:        char str[];
        !           233: {
        !           234:        register char *cp;
        !           235:        char *secbuf;
        !           236:        register int c;
        !           237:        static char retbuf[100];
        !           238:        char *gword();
        !           239: 
        !           240:        cp = str;
        !           241:        if ((c = index) > 0) {
        !           242:                while (c-- > 0)
        !           243:                        cp = gword(cp, retbuf);
        !           244:                return(retbuf);
        !           245:        }
        !           246:        if (c == 0)
        !           247:                return("");
        !           248:        secbuf = (char *) alloca(strlen(str) + 1);
        !           249:        strcpy(secbuf, str);
        !           250:        rev(secbuf);
        !           251:        cp = word(-index, secbuf);
        !           252:        rev(cp);
        !           253:        return(cp);
        !           254: }
        !           255: 
        !           256: /*
        !           257:  * Skip leading blanks in the string, return
        !           258:  * first liberal word collected.
        !           259:  */
        !           260: 
        !           261: char *
        !           262: gword(cp, buf)
        !           263:        register char *cp;
        !           264:        char buf[];
        !           265: {
        !           266:        register char *cp2;
        !           267: 
        !           268:        cp2 = buf;
        !           269:        while (*cp && any(*cp, " \t\n"))
        !           270:                cp++;
        !           271:        while (*cp && !any(*cp, " \t\n"))
        !           272:                *cp2++ = *cp++;
        !           273:        *cp2 = 0;
        !           274:        return(cp);
        !           275: }
        !           276: 
        !           277: /*
        !           278:  * Reverse the characters in the string in place
        !           279:  */
        !           280: 
        !           281: rev(str)
        !           282:        char str[];
        !           283: {
        !           284:        register char *cpl, *cpr;
        !           285:        register int s;
        !           286: 
        !           287:        s = strlen(str);
        !           288:        cpl = str;
        !           289:        cpr = &str[s-1];
        !           290:        while (cpl < cpr) {
        !           291:                s = *cpl;
        !           292:                *cpl++ = *cpr;
        !           293:                *cpr-- = s;
        !           294:        }
        !           295: }
        !           296: #endif UUCP
        !           297: 
        !           298: /*
        !           299:  * Save a string in dynamic space.
        !           300:  * This little goodie is needed for
        !           301:  * a headline detector in head.c
        !           302:  */
        !           303: 
        !           304: char *
        !           305: savestr(str)
        !           306:        char str[];
        !           307: {
        !           308:        register char *top;
        !           309: 
        !           310:        top = calloc(strlen(str) + 1, 1);
        !           311:        if (top == NOSTR) {
        !           312:                fprintf(stderr, "unixtomh:  Ran out of memory\n");
        !           313:                exit(1);
        !           314:        }
        !           315:        copy(str, top);
        !           316:        return(top);
        !           317: }
        !           318: 
        !           319: /*
        !           320:  * See if the passed line buffer is a mail header.
        !           321:  * Return true if yes.  Note the extreme pains to
        !           322:  * accomodate all funny formats.
        !           323:  */
        !           324: 
        !           325: ishead(linebuf)
        !           326:        char linebuf[];
        !           327: {
        !           328:        register char *cp;
        !           329:        struct headline hl;
        !           330:        char parbuf[BUFSIZ];
        !           331: 
        !           332:        cp = linebuf;
        !           333:        if (!isname("From ", cp, 5))
        !           334:                return(0);
        !           335:        parse(cp, &hl, parbuf);
        !           336:        if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
        !           337:                fail(linebuf, "No from or date field");
        !           338:                return(0);
        !           339:        }
        !           340:        if (!isdate(hl.l_date)) {
        !           341:                fail(linebuf, "Date field not legal date");
        !           342:                return(0);
        !           343:        }
        !           344:        
        !           345:        /*
        !           346:         * I guess we got it!
        !           347:         */
        !           348: 
        !           349:        return(1);
        !           350: }
        !           351: 
        !           352: fail(linebuf, reason)
        !           353:        char linebuf[], reason[];
        !           354: {
        !           355:        return;
        !           356: }
        !           357: 
        !           358: /*
        !           359:  * Split a headline into its useful components.
        !           360:  * Copy the line into dynamic string space, then set
        !           361:  * pointers into the copied line in the passed headline
        !           362:  * structure.  Actually, it scans.
        !           363:  */
        !           364: 
        !           365: parse(line, hl, pbuf)
        !           366:        char line[], pbuf[];
        !           367:        struct headline *hl;
        !           368: {
        !           369:        register char *cp, *dp;
        !           370:        char *sp;
        !           371:        char word[BUFSIZ];
        !           372: 
        !           373:        hl->l_from = NOSTR;
        !           374:        hl->l_tty = NOSTR;
        !           375:        hl->l_date = NOSTR;
        !           376:        cp = line;
        !           377:        sp = pbuf;
        !           378: 
        !           379:        /*
        !           380:         * Skip the first "word" of the line, which should be "From"
        !           381:         * anyway.
        !           382:         */
        !           383: 
        !           384:        cp = nextword(cp, word);
        !           385:        dp = nextword(cp, word);
        !           386:        if (word[0] != 0)
        !           387:                hl->l_from = copyin(word, &sp);
        !           388:        if (isname(dp, "tty", 3)) {
        !           389:                cp = nextword(dp, word);
        !           390:                hl->l_tty = copyin(word, &sp);
        !           391:                if (cp != NOSTR)
        !           392:                        hl->l_date = copyin(cp, &sp);
        !           393:        }
        !           394:        else
        !           395:                if (dp != NOSTR)
        !           396:                        hl->l_date = copyin(dp, &sp);
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * Copy the string on the left into the string on the right
        !           401:  * and bump the right (reference) string pointer by the length.
        !           402:  * Thus, dynamically allocate space in the right string, copying
        !           403:  * the left string into it.
        !           404:  */
        !           405: 
        !           406: char *
        !           407: copyin(src, space)
        !           408:        char src[];
        !           409:        char **space;
        !           410: {
        !           411:        register char *cp, *top;
        !           412:        register int s;
        !           413: 
        !           414:        s = strlen(src);
        !           415:        cp = *space;
        !           416:        top = cp;
        !           417:        strcpy(cp, src);
        !           418:        cp += s + 1;
        !           419:        *space = cp;
        !           420:        return(top);
        !           421: }
        !           422: 
        !           423: /*
        !           424:  * See if the two passed strings agree in the first n characters.
        !           425:  * Return true if they do, gnu.
        !           426:  */
        !           427: 
        !           428: isname(as1, as2, acount)
        !           429:        char *as1, *as2;
        !           430: {
        !           431:        register char *s1, *s2;
        !           432:        register count;
        !           433: 
        !           434:        s1 = as1;
        !           435:        s2 = as2;
        !           436:        count = acount;
        !           437:        if (count > 0)
        !           438:                do
        !           439:                        if (*s1++ != *s2++)
        !           440:                                return(0);
        !           441:                while (--count);
        !           442:        return(1);
        !           443: }
        !           444: 
        !           445: /*
        !           446:  * Test to see if the passed string is a ctime(3) generated
        !           447:  * date string as documented in the manual.  The template
        !           448:  * below is used as the criterion of correctness.
        !           449:  * Also, we check for a possible trailing time zone using
        !           450:  * the auxtype template.
        !           451:  */
        !           452: 
        !           453: #define        L       1               /* A lower case char */
        !           454: #define        S       2               /* A space */
        !           455: #define        D       3               /* A digit */
        !           456: #define        O       4               /* An optional digit or space */
        !           457: #define        C       5               /* A colon */
        !           458: #define        N       6               /* A new line */
        !           459: #define U      7               /* An upper case char */
        !           460: 
        !           461: char ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
        !           462: char tmztypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
        !           463: 
        !           464: isdate(date)
        !           465:        char date[];
        !           466: {
        !           467:        register char *cp;
        !           468: 
        !           469:        cp = date;
        !           470:        if (cmatch(cp, ctypes))
        !           471:                return(1);
        !           472:        return(cmatch(cp, tmztypes));
        !           473: }
        !           474: 
        !           475: /*
        !           476:  * Match the given string against the given template.
        !           477:  * Return 1 if they match, 0 if they don't
        !           478:  */
        !           479: 
        !           480: cmatch(str, temp)
        !           481:        char str[], temp[];
        !           482: {
        !           483:        register char *cp, *tp;
        !           484:        register int c;
        !           485: 
        !           486:        cp = str;
        !           487:        tp = temp;
        !           488:        while (*cp != '\0' && *tp != 0) {
        !           489:                c = *cp++;
        !           490:                switch (*tp++) {
        !           491:                case L:
        !           492:                        if (!islower(c))
        !           493:                                return(0);
        !           494:                        break;
        !           495: 
        !           496:                case S:
        !           497:                        if (c != ' ')
        !           498:                                return(0);
        !           499:                        break;
        !           500: 
        !           501:                case D:
        !           502:                        if (!isdigit(c))
        !           503:                                return(0);
        !           504:                        break;
        !           505: 
        !           506:                case O:
        !           507:                        if (c != ' ' && !isdigit(c))
        !           508:                                return(0);
        !           509:                        break;
        !           510: 
        !           511:                case C:
        !           512:                        if (c != ':')
        !           513:                                return(0);
        !           514:                        break;
        !           515: 
        !           516:                case N:
        !           517:                        if (c != '\n')
        !           518:                                return(0);
        !           519:                        break;
        !           520: 
        !           521:                case U:
        !           522:                        if (!isupper(c))
        !           523:                                return(0);
        !           524:                        break;
        !           525:                }
        !           526:        }
        !           527:        if (*cp != '\0' || *tp != 0)
        !           528:                return(0);
        !           529:        return(1);
        !           530: }
        !           531: 
        !           532: /*
        !           533:  * Collect a liberal (space, tab delimited) word into the word buffer
        !           534:  * passed.  Also, return a pointer to the next word following that,
        !           535:  * or NOSTR if none follow.
        !           536:  */
        !           537: 
        !           538: char *
        !           539: nextword(wp, wbuf)
        !           540:        char wp[], wbuf[];
        !           541: {
        !           542:        register char *cp, *cp2;
        !           543: 
        !           544:        if ((cp = wp) == NOSTR) {
        !           545:                copy("", wbuf);
        !           546:                return(NOSTR);
        !           547:        }
        !           548:        cp2 = wbuf;
        !           549:        while (!any(*cp, " \t") && *cp != '\0')
        !           550:                if (*cp == '"') {
        !           551:                        *cp2++ = *cp++;
        !           552:                        while (*cp != '\0' && *cp != '"')
        !           553:                                *cp2++ = *cp++;
        !           554:                        if (*cp == '"')
        !           555:                                *cp2++ = *cp++;
        !           556:                } else
        !           557:                        *cp2++ = *cp++;
        !           558:        *cp2 = '\0';
        !           559:        while (any(*cp, " \t"))
        !           560:                cp++;
        !           561:        if (*cp == '\0')
        !           562:                return(NOSTR);
        !           563:        return(cp);
        !           564: }
        !           565: 
        !           566: /*
        !           567:  * Copy str1 to str2, return pointer to null in str2.
        !           568:  */
        !           569: 
        !           570: char *
        !           571: copy(str1, str2)
        !           572:        char *str1, *str2;
        !           573: {
        !           574:        register char *s1, *s2;
        !           575: 
        !           576:        s1 = str1;
        !           577:        s2 = str2;
        !           578:        while (*s1)
        !           579:                *s2++ = *s1++;
        !           580:        *s2 = 0;
        !           581:        return(s2);
        !           582: }
        !           583: 
        !           584: /*
        !           585:  * Is ch any of the characters in str?
        !           586:  */
        !           587: 
        !           588: any(ch, str)
        !           589:        char *str;
        !           590: {
        !           591:        register char *f;
        !           592:        register c;
        !           593: 
        !           594:        f = str;
        !           595:        c = ch;
        !           596:        while (*f)
        !           597:                if (c == *f++)
        !           598:                        return(1);
        !           599:        return(0);
        !           600: }
        !           601: 
        !           602: /*
        !           603:  * Convert lower case letters to upper case.
        !           604:  */
        !           605: 
        !           606: raise(c)
        !           607:        register int c;
        !           608: {
        !           609:        if (c >= 'a' && c <= 'z')
        !           610:                c += 'A' - 'a';
        !           611:        return(c);
        !           612: }

unix.superglobalmegacorp.com

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