Sendmail Bug

Barry Shein bzs%bostonu.csnet at csnet-relay.arpa
Fri Feb 14 02:45:51 AEST 1986


This didn't seem to make it out, sorry if you got it twice.
-----


SYSTEM:
	4.2bsd
PROGRAM:
	sendmail
FILE:
	usr.lib/sendmail/src/deliver.c
PROBLEM:

	If a forked mailer dies a 'horrible' death (eg. by interrupt)
	sendmail makes almost no attempt to indicate or analyze the
	problem.

DIAGNOSIS:

	in endmailer() in deliver.c there is a check:

	if ((st & 0377) != 0)
	{
		syserr("endmailer %s: stat %o", name, st);
		ExitStat = EX_UNAVAILABLE;
		return (EX_UNAVAILABLE);
	}

where st is the status returned by wait() (actually, waitfor() which calls
wait and returns status.)

FIXES:

The first problem is that the returned status is printed in octal
without any hint of the base.

FIX 1:
	change call to:

		syserr("endmailer: %s: stat 0%o", name, st);

	or

		syserr("endmailer: %s: stat %d", name, st);

the latter probably being more sensible as the codes are documented
(in sigvec(2)) in decimal, not octal. In either case give us a hint.

FIX 2:

	This fix obviates FIX 1, is a little harder to maintain
	but probably much closer to what people want.

	Sending random numeric codes back to the user in the mail
	message is useless to most users except sendmail wizards
	with the source code either in hand or in head and similarly
	for the sigvec(2) manual page.

	Build a string table of codes mapping to reasonable messages
	and change syserr() call to use them (generated from the
	manual page):


/* into conf.c */

char *enderr[] = {
	"IMPOSSIBLE"
	"hangup"
	"interrupt"
	"quit"
	"illegal instruction"
	"trace trap"
	"IOT instruction"
	"EMT instruction"
	"floating point exception"
	"kill"
	"bus error"
	"segmentation violation"
	"bad argument to system call"
	"write on a pipe with no one to read it"
	"alarm clock"
	"software termination signal"
	"urgent condition present on socket"
	"stop"
	"stop signal generated from keyboard"
	"continue after stop"
	"child status has changed"
	"background read attempted from control terminal"
	"background write attempted to control terminal"
	"i/o is possible on a descriptor"
	"cpu time limit exceeded"
	"file size limit exceeded"
	"virtual time alarm"
	"profiling timer alarm"
	"window changed"
} ;

/* into conf.h */
extern char *enderr[];
#define MAXENDERR	(sizeof(enderr)/sizeof(enderr[0]))

Notice that some of these error values are impossible or at least very
unlikely ("stop") to come from a mailer but at least they act as place
holders and make it easy to regenerate the table if the manual page
changes. This table will have to be modified from time to time.

Even those error messages leave something to be desired but the likely
ones are self-explanatory (see below for MRC's.)

Change the syserr call above:

From
	syserr("endmailer %s: stat %o", name, st);

To something like:

	syserr("Sendmail: fatal error from mailer %s: %s",name,
		((st < 0) || (st >= MAXENDERR)) ? "Impossible Error?"
						: enderr[st]);

In MRC's case it SIGXFSZ (31(8) == 25(10)) or File Size Limit
Exceeded, probably due to a policy on the remote host (note that
unless it was an administrative error this is not a temporary
condition as it is an upper limit on the largest single file, not the
total file quota necessarily, so sendmail rejecting the letter was
an appropriate, if not friendly, response, the message was not.)

Well, that would make it at least as 'friendly' as MIT-MC when it gets
a file that is too large. MC also suggests using FTP which may or may
not be appropriate here. Perhaps some energetic person will supply
a list of nicely explanatory error messages with built-in suggestions
where possible.

WARNING: I have not tried this fix but if you understand what is
going on it should be trivial to install and check (if you can force
an appropriate error on your system.)

	-Barry Shein, Boston University



More information about the Comp.unix.wizards mailing list