static char sccsid
[] = "@(#)bugfiler.c 4.11 (Berkeley) 9/14/83";
* Bug report processing program.
* It is designed to be invoked by alias(5)
* and to be compatible with mh.
#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 errfile
[] = ".format";
char sumfile
[] = "summary";
char logfile
[] = "errors/log";
char redistfile
[] = ".redist";
char tmpname
[] = "BfXXXXXX";
char draft
[] = "RpXXXXXX";
char disttmp
[] = "RcXXXXXX";
fprintf(stderr
, "Usage: bugfiler [-d] [-mmsg_mode] [maildir]\n");
case 'm': /* set message protection */
for (cp
+= 2; *cp
>= '0' && *cp
<= '7'; )
n
= (n
<< 3) + (*cp
++ - '0');
freopen(logfile
, "a", stderr
);
struct passwd
*pwd
= getpwnam(bugperson
);
fprintf(stderr
, "%s: bugs person is unknown\n",
if (chdir(pwd
->pw_dir
) < 0) {
fprintf(stderr
, "can't chdir to %s\n", pwd
->pw_dir
);
if (chdir(maildir
) < 0) {
fprintf(stderr
, "can't chdir to %s\n", maildir
);
* Convert UNIX style mail to mh style by filtering stdin through
while ((n
= fork()) == -1)
execl(unixtomh
, "unixtomh", 0);
#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 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
"From", H_REQ
|H_SAV
|H_HDR
, 0,
"Subject", H_REQ
|H_SAV
, 0,
"Message-Id", H_SAV
|H_HDR
, 0,
"Reply-To", H_SAV
|H_HDR
, 0,
struct header
*findheader();
register struct header
*hp
;
* Insure all headers are in a consistent
* state. Anything left there is free'd.
for (hp
= headers
; hp
->h_tag
; hp
++) {
* 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')
return(0); /* all done */
if ((tmp
= creat(tmpname
, msg_prot
)) < 0) {
fprintf(stderr
, "cannont create %s\n", tmpname
);
if ((tfp
= fdopen(tmp
, "w")) == NULL
) {
fprintf(stderr
, "cannot fdopen temp file\n");
for (state
= FLD
; state
!= EOF
&& state
!= EOM
; c
= getchar()) {
if (c
== '\n' || c
== '-')
for (cp
= buf
; c
!= ':'; c
= getchar()) {
if (cp
< buf
+sizeof(buf
)-1 && c
!= '\n' && c
!= EOF
) {
if ((tmp
= peekc(stdin
)) == EOF
)
else if (tmp
== '\001') {
fprintf(tfp
, "%s:", buf
);
hp
= findheader(buf
, state
);
if (cp
>= buf
+sizeof(buf
)-1) {
fprintf(stderr
, "field truncated\n");
while ((c
= getchar()) != EOF
&& c
!= '\n')
if ((c
= getchar()) == EOF
) {
if ((c
= peekc(stdin
)) != ' ' && c
!= '\t') {
for (cp
= buf
; ; c
= getchar()) {
if (c
== '\001' && peekc(stdin
) == '\001') {
if (cp
>= buf
+sizeof(buf
)-1 || c
== '\n')
if ((cp
= index(buf
, ':')) == NULL
)
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
)
hp
->h_info
= (char *) malloc(strlen(info
) + 1);
if (hp
->h_info
== NULL
) {
fprintf(stderr
, "ran out of memory\n");
strcpy(hp
->h_info
, info
);
* Verify all the required pieces of information
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
)) {
printf("Missing %s\n", hp
->h_tag
);
reply(FROM_I
, errfile
, tmpname
);
reply(FROM_I
, ackfile
, (char *)0);
* Append information about the new bug report
if ((fs
= fopen(sumfile
, "a")) == NULL
)
fprintf(stderr
, "Can't open %s\n", sumfile
);
fprintf(fs
, "%14.14s/%-3d ", folder
, num
);
fprintf(fs
, "%-51.51s Recv\n", INDEX_I
);
fprintf(fs
, "\t\t %-51.51s\n", SUBJECT_I
);
* Check redistribution list and, if members,
* mail a copy of the bug report to these people.
redistribute(folder
, num
);
* Lookup the string in the list of headers and return a pointer
register struct header
*hp
;
printf("findheader(%s, %d)\n", name
, state
);
for (hp
= headers
; hp
->h_tag
; hp
++) {
if (!streq(hp
->h_tag
, buf
))
if ((hp
->h_flags
& H_HDR
) && state
!= FLD
)
* Check the format of the Index information.
* A side effect is to set the name of the folder if all is well.
register char *cp1
, *cp2
;
printf("chkindex(%s)\n", hp
->h_info
);
* Strip of leading "/", "usr/", or "src/".
while (substr(cp1
, "usr/") || substr(cp1
, "src/"))
* Read the folder name and remove it from the index line.
if (cp2
< folder
+sizeof(folder
)-1)
for (cp2
= hp
->h_info
; *cp2
++ = *cp1
++; )
printf("folder = %s\n", folder
);
* Check to make sure we have a valid folder name
if (stat(folder
, &stbuf
) == 0 && (stbuf
.st_mode
& S_IFMT
) == S_IFDIR
)
* The Index line is not in the correct format so clear
* the H_FND flag to mail back the correct format.
* Move or copy the file msg to the folder (directory).
* As a side effect, num is set to the number under which
* the message is filed in folder.
char msgname
[MAXNAMLEN
*2+2];
printf("file(%s, %s)\n", fname
, folder
);
* Get the next number to use by finding the last message number
* in folder and adding one.
if ((dirp
= opendir(folder
)) == NULL
) {
fprintf(stderr
, "Cannot open %s/%s\n", maildir
, folder
);
while ((d
= readdir(dirp
)) != NULL
) {
n
= n
* 10 + (*cp
++ - '0');
if (*cp
== '\0' && n
> num
)
* Create the destination file "folder/num" and copy fname to it.
sprintf(msgname
, "%s/%d", folder
, num
);
if (link(fname
, msgname
) < 0) {
if ((fin
= open(fname
, 0)) < 0) {
fprintf(stderr
, "cannot open %s\n", fname
);
if ((fout
= creat(msgname
, msg_prot
)) < 0) {
fprintf(stderr
, "cannot create %s\n", msgname
);
while ((n
= read(fin
, buf
, sizeof(buf
))) > 0)
* Redistribute a bug report to those people indicated
* in the redistribution list file. Perhaps should also
* annotate bug report with this information for future
redistribute(folder
, num
)
FILE *fredist
, *fbug
, *ftemp
;
char line
[BUFSIZ
], bug
[2 * MAXNAMLEN
+ 1];
int redistcnt
, continuation
, first
;
fredist
= fopen(redistfile
, "r");
printf("redistribute(%s, %d), no distribution list\n",
while (fgets(line
, sizeof (line
) - 1, fredist
) != NULL
) {
printf("%s: %s", redistfile
, line
);
if (continuation
&& index(line
, '\\'))
if (strcmp(folder
, line
) == 0)
printf("no redistribution list found\n");
ftemp
= fopen(disttmp
, "w+r");
printf("%s: couldn't create\n", disttmp
);
printf("redistribution list %s", cp
);
while (*cp
&& (*cp
== ' ' || *cp
== '\t' || *cp
== ','))
user
= cp
, cp
= any(cp
, ", \t\n\\");
printf("copy to %s\n", user
);
fprintf(ftemp
, "To: %s", user
);
fprintf(ftemp
, ", %s", user
);
if (fgets(line
, sizeof (line
) - 1, fredist
))
fprintf(ftemp
, "Subject: ");
fprintf(ftemp
, "%s\n", SUBJECT_I
);
fprintf(ftemp
, "Untitled bug report\n");
fprintf(ftemp
, "\nRedistributed-by: %s%s\n", BUGS_NAME
, BUGS_HOME
);
* Create copy of bug report. Perhaps we should
* truncate large messages and just give people
* a pointer to the original?
sprintf(bug
, "%s/%d", folder
, num
);
printf("%s: disappeared?\n", bug
);
while (fgets(line
, sizeof (line
) - 1, fbug
)) {
/* first blank line indicates start of mesg */
if (first
&& line
[0] == '\n') {
printf("empty bug report?\n");
char buf
[BUFSIZ
], cmd
[BUFSIZ
];
printf("dodeliver \"%s\"\n", cmd
);
printf("dodeliver, \"%s\" failed\n", cmd
);
while (fgets(buf
, sizeof (buf
) - 1, fd
)) {
* Mail file1 and file2 back to the sender.
char *to
, *file1
, *file2
;
printf("reply(%s, %s, %s)\n", to
, file1
, file2
);
* Create a temporary file to put the message in.
if ((fout
= fopen(draft
, "w+r")) == NULL
) {
fprintf(stderr
, "Can't create %s\n", draft
);
* Output the proper header information.
fprintf(fout
, "Reply-To: %s%s\n", BUGS_NAME
, BUGS_HOME
);
fprintf(fout
, "From: %s%s (Bugs Bunny)\n", BUGS_NAME
, BUGS_HOME
);
if ((to
= fixaddr(to
)) == 0) {
fprintf(stderr
, "No one to reply to\n");
fprintf(fout
, "To: %s\n", to
);
fprintf(fout
, "Subject: ");
if ((SUBJECT_I
[0] != 'R' && SUBJECT_I
[0] != 'r') ||
(SUBJECT_I
[1] != 'E' && SUBJECT_I
[1] != 'e') ||
fprintf(fout
, "%s\n", SUBJECT_I
);
fprintf(fout
, "In-Acknowledgement-Of: Your message of ");
fprintf(fout
, "%s.\n", DATE_I
);
fprintf(fout
, " %s\n", MSGID_I
);
if ((in
= open(file1
, 0)) >= 0) {
while ((w
= read(in
, buf
, sizeof(buf
))) > 0)
if (file2
&& (in
= open(file2
, 0)) >= 0) {
while ((w
= read(in
, buf
, sizeof(buf
))) > 0)
* fix names like "xxx (something)" to "xxx" and
* "xxx <something>" to "something".
register char *cp
, *lp
, c
;
for (lp
= cp
= text
; ; ) {
while (*cp
&& *cp
++ != ')');
while (lp
!= text
&& (*lp
== ' ' || *lp
== '\t'))
* Compare two strings and convert any upper case letters to lower case.
if ((c
| 040) != (*s2
++ | 040))
* Return true if string s2 matches the first part of s1.
for (sp
= set
; *sp
; sp
++)