# 2.11BSD#431 - /usr/src/ucb/sendbug/bugfiler.c

##### Functions

    any               X
    chkfrom           X
    chkindex          X
    dodeliver         X
    file              X
    findheader        X
    fixaddr           X
    main              X
    peekc             X
    process           X
    redistribute      X
    reply             X
    streq             X
    substr            X

##### Variables

    ackfile           X
    buf               X
    bugperson         X
    copyright         X
    debug             X
    disttmp           X
    draft             X
    errfile           X
    folder            X
    folder_prot       X
    headers           X
    logfile           X
    maildir           X
    msg_prot          X
    num               X
    redistfile        X
    sumfile           X
    tmpname           X

##### Macros

    BODY              X
    BUGS_HOME         X
    BUGS_NAME         X
    CC_I              X
    DATE_I            X
    EOM               X
    FIX               X
    FLD               X
    FROM              X
    FROM_I            X
    H_FND             X
    H_HDR             X
    H_REQ             X
    H_SAV             X
    INDEX             X
    INDEX_I           X
    MSGID_I           X
    REPLYTO_I         X
    SUBJECT_I         X
    TO_I              X
    UNIXTOMH          X

##### struct's

    header            X

       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

- in line 63, 592, 621

chkfrom defined in line 419; used 1 times

- in line 334

chkindex defined in line 440; used 1 times

- in line 337

dodeliver defined in line 693; used 2 times

- in line 684, 780

file defined in line 504; used 2 times

- in line 359, 368

findheader defined in line 394; used 3 times

- in line 190, 263, 311

fixaddr defined in line 790; used 2 times

- in line 62, 750

main defined in line 65; never used
peekc defined in line 866; used 4 times

- in line 218, 249, 278, 298

process defined in line 192; used 1 times

- in line 141

redistribute defined in line 567; used 2 times

- in line 360, 385

reply defined in line 726; used 2 times

- in line 358, 367

streq defined in line 822; used 1 times

- in line 405

substr defined in line 837; used 4 times

- in line 428-430(2), 455(2)

#### Defined variables

ackfile defined in line 43; used 1 times

- in line 367

buf defined in line 52; used 30 times

- in line 239-245(4), 262-266(5), 287, 293, 304-311(4), 405, 553-554(3), 696, 711-714(4), 771-777(6)

bugperson defined in line 41; used 3 times

- in line 101-106(3)

copyright defined in line 8; never used
debug defined in line 58; used 21 times

- in line 82, 98, 355, 401, 425, 447, 484, 514, 578, 587, 601, 609-614(2), 632, 666, 680, 700, 706, 712-716(2), 732

disttmp defined in line 50; used 5 times

- in line 606-610(3), 685-690(2)

draft defined in line 49; used 4 times

- in line 738-740(3), 781

errfile defined in line 44; used 1 times

- in line 358

folder defined in line 53; used 23 times

- in line 368, 376, 385, 460-463(2), 475(2), 485-489(2), 504-505(2), 515-523(5), 541, 567-568(2), 580, 596, 657, 663

folder_prot defined in line 56; used 1 times

- in line 521

headers defined in line 175; used 14 times

- in line 159-169(11), 205, 349, 404

logfile defined in line 46; used 1 times

- in line 99

maildir defined in line 42; used 4 times

- in line 96, 115-116(2), 523

msg_prot defined in line 55; used 3 times

- in line 89, 225, 549

num defined in line 54; used 13 times

- in line 360, 376, 385, 527, 533-541(4), 567-569(2), 580, 657, 663

redistfile defined in line 47; used 2 times

- in line 576, 588

sccsid defined in line 12; never used
sumfile defined in line 45; used 2 times

- in line 373-374(2)

tmpname defined in line 48; used 7 times

- in line 224-226(3), 342, 358-359(2), 368

#### Defined struct's

header defined in line 171; used 12 times

- in line 190-194(4), 394-399(4), 420(2), 441(2)

#### Defined macros

BODY defined in line 150; used 1 times

- in line 291

BUGS_HOME defined in line 35; used 3 times

- in line 34, 746-747(2)

BUGS_NAME defined in line 32; used 4 times

- in line 31, 428, 746-747(2)

CC_I defined in line 168; never used
DATE_I defined in line 164; used 2 times

- in line 763-765(2)

EOM defined in line 148; used 6 times

- in line 234, 252, 282, 299, 361, 386

FIX defined in line 169; never used
FLD defined in line 149; used 2 times

- in line 234, 407

FROM defined in line 159; used 1 times

- in line 334

FROM_I defined in line 160; used 2 times

- in line 358, 367

H_FND defined in line 157; used 4 times

- in line 206, 354, 409, 495

H_HDR defined in line 156; used 7 times

- in line 176-183(6), 407

H_REQ defined in line 154; used 5 times

- in line 176-178(3), 184, 354

H_SAV defined in line 155; used 9 times

- in line 176-183(8), 318

INDEX defined in line 162; used 1 times

- in line 336

INDEX_I defined in line 163; used 1 times

- in line 377

MSGID_I defined in line 165; used 2 times

- in line 766-767(2)

REPLYTO_I defined in line 166; used 2 times

- in line 748-749(2)

SUBJECT_I defined in line 161; used 9 times

- in line 378, 653, 755-761(7)

TO_I defined in line 167; never used
UNIXTOMH defined in line 39; used 2 times

- in line 38, 133

Last modified: 1996-10-24 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3111 |