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
cmatch defined in line 480; used 2 times
copy defined in line 570; used 3 times
copyin defined in line 406; used 5 times
dohead defined in line 153; used 1 times
  • in line 72
fail defined in line 352; used 2 times
gword defined in line 261; used 2 times
isdate defined in line 464; used 1 times
ishead defined in line 325; used 1 times
  • in line 69
isname defined in line 428; used 2 times
main defined in line 40; never used
nextword defined in line 538; used 4 times
nullgets defined in line 125; used 1 times
  • in line 68
parse defined in line 365; used 2 times
raise defined in line 606; never used
rev defined in line 281; used 2 times
savestr defined in line 304; used 1 times
  • in line 34
word defined in line 230; used 16 times

Defined variables

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

Defined struct's

headline defined in line 28; used 6 times

Defined macros

C defined in line 457; used 4 times
D defined in line 455; used 22 times
L defined in line 453; used 8 times
N defined in line 458; never used
NOSTR defined in line 37; used 13 times
O defined in line 456; used 2 times
S defined in line 454; used 9 times
SENDMAIL defined in line 26; used 6 times
U defined in line 459; used 7 times
UUCP defined in line 38; used 3 times
Last modified: 1985-11-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4322
Valid CSS Valid XHTML 1.0 Strict