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