|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.