-#ifndef lint
-static char sccsid[] = "@(#)bugfiler.c 4.14 (Berkeley) %G%";
-#endif
-
-/*
- * Bug report processing program.
- * It is designed to be invoked by alias(5)
- * and to be compatible with mh.
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-#include <pwd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/dir.h>
-
-#define BUGS_NAME "4bsd-bugs"
-#define BUGS_HOME "%ucbarpa@BERKELEY"
-#define MAILCMD "/usr/lib/sendmail -i -t"
-
-char unixtomh[] = "/usr/new/lib/mh/unixtomh";
-char *bugperson = "bugs";
-char *maildir = "mail";
-char ackfile[] = ".ack";
-char errfile[] = ".format";
-char sumfile[] = "summary";
-char logfile[] = "errors/log";
-char redistfile[] = ".redist";
-char tmpname[] = "BfXXXXXX";
-char draft[] = "RpXXXXXX";
-char disttmp[] = "RcXXXXXX";
-
-char buf[8192];
-char folder[MAXNAMLEN];
-int num;
-int msg_prot = 0664;
-
-int debug;
-
-char *index();
-char *rindex();
-char *fixaddr();
-char *any();
-
-main(argc, argv)
- char *argv[];
-{
- register char *cp;
- register int n;
- int pfd[2];
-
- if (argc > 4) {
- usage:
- fprintf(stderr, "Usage: bugfiler [-d] [-mmsg_mode] [maildir]\n");
- exit(1);
- }
- while (--argc > 0) {
- cp = *++argv;
- if (*cp == '-')
- switch (cp[1]) {
- case 'd':
- debug++;
- break;
-
- case 'm': /* set message protection */
- n = 0;
- for (cp += 2; *cp >= '0' && *cp <= '7'; )
- n = (n << 3) + (*cp++ - '0');
- msg_prot = n & 0777;
- break;
-
- default:
- goto usage;
- }
- else
- maildir = cp;
- }
- if (!debug)
- freopen(logfile, "a", stderr);
-
- if (bugperson) {
- struct passwd *pwd = getpwnam(bugperson);
-
- if (pwd == NULL) {
- fprintf(stderr, "%s: bugs person is unknown\n",
- bugperson);
- exit(1);
- }
- if (chdir(pwd->pw_dir) < 0) {
- fprintf(stderr, "can't chdir to %s\n", pwd->pw_dir);
- exit(1);
- }
- setuid(pwd->pw_uid);
- }
- if (chdir(maildir) < 0) {
- fprintf(stderr, "can't chdir to %s\n", maildir);
- exit(1);
- }
- umask(0);
-
-#ifdef UNIXCOMP
- /*
- * Convert UNIX style mail to mh style by filtering stdin through
- * unixtomh.
- */
- if (pipe(pfd) >= 0) {
- while ((n = fork()) == -1)
- sleep(5);
- if (n == 0) {
- close(pfd[0]);
- dup2(pfd[1], 1);
- close(pfd[1]);
- execl(unixtomh, "unixtomh", 0);
- _exit(127);
- }
- close(pfd[1]);
- dup2(pfd[0], 0);
- close(pfd[0]);
- }
-#endif
- while (process())
- ;
- exit(0);
-}
-
-/* states */
-
-#define EOM 0 /* End of message seen */
-#define FLD 1 /* Looking for header lines */
-#define BODY 2 /* Looking for message body lines */
-
-/* defines used for tag attributes */
-
-#define H_REQ 01
-#define H_SAV 02
-#define H_HDR 04
-#define H_FND 010
-
-#define FROM &headers[0]
-#define FROM_I headers[0].h_info
-#define SUBJECT_I headers[1].h_info
-#define INDEX &headers[2]
-#define INDEX_I headers[2].h_info
-#define DATE_I headers[3].h_info
-#define MSGID_I headers[4].h_info
-#define REPLYTO_I headers[5].h_info
-#define TO_I headers[6].h_info
-#define CC_I headers[7].h_info
-#define FIX headers[10]
-
-struct header {
- char *h_tag;
- int h_flags;
- char *h_info;
-} headers[] = {
- "From", H_REQ|H_SAV|H_HDR, 0,
- "Subject", H_REQ|H_SAV, 0,
- "Index", H_REQ|H_SAV, 0,
- "Date", H_SAV|H_HDR, 0,
- "Message-Id", H_SAV|H_HDR, 0,
- "Reply-To", H_SAV|H_HDR, 0,
- "To", H_SAV|H_HDR, 0,
- "Cc", H_SAV|H_HDR, 0,
- "Description", H_REQ, 0,
- "Repeat-By", 0, 0,
- "Fix", 0, 0,
- 0, 0, 0,
-};
-
-struct header *findheader();
-
-process()
-{
- register struct header *hp;
- register char *cp;
- register int c;
- char *info;
- int state, tmp, no_reply = 0;
- FILE *tfp, *fs;
-
- /*
- * Insure all headers are in a consistent
- * state. Anything left there is free'd.
- */
- for (hp = headers; hp->h_tag; hp++) {
- hp->h_flags &= ~H_FND;
- if (hp->h_info) {
- free(hp->h_info);
- hp->h_info = 0;
- }
- }
- /*
- * Read the report and make a copy. Must conform to RFC822 and
- * be of the form... <tag>: <info>
- * Note that the input is expected to be in mh mail format
- * (i.e., messages are separated by lines of ^A's).
- */
- while ((c = getchar()) == '\001' && peekc(stdin) == '\001')
- while (getchar() != '\n')
- ;
- if (c == EOF)
- return(0); /* all done */
-
- mktemp(tmpname);
- if ((tmp = creat(tmpname, msg_prot)) < 0) {
- fprintf(stderr, "cannont create %s\n", tmpname);
- exit(1);
- }
- if ((tfp = fdopen(tmp, "w")) == NULL) {
- fprintf(stderr, "cannot fdopen temp file\n");
- exit(1);
- }
-
- for (state = FLD; state != EOF && state != EOM; c = getchar()) {
- switch (state) {
- case FLD:
- if (c == '\n' || c == '-')
- goto body;
- for (cp = buf; c != ':'; c = getchar()) {
- if (cp < buf+sizeof(buf)-1 && c != '\n' && c != EOF) {
- *cp++ = c;
- continue;
- }
- *cp = '\0';
- fputs(buf, tfp);
- state = EOF;
- while (c != EOF) {
- if (c == '\n')
- if ((tmp = peekc(stdin)) == EOF)
- break;
- else if (tmp == '\001') {
- state = EOM;
- break;
- }
- putc(c, tfp);
- c = getchar();
- }
- fclose(tfp);
- goto badfmt;
- }
- *cp = '\0';
- fprintf(tfp, "%s:", buf);
- hp = findheader(buf, state);
-
- for (cp = buf; ; ) {
- if (cp >= buf+sizeof(buf)-1) {
- fprintf(stderr, "field truncated\n");
- while ((c = getchar()) != EOF && c != '\n')
- putc(c, tfp);
- }
- if ((c = getchar()) == EOF) {
- state = EOF;
- break;
- }
- putc(c, tfp);
- *cp++ = c;
- if (c == '\n')
- if ((c = peekc(stdin)) != ' ' && c != '\t') {
- if (c == EOF)
- state = EOF;
- else if (c == '\001')
- state = EOM;
- break;
- }
- }
- *cp = '\0';
- cp = buf;
- break;
-
- body:
- state = BODY;
- case BODY:
- for (cp = buf; ; c = getchar()) {
- if (c == EOF) {
- state = EOF;
- break;
- }
- if (c == '\001' && peekc(stdin) == '\001') {
- state = EOM;
- break;
- }
- putc(c, tfp);
- *cp++ = c;
- if (cp >= buf+sizeof(buf)-1 || c == '\n')
- break;
- }
- *cp = '\0';
- if ((cp = index(buf, ':')) == NULL)
- continue;
- *cp++ = '\0';
- hp = findheader(buf, state);
- }
-
- /*
- * Don't save the info if the header wasn't found, we don't
- * care about the info, or the header is repeated.
- */
- if (hp == NULL || !(hp->h_flags & H_SAV) || hp->h_info)
- continue;
- while (isspace(*cp))
- cp++;
- if (*cp) {
- info = cp;
- while (*cp++);
- cp--;
- while (isspace(cp[-1]))
- *--cp = '\0';
- hp->h_info = (char *) malloc(strlen(info) + 1);
- if (hp->h_info == NULL) {
- fprintf(stderr, "ran out of memory\n");
- continue;
- }
- strcpy(hp->h_info, info);
- if (hp == FROM && chkfrom(hp) < 0)
- no_reply = 1;
- if (hp == INDEX)
- chkindex(hp);
- }
- }
- fclose(tfp);
- if (no_reply) {
- unlink(tmpname);
- exit(0);
- }
- /*
- * Verify all the required pieces of information
- * are present.
- */
- for (hp = headers; hp->h_tag; hp++) {
- /*
- * Mail the bug report back to the sender with a note
- * explaining they must conform to the specification.
- */
- if ((hp->h_flags & H_REQ) && !(hp->h_flags & H_FND)) {
- if (debug)
- printf("Missing %s\n", hp->h_tag);
- badfmt:
- reply(FROM_I, errfile, tmpname);
- file(tmpname, "errors");
- return(state == EOM);
- }
- }
- /*
- * Acknowledge receipt.
- */
- reply(FROM_I, ackfile, (char *)0);
- file(tmpname, folder);
- /*
- * Append information about the new bug report
- * to the summary file.
- */
- if ((fs = fopen(sumfile, "a")) == NULL)
- fprintf(stderr, "Can't open %s\n", sumfile);
- else {
- fprintf(fs, "%14.14s/%-3d ", folder, num);
- fprintf(fs, "%-51.51s Recv\n", INDEX_I);
- fprintf(fs, "\t\t %-51.51s\n", SUBJECT_I);
- }
- fclose(fs);
- /*
- * Check redistribution list and, if members,
- * mail a copy of the bug report to these people.
- */
- redistribute(folder, num);
- return(state == EOM);
-}
-