# 2.11BSD#431 - /usr/src/ucb/sendbug/unixtomh.c

##### Functions

    any               X
    cmatch            X
    copy              X
    copyin            X
    dohead            X
    fail              X
    gword             X
    isdate            X
    ishead            X
    isname            X
    main              X
    nextword          X
    nullgets          X
    parse             X
    raise             X
    rev               X
    savestr           X
    word              X

##### Variables

    ctypes            X
    tmztypes          X

##### Macros

    C                 X
    D                 X
    L                 X
    N                 X
    NOSTR             X
    O                 X
    S                 X
    SENDMAIL          X
    U                 X
    UUCP              X

##### struct's

    headline          X

       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: }

#### Defined functions

any defined in line 588; used 4 times

- in line 269-271(2), 549, 559

cmatch defined in line 480; used 2 times

- in line 470-472(2)

copy defined in line 570; used 3 times

- in line 34, 315, 545

copyin defined in line 406; used 5 times

- in line 34, 387-396(4)

dohead defined in line 153; used 1 times

- in line 72

fail defined in line 352; used 2 times

- in line 337-341(2)

gword defined in line 261; used 2 times

- in line 238-243(2)

isdate defined in line 464; used 1 times

- in line 340

ishead defined in line 325; used 1 times

- in line 69

isname defined in line 428; used 2 times

- in line 333, 388

main defined in line 40; never used
nextword defined in line 538; used 4 times

- in line 34, 384-389(3)

nullgets defined in line 125; used 1 times

- in line 68

parse defined in line 365; used 2 times

- in line 168, 335

raise defined in line 606; never used
rev defined in line 281; used 2 times

- in line 250-252(2)

savestr defined in line 304; used 1 times

- in line 34

word defined in line 230; used 16 times

- in line 161, 180-196(7), 251, 371, 384-390(6)

#### Defined variables

SccsId defined in line 2; never used
ctypes defined in line 461; used 1 times

- in line 470

tmztypes defined in line 462; used 1 times

- in line 472

#### Defined struct's

headline defined in line 28; used 6 times

- in line 158(2), 329(2), 367(2)

#### Defined macros

C defined in line 457; used 4 times

- in line 461-462(4)

D defined in line 455; used 22 times

- in line 461-462(22)

L defined in line 453; used 8 times

- in line 461-462(8)

N defined in line 458; never used
NOSTR defined in line 37; used 13 times

- in line 100(2), 311, 336(2), 373-375(3), 391-395(2), 544-546(2), 562

O defined in line 456; used 2 times

- in line 461-462(2)

S defined in line 454; used 9 times

- in line 461-462(9)

SENDMAIL defined in line 26; used 6 times

- in line 84, 169, 200-203(2), 212-217(2)

U defined in line 459; used 7 times

- in line 461-462(7)

UUCP defined in line 38; used 3 times

- in line 160, 172, 222

Last modified: 1985-11-05 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1856 |