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

Defined functions

any defined in line 848; used 3 times
chkfrom defined in line 419; used 1 times
chkindex defined in line 440; used 1 times
dodeliver defined in line 693; used 2 times
file defined in line 504; used 2 times
findheader defined in line 394; used 3 times
fixaddr defined in line 790; used 2 times
main defined in line 65; never used
peekc defined in line 866; used 4 times
process defined in line 192; used 1 times
redistribute defined in line 567; used 2 times
reply defined in line 726; used 2 times
streq defined in line 822; used 1 times
substr defined in line 837; used 4 times

Defined variables

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

Defined struct's

header defined in line 171; used 12 times

Defined macros

BODY defined in line 150; used 1 times
BUGS_HOME defined in line 35; used 3 times
BUGS_NAME defined in line 32; used 4 times
CC_I defined in line 168; never used
DATE_I defined in line 164; used 2 times
EOM defined in line 148; used 6 times
FIX defined in line 169; never used
FLD defined in line 149; used 2 times
FROM defined in line 159; used 1 times
FROM_I defined in line 160; used 2 times
H_FND defined in line 157; used 4 times
H_HDR defined in line 156; used 7 times
H_REQ defined in line 154; used 5 times
H_SAV defined in line 155; used 9 times
INDEX defined in line 162; used 1 times
INDEX_I defined in line 163; used 1 times
MSGID_I defined in line 165; used 2 times
REPLYTO_I defined in line 166; used 2 times
SUBJECT_I defined in line 161; used 9 times
TO_I defined in line 167; never used
UNIXTOMH defined in line 39; used 2 times
Last modified: 1996-10-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6681
Valid CSS Valid XHTML 1.0 Strict