|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)bugfiler.c 5.5 (Berkeley) 86/05/20"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * Bug report processing program. ! 19: * It is designed to be invoked by alias(5) ! 20: * and to be compatible with mh. ! 21: */ ! 22: ! 23: #include <stdio.h> ! 24: #include <ctype.h> ! 25: #include <signal.h> ! 26: #include <pwd.h> ! 27: ! 28: #include <sys/types.h> ! 29: #include <sys/stat.h> ! 30: #include <sys/dir.h> ! 31: ! 32: #ifndef BUGS_NAME ! 33: #define BUGS_NAME "4bsd-bugs" ! 34: #endif ! 35: #ifndef BUGS_HOME ! 36: #define BUGS_HOME "@ucbvax.BERKELEY.EDU" ! 37: #endif ! 38: #define MAILCMD "/usr/lib/sendmail -i -t" ! 39: ! 40: #ifndef UNIXTOMH ! 41: #define UNIXTOMH "/usr/lib/unixtomh" ! 42: #endif ! 43: char *bugperson = "bugs"; ! 44: char *maildir = "mail"; ! 45: char ackfile[] = ".ack"; ! 46: char errfile[] = ".format"; ! 47: char sumfile[] = "summary"; ! 48: char logfile[] = "errors/log"; ! 49: char redistfile[] = ".redist"; ! 50: char tmpname[] = "BfXXXXXX"; ! 51: char draft[] = "RpXXXXXX"; ! 52: char disttmp[] = "RcXXXXXX"; ! 53: ! 54: char buf[8192]; ! 55: char folder[MAXNAMLEN]; ! 56: int num; ! 57: int msg_prot = 0640; ! 58: int folder_prot = 0750; ! 59: ! 60: int debug; ! 61: ! 62: char *index(); ! 63: char *rindex(); ! 64: char *fixaddr(); ! 65: char *any(); ! 66: ! 67: main(argc, argv) ! 68: char *argv[]; ! 69: { ! 70: register char *cp; ! 71: register int n; ! 72: int pfd[2]; ! 73: ! 74: if (argc > 4) { ! 75: usage: ! 76: fprintf(stderr, "Usage: bugfiler [-d] [-mmsg_mode] [maildir]\n"); ! 77: exit(1); ! 78: } ! 79: while (--argc > 0) { ! 80: cp = *++argv; ! 81: if (*cp == '-') ! 82: switch (cp[1]) { ! 83: case 'd': ! 84: debug++; ! 85: break; ! 86: ! 87: case 'm': /* set message protection */ ! 88: n = 0; ! 89: for (cp += 2; *cp >= '0' && *cp <= '7'; ) ! 90: n = (n << 3) + (*cp++ - '0'); ! 91: msg_prot = n & 0777; ! 92: break; ! 93: ! 94: default: ! 95: goto usage; ! 96: } ! 97: else ! 98: maildir = cp; ! 99: } ! 100: if (!debug) ! 101: freopen(logfile, "a", stderr); ! 102: ! 103: if (bugperson) { ! 104: struct passwd *pwd = getpwnam(bugperson); ! 105: ! 106: if (pwd == NULL) { ! 107: fprintf(stderr, "%s: bugs person is unknown\n", ! 108: bugperson); ! 109: exit(1); ! 110: } ! 111: if (chdir(pwd->pw_dir) < 0) { ! 112: fprintf(stderr, "can't chdir to %s\n", pwd->pw_dir); ! 113: exit(1); ! 114: } ! 115: setuid(pwd->pw_uid); ! 116: } ! 117: if (chdir(maildir) < 0) { ! 118: fprintf(stderr, "can't chdir to %s\n", maildir); ! 119: exit(1); ! 120: } ! 121: umask(0); ! 122: ! 123: #ifdef UNIXCOMP ! 124: /* ! 125: * Convert UNIX style mail to mh style by filtering stdin through ! 126: * unixtomh. ! 127: */ ! 128: if (pipe(pfd) >= 0) { ! 129: while ((n = fork()) == -1) ! 130: sleep(5); ! 131: if (n == 0) { ! 132: close(pfd[0]); ! 133: dup2(pfd[1], 1); ! 134: close(pfd[1]); ! 135: execl(UNIXTOMH, "unixtomh", 0); ! 136: _exit(127); ! 137: } ! 138: close(pfd[1]); ! 139: dup2(pfd[0], 0); ! 140: close(pfd[0]); ! 141: } ! 142: #endif ! 143: while (process()) ! 144: ; ! 145: exit(0); ! 146: } ! 147: ! 148: /* states */ ! 149: ! 150: #define EOM 0 /* End of message seen */ ! 151: #define FLD 1 /* Looking for header lines */ ! 152: #define BODY 2 /* Looking for message body lines */ ! 153: ! 154: /* defines used for tag attributes */ ! 155: ! 156: #define H_REQ 01 ! 157: #define H_SAV 02 ! 158: #define H_HDR 04 ! 159: #define H_FND 010 ! 160: ! 161: #define FROM &headers[0] ! 162: #define FROM_I headers[0].h_info ! 163: #define SUBJECT_I headers[1].h_info ! 164: #define INDEX &headers[2] ! 165: #define INDEX_I headers[2].h_info ! 166: #define DATE_I headers[3].h_info ! 167: #define MSGID_I headers[4].h_info ! 168: #define REPLYTO_I headers[5].h_info ! 169: #define TO_I headers[6].h_info ! 170: #define CC_I headers[7].h_info ! 171: #define FIX headers[10] ! 172: ! 173: struct header { ! 174: char *h_tag; ! 175: int h_flags; ! 176: char *h_info; ! 177: } headers[] = { ! 178: "From", H_REQ|H_SAV|H_HDR, 0, ! 179: "Subject", H_REQ|H_SAV, 0, ! 180: "Index", H_REQ|H_SAV, 0, ! 181: "Date", H_SAV|H_HDR, 0, ! 182: "Message-Id", H_SAV|H_HDR, 0, ! 183: "Reply-To", H_SAV|H_HDR, 0, ! 184: "To", H_SAV|H_HDR, 0, ! 185: "Cc", H_SAV|H_HDR, 0, ! 186: "Description", H_REQ, 0, ! 187: "Repeat-By", 0, 0, ! 188: "Fix", 0, 0, ! 189: 0, 0, 0, ! 190: }; ! 191: ! 192: struct header *findheader(); ! 193: ! 194: process() ! 195: { ! 196: register struct header *hp; ! 197: register char *cp; ! 198: register int c; ! 199: char *info; ! 200: int state, tmp, no_reply = 0; ! 201: FILE *tfp, *fs; ! 202: ! 203: /* ! 204: * Insure all headers are in a consistent ! 205: * state. Anything left there is free'd. ! 206: */ ! 207: for (hp = headers; hp->h_tag; hp++) { ! 208: hp->h_flags &= ~H_FND; ! 209: if (hp->h_info) { ! 210: free(hp->h_info); ! 211: hp->h_info = 0; ! 212: } ! 213: } ! 214: /* ! 215: * Read the report and make a copy. Must conform to RFC822 and ! 216: * be of the form... <tag>: <info> ! 217: * Note that the input is expected to be in mh mail format ! 218: * (i.e., messages are separated by lines of ^A's). ! 219: */ ! 220: while ((c = getchar()) == '\001' && peekc(stdin) == '\001') ! 221: while (getchar() != '\n') ! 222: ; ! 223: if (c == EOF) ! 224: return(0); /* all done */ ! 225: ! 226: mktemp(tmpname); ! 227: if ((tmp = creat(tmpname, msg_prot)) < 0) { ! 228: fprintf(stderr, "cannot create %s\n", tmpname); ! 229: exit(1); ! 230: } ! 231: if ((tfp = fdopen(tmp, "w")) == NULL) { ! 232: fprintf(stderr, "cannot fdopen temp file\n"); ! 233: exit(1); ! 234: } ! 235: ! 236: for (state = FLD; state != EOF && state != EOM; c = getchar()) { ! 237: switch (state) { ! 238: case FLD: ! 239: if (c == '\n' || c == '-') ! 240: goto body; ! 241: for (cp = buf; c != ':'; c = getchar()) { ! 242: if (cp < buf+sizeof(buf)-1 && c != '\n' && c != EOF) { ! 243: *cp++ = c; ! 244: continue; ! 245: } ! 246: *cp = '\0'; ! 247: fputs(buf, tfp); ! 248: state = EOF; ! 249: while (c != EOF) { ! 250: if (c == '\n') ! 251: if ((tmp = peekc(stdin)) == EOF) ! 252: break; ! 253: else if (tmp == '\001') { ! 254: state = EOM; ! 255: break; ! 256: } ! 257: putc(c, tfp); ! 258: c = getchar(); ! 259: } ! 260: fclose(tfp); ! 261: goto badfmt; ! 262: } ! 263: *cp = '\0'; ! 264: fprintf(tfp, "%s:", buf); ! 265: hp = findheader(buf, state); ! 266: ! 267: for (cp = buf; ; ) { ! 268: if (cp >= buf+sizeof(buf)-1) { ! 269: fprintf(stderr, "field truncated\n"); ! 270: while ((c = getchar()) != EOF && c != '\n') ! 271: putc(c, tfp); ! 272: } ! 273: if ((c = getchar()) == EOF) { ! 274: state = EOF; ! 275: break; ! 276: } ! 277: putc(c, tfp); ! 278: *cp++ = c; ! 279: if (c == '\n') ! 280: if ((c = peekc(stdin)) != ' ' && c != '\t') { ! 281: if (c == EOF) ! 282: state = EOF; ! 283: else if (c == '\001') ! 284: state = EOM; ! 285: break; ! 286: } ! 287: } ! 288: *cp = '\0'; ! 289: cp = buf; ! 290: break; ! 291: ! 292: body: ! 293: state = BODY; ! 294: case BODY: ! 295: for (cp = buf; ; c = getchar()) { ! 296: if (c == EOF) { ! 297: state = EOF; ! 298: break; ! 299: } ! 300: if (c == '\001' && peekc(stdin) == '\001') { ! 301: state = EOM; ! 302: break; ! 303: } ! 304: putc(c, tfp); ! 305: *cp++ = c; ! 306: if (cp >= buf+sizeof(buf)-1 || c == '\n') ! 307: break; ! 308: } ! 309: *cp = '\0'; ! 310: if ((cp = index(buf, ':')) == NULL) ! 311: continue; ! 312: *cp++ = '\0'; ! 313: hp = findheader(buf, state); ! 314: } ! 315: ! 316: /* ! 317: * Don't save the info if the header wasn't found, we don't ! 318: * care about the info, or the header is repeated. ! 319: */ ! 320: if (hp == NULL || !(hp->h_flags & H_SAV) || hp->h_info) ! 321: continue; ! 322: while (isspace(*cp)) ! 323: cp++; ! 324: if (*cp) { ! 325: info = cp; ! 326: while (*cp++); ! 327: cp--; ! 328: while (isspace(cp[-1])) ! 329: *--cp = '\0'; ! 330: hp->h_info = (char *) malloc(strlen(info) + 1); ! 331: if (hp->h_info == NULL) { ! 332: fprintf(stderr, "ran out of memory\n"); ! 333: continue; ! 334: } ! 335: strcpy(hp->h_info, info); ! 336: if (hp == FROM && chkfrom(hp) < 0) ! 337: no_reply = 1; ! 338: if (hp == INDEX) ! 339: chkindex(hp); ! 340: } ! 341: } ! 342: fclose(tfp); ! 343: if (no_reply) { ! 344: unlink(tmpname); ! 345: exit(0); ! 346: } ! 347: /* ! 348: * Verify all the required pieces of information ! 349: * are present. ! 350: */ ! 351: for (hp = headers; hp->h_tag; hp++) { ! 352: /* ! 353: * Mail the bug report back to the sender with a note ! 354: * explaining they must conform to the specification. ! 355: */ ! 356: if ((hp->h_flags & H_REQ) && !(hp->h_flags & H_FND)) { ! 357: if (debug) ! 358: printf("Missing %s\n", hp->h_tag); ! 359: badfmt: ! 360: reply(FROM_I, errfile, tmpname); ! 361: file(tmpname, "errors"); ! 362: redistribute("errors", num); ! 363: return(state == EOM); ! 364: } ! 365: } ! 366: /* ! 367: * Acknowledge receipt. ! 368: */ ! 369: reply(FROM_I, ackfile, (char *)0); ! 370: file(tmpname, folder); ! 371: /* ! 372: * Append information about the new bug report ! 373: * to the summary file. ! 374: */ ! 375: if ((fs = fopen(sumfile, "a")) == NULL) ! 376: fprintf(stderr, "Can't open %s\n", sumfile); ! 377: else { ! 378: fprintf(fs, "%14.14s/%-3d ", folder, num); ! 379: fprintf(fs, "%-51.51s Recv\n", INDEX_I); ! 380: fprintf(fs, "\t\t %-51.51s\n", SUBJECT_I); ! 381: } ! 382: fclose(fs); ! 383: /* ! 384: * Check redistribution list and, if members, ! 385: * mail a copy of the bug report to these people. ! 386: */ ! 387: redistribute(folder, num); ! 388: return(state == EOM); ! 389: } ! 390: ! 391: /* ! 392: * Lookup the string in the list of headers and return a pointer ! 393: * to the entry or NULL. ! 394: */ ! 395: ! 396: struct header * ! 397: findheader(name, state) ! 398: char *name; ! 399: int state; ! 400: { ! 401: register struct header *hp; ! 402: ! 403: if (debug) ! 404: printf("findheader(%s, %d)\n", name, state); ! 405: ! 406: for (hp = headers; hp->h_tag; hp++) { ! 407: if (!streq(hp->h_tag, buf)) ! 408: continue; ! 409: if ((hp->h_flags & H_HDR) && state != FLD) ! 410: continue; ! 411: hp->h_flags |= H_FND; ! 412: return(hp); ! 413: } ! 414: return(NULL); ! 415: } ! 416: ! 417: /* ! 418: * Check the FROM line to eliminate loops. ! 419: */ ! 420: ! 421: chkfrom(hp) ! 422: struct header *hp; ! 423: { ! 424: register char *cp1, *cp2; ! 425: register char c; ! 426: ! 427: if (debug) ! 428: printf("chkfrom(%s)\n", hp->h_info); ! 429: ! 430: if (substr(hp->h_info, BUGS_NAME)) ! 431: return(-1); ! 432: if (substr(hp->h_info, "MAILER-DAEMON")) ! 433: return(-1); ! 434: return(0); ! 435: } ! 436: ! 437: /* ! 438: * Check the format of the Index information. ! 439: * A side effect is to set the name of the folder if all is well. ! 440: */ ! 441: ! 442: chkindex(hp) ! 443: struct header *hp; ! 444: { ! 445: register char *cp1, *cp2; ! 446: register char c; ! 447: struct stat stbuf; ! 448: ! 449: if (debug) ! 450: printf("chkindex(%s)\n", hp->h_info); ! 451: /* ! 452: * Strip of leading "/", ".", "usr/", or "src/". ! 453: */ ! 454: cp1 = hp->h_info; ! 455: while (*cp1 == '/' || *cp1 == '.') ! 456: cp1++; ! 457: while (substr(cp1, "usr/") || substr(cp1, "src/")) ! 458: cp1 += 4; ! 459: /* ! 460: * Read the folder name and remove it from the index line. ! 461: */ ! 462: for (cp2 = folder; ;) { ! 463: switch (c = *cp1++) { ! 464: case '/': ! 465: if (cp2 == folder) ! 466: continue; ! 467: break; ! 468: case '\0': ! 469: cp1--; ! 470: break; ! 471: case ' ': ! 472: case '\t': ! 473: while (isspace(*cp1)) ! 474: cp1++; ! 475: break; ! 476: default: ! 477: if (cp2 < folder+sizeof(folder)-1) ! 478: *cp2++ = c; ! 479: continue; ! 480: } ! 481: *cp2 = '\0'; ! 482: for (cp2 = hp->h_info; *cp2++ = *cp1++; ) ! 483: ; ! 484: break; ! 485: } ! 486: if (debug) ! 487: printf("folder = %s\n", folder); ! 488: /* ! 489: * Check to make sure we have a valid folder name ! 490: */ ! 491: if (stat(folder, &stbuf) == 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR) ! 492: return; ! 493: /* ! 494: * The Index line is not in the correct format so clear ! 495: * the H_FND flag to mail back the correct format. ! 496: */ ! 497: hp->h_flags &= ~H_FND; ! 498: } ! 499: ! 500: /* ! 501: * Move or copy the file msg to the folder (directory). ! 502: * As a side effect, num is set to the number under which ! 503: * the message is filed in folder. ! 504: */ ! 505: ! 506: file(fname, folder) ! 507: char *fname, *folder; ! 508: { ! 509: register char *cp; ! 510: register int n; ! 511: char msgname[MAXNAMLEN*2+2]; ! 512: struct stat stbuf; ! 513: DIR *dirp; ! 514: struct direct *d; ! 515: ! 516: if (debug) ! 517: printf("file(%s, %s)\n", fname, folder); ! 518: /* ! 519: * Get the next number to use by finding the last message number ! 520: * in folder and adding one. ! 521: */ ! 522: if ((dirp = opendir(folder)) == NULL) { ! 523: (void) mkdir(folder, folder_prot); ! 524: if ((dirp = opendir(folder)) == NULL) { ! 525: fprintf(stderr, "Cannot open %s/%s\n", maildir, folder); ! 526: return; ! 527: } ! 528: } ! 529: num = 0; ! 530: while ((d = readdir(dirp)) != NULL) { ! 531: cp = d->d_name; ! 532: n = 0; ! 533: while (isdigit(*cp)) ! 534: n = n * 10 + (*cp++ - '0'); ! 535: if (*cp == '\0' && n > num) ! 536: num = n; ! 537: } ! 538: closedir(dirp); ! 539: num++; ! 540: /* ! 541: * Create the destination file "folder/num" and copy fname to it. ! 542: */ ! 543: sprintf(msgname, "%s/%d", folder, num); ! 544: if (link(fname, msgname) < 0) { ! 545: int fin, fout; ! 546: ! 547: if ((fin = open(fname, 0)) < 0) { ! 548: fprintf(stderr, "cannot open %s\n", fname); ! 549: return; ! 550: } ! 551: if ((fout = creat(msgname, msg_prot)) < 0) { ! 552: fprintf(stderr, "cannot create %s\n", msgname); ! 553: return; ! 554: } ! 555: while ((n = read(fin, buf, sizeof(buf))) > 0) ! 556: write(fout, buf, n); ! 557: close(fin); ! 558: close(fout); ! 559: } ! 560: unlink(fname); ! 561: } ! 562: ! 563: /* ! 564: * Redistribute a bug report to those people indicated ! 565: * in the redistribution list file. Perhaps should also ! 566: * annotate bug report with this information for future ! 567: * reference? ! 568: */ ! 569: redistribute(folder, num) ! 570: char *folder; ! 571: int num; ! 572: { ! 573: FILE *fredist, *fbug, *ftemp; ! 574: char line[BUFSIZ], bug[2 * MAXNAMLEN + 1]; ! 575: register char *cp; ! 576: int redistcnt, continuation, first; ! 577: ! 578: fredist = fopen(redistfile, "r"); ! 579: if (fredist == NULL) { ! 580: if (debug) ! 581: printf("redistribute(%s, %d), no distribution list\n", ! 582: folder, num); ! 583: return; ! 584: } ! 585: continuation = 0; ! 586: first = 1; ! 587: redistcnt = 0; ! 588: while (fgets(line, sizeof (line) - 1, fredist) != NULL) { ! 589: if (debug) ! 590: printf("%s: %s", redistfile, line); ! 591: if (continuation && index(line, '\\')) ! 592: continue; ! 593: continuation = 0; ! 594: cp = any(line, " \t"); ! 595: if (cp == NULL) ! 596: continue; ! 597: *cp++ = '\0'; ! 598: if (strcmp(folder, line) == 0) ! 599: goto found; ! 600: if (index(cp, '\\')) ! 601: continuation = 1; ! 602: } ! 603: if (debug) ! 604: printf("no redistribution list found\n"); ! 605: fclose(fredist); ! 606: return; ! 607: found: ! 608: mktemp(disttmp); ! 609: ftemp = fopen(disttmp, "w+r"); ! 610: if (ftemp == NULL) { ! 611: if (debug) ! 612: printf("%s: couldn't create\n", disttmp); ! 613: return; ! 614: } ! 615: again: ! 616: if (debug) ! 617: printf("redistribution list %s", cp); ! 618: while (cp) { ! 619: char *user, terminator; ! 620: ! 621: while (*cp && (*cp == ' ' || *cp == '\t' || *cp == ',')) ! 622: cp++; ! 623: user = cp, cp = any(cp, ", \t\n\\"); ! 624: if (cp) { ! 625: terminator = *cp; ! 626: *cp++ = '\0'; ! 627: if (terminator == '\n') ! 628: cp = 0; ! 629: if (terminator == '\\') ! 630: continuation++; ! 631: } ! 632: if (*user == '\0') ! 633: continue; ! 634: if (debug) ! 635: printf("copy to %s\n", user); ! 636: if (first) { ! 637: fprintf(ftemp, "Resent-To: %s", user); ! 638: first = 0; ! 639: } else ! 640: fprintf(ftemp, ", %s", user); ! 641: redistcnt++; ! 642: } ! 643: if (!first) ! 644: putc('\n', ftemp); ! 645: if (continuation) { ! 646: first = 1; ! 647: continuation = 0; ! 648: cp = line; ! 649: if (fgets(line, sizeof (line) - 1, fredist)) ! 650: goto again; ! 651: } ! 652: fclose(fredist); ! 653: if (redistcnt == 0) ! 654: goto cleanup; ! 655: if (! SUBJECT_I) { ! 656: fprintf(ftemp, "Subject: "); ! 657: fprintf(ftemp, "Untitled bug report\n"); ! 658: } ! 659: fprintf(ftemp, "Folder: %s/%d\n", folder, num); ! 660: /* ! 661: * Create copy of bug report. Perhaps we should ! 662: * truncate large messages and just give people ! 663: * a pointer to the original? ! 664: */ ! 665: sprintf(bug, "%s/%d", folder, num); ! 666: fbug = fopen(bug, "r"); ! 667: if (fbug == NULL) { ! 668: if (debug) ! 669: printf("%s: disappeared?\n", bug); ! 670: goto cleanup; ! 671: } ! 672: first = 1; ! 673: while (fgets(line, sizeof (line) - 1, fbug)) { ! 674: /* first blank line indicates start of mesg */ ! 675: if (first && line[0] == '\n') { ! 676: first = 0; ! 677: } ! 678: fputs(line, ftemp); ! 679: } ! 680: fclose(fbug); ! 681: if (first) { ! 682: if (debug) ! 683: printf("empty bug report?\n"); ! 684: goto cleanup; ! 685: } ! 686: if (dodeliver(ftemp)) ! 687: unlink(disttmp); ! 688: fclose(ftemp); ! 689: return; ! 690: cleanup: ! 691: fclose(ftemp); ! 692: unlink(disttmp); ! 693: } ! 694: ! 695: dodeliver(fd) ! 696: FILE *fd; ! 697: { ! 698: char buf[BUFSIZ], cmd[BUFSIZ]; ! 699: FILE *pf, *popen(); ! 700: ! 701: strcpy(cmd, MAILCMD); ! 702: if (debug) { ! 703: strcat(cmd, " -v"); ! 704: printf("dodeliver \"%s\"\n", cmd); ! 705: } ! 706: pf = popen(cmd, "w"); ! 707: if (pf == NULL) { ! 708: if (debug) ! 709: printf("dodeliver, \"%s\" failed\n", cmd); ! 710: return (0); ! 711: } ! 712: rewind(fd); ! 713: while (fgets(buf, sizeof (buf) - 1, fd)) { ! 714: if (debug) ! 715: printf("%s", buf); ! 716: (void) fputs(buf, pf); ! 717: } ! 718: if (debug) ! 719: printf("EOF\n"); ! 720: (void) pclose(pf); ! 721: return (1); ! 722: } ! 723: ! 724: /* ! 725: * Mail file1 and file2 back to the sender. ! 726: */ ! 727: ! 728: reply(to, file1, file2) ! 729: char *to, *file1, *file2; ! 730: { ! 731: int pfd[2], in, w; ! 732: FILE *fout; ! 733: ! 734: if (debug) ! 735: printf("reply(%s, %s, %s)\n", to, file1, file2); ! 736: ! 737: /* ! 738: * Create a temporary file to put the message in. ! 739: */ ! 740: mktemp(draft); ! 741: if ((fout = fopen(draft, "w+r")) == NULL) { ! 742: fprintf(stderr, "Can't create %s\n", draft); ! 743: return; ! 744: } ! 745: /* ! 746: * Output the proper header information. ! 747: */ ! 748: fprintf(fout, "Reply-To: %s%s\n", BUGS_NAME, BUGS_HOME); ! 749: fprintf(fout, "From: %s%s (Bugs Bunny)\n", BUGS_NAME, BUGS_HOME); ! 750: if (REPLYTO_I != NULL) ! 751: to = REPLYTO_I; ! 752: if ((to = fixaddr(to)) == 0) { ! 753: fprintf(stderr, "No one to reply to\n"); ! 754: return; ! 755: } ! 756: fprintf(fout, "To: %s\n", to); ! 757: if (SUBJECT_I) { ! 758: fprintf(fout, "Subject: "); ! 759: if ((SUBJECT_I[0] != 'R' && SUBJECT_I[0] != 'r') || ! 760: (SUBJECT_I[1] != 'E' && SUBJECT_I[1] != 'e') || ! 761: SUBJECT_I[2] != ':') ! 762: fprintf(fout, "Re: "); ! 763: fprintf(fout, "%s\n", SUBJECT_I); ! 764: } ! 765: if (DATE_I) { ! 766: fprintf(fout, "In-Acknowledgement-Of: Your message of "); ! 767: fprintf(fout, "%s.\n", DATE_I); ! 768: if (MSGID_I) ! 769: fprintf(fout, " %s\n", MSGID_I); ! 770: } ! 771: fprintf(fout, "\n"); ! 772: if ((in = open(file1, 0)) >= 0) { ! 773: while ((w = read(in, buf, sizeof(buf))) > 0) ! 774: fwrite(buf, 1, w, fout); ! 775: close(in); ! 776: } ! 777: if (file2 && (in = open(file2, 0)) >= 0) { ! 778: while ((w = read(in, buf, sizeof(buf))) > 0) ! 779: fwrite(buf, 1, w, fout); ! 780: close(in); ! 781: } ! 782: if (dodeliver(fout)) ! 783: unlink(draft); ! 784: fclose(fout); ! 785: } ! 786: ! 787: /* ! 788: * fix names like "xxx (something)" to "xxx" and ! 789: * "xxx <something>" to "something". ! 790: */ ! 791: ! 792: char * ! 793: fixaddr(text) ! 794: char *text; ! 795: { ! 796: register char *cp, *lp, c; ! 797: char *tp; ! 798: ! 799: if (!text) ! 800: return(0); ! 801: for (lp = cp = text; ; ) { ! 802: switch (c = *cp++) { ! 803: case '(': ! 804: while (*cp && *cp++ != ')'); ! 805: continue; ! 806: case '<': ! 807: lp = text; ! 808: case '>': ! 809: continue; ! 810: case '\0': ! 811: while (lp != text && (*lp == ' ' || *lp == '\t')) ! 812: lp--; ! 813: *lp = c; ! 814: return(text); ! 815: } ! 816: *lp++ = c; ! 817: } ! 818: } ! 819: ! 820: /* ! 821: * Compare two strings and convert any upper case letters to lower case. ! 822: */ ! 823: ! 824: streq(s1, s2) ! 825: register char *s1, *s2; ! 826: { ! 827: register int c; ! 828: ! 829: while (c = *s1++) ! 830: if ((c | 040) != (*s2++ | 040)) ! 831: return(0); ! 832: return(*s2 == '\0'); ! 833: } ! 834: ! 835: /* ! 836: * Return true if string s2 matches the first part of s1. ! 837: */ ! 838: ! 839: substr(s1, s2) ! 840: register char *s1, *s2; ! 841: { ! 842: register int c; ! 843: ! 844: while (c = *s2++) ! 845: if (c != *s1++) ! 846: return(0); ! 847: return(1); ! 848: } ! 849: ! 850: char * ! 851: any(cp, set) ! 852: register char *cp; ! 853: char *set; ! 854: { ! 855: register char *sp; ! 856: ! 857: if (cp == 0 || set == 0) ! 858: return (0); ! 859: while (*cp) { ! 860: for (sp = set; *sp; sp++) ! 861: if (*cp == *sp) ! 862: return (cp); ! 863: cp++; ! 864: } ! 865: return ((char *)0); ! 866: } ! 867: ! 868: peekc(fp) ! 869: FILE *fp; ! 870: { ! 871: register c; ! 872: ! 873: c = getc(fp); ! 874: ungetc(c, fp); ! 875: return(c); ! 876: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.