Annotation of 43BSD/ucb/sendbug/bugfiler.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.