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

Defined functions

any defined in line 850; used 3 times
chkfrom defined in line 421; used 1 times
chkindex defined in line 442; used 1 times
dodeliver defined in line 695; used 2 times
file defined in line 506; used 2 times
findheader defined in line 396; used 3 times
fixaddr defined in line 792; used 2 times
main defined in line 67; never used
peekc defined in line 868; used 4 times
process defined in line 194; used 1 times
redistribute defined in line 569; used 2 times
reply defined in line 728; used 2 times
streq defined in line 824; used 1 times
substr defined in line 839; used 4 times

Defined variables

ackfile defined in line 45; used 1 times
buf defined in line 54; used 30 times
bugperson defined in line 43; used 3 times
copyright defined in line 8; never used
debug defined in line 60; used 21 times
disttmp defined in line 52; used 5 times
draft defined in line 51; used 4 times
errfile defined in line 46; used 1 times
folder defined in line 55; used 23 times
folder_prot defined in line 58; used 1 times
headers defined in line 177; used 14 times
logfile defined in line 48; used 1 times
maildir defined in line 44; used 4 times
msg_prot defined in line 57; used 3 times
num defined in line 56; used 13 times
redistfile defined in line 49; used 2 times
sccsid defined in line 14; never used
sumfile defined in line 47; used 2 times
tmpname defined in line 50; used 7 times

Defined struct's

header defined in line 173; used 12 times

Defined macros

BODY defined in line 152; used 1 times
BUGS_HOME defined in line 36; used 3 times
BUGS_NAME defined in line 33; used 4 times
CC_I defined in line 170; never used
DATE_I defined in line 166; used 2 times
EOM defined in line 150; used 6 times
FIX defined in line 171; never used
FLD defined in line 151; used 2 times
FROM defined in line 161; used 1 times
FROM_I defined in line 162; used 2 times
H_FND defined in line 159; used 4 times
H_HDR defined in line 158; used 7 times
H_REQ defined in line 156; used 5 times
H_SAV defined in line 157; used 9 times
INDEX defined in line 164; used 1 times
INDEX_I defined in line 165; used 1 times
MAILCMD defined in line 38; used 1 times
MSGID_I defined in line 167; used 2 times
REPLYTO_I defined in line 168; used 2 times
SUBJECT_I defined in line 163; used 9 times
TO_I defined in line 169; never used
UNIXTOMH defined in line 41; used 2 times
Last modified: 1986-05-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3238
Valid CSS Valid XHTML 1.0 Strict