76b7bf7135
were submitted back to sendmail.org (stage 1) and were incorporated.
768 lines
15 KiB
C
768 lines
15 KiB
C
/*
|
||
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
|
||
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
|
||
* Copyright (c) 1988, 1993
|
||
* The Regents of the University of California. All rights reserved.
|
||
*
|
||
* By using this file, you agree to the terms and conditions set
|
||
* forth in the LICENSE file which can be found at the top level of
|
||
* the sendmail distribution.
|
||
*
|
||
*/
|
||
|
||
#ifndef lint
|
||
static char sccsid[] = "@(#)err.c 8.74 (Berkeley) 6/4/1998";
|
||
#endif /* not lint */
|
||
|
||
# include "sendmail.h"
|
||
# include <errno.h>
|
||
|
||
/*
|
||
** SYSERR -- Print error message.
|
||
**
|
||
** Prints an error message via printf to the diagnostic output.
|
||
**
|
||
** If the first character of the syserr message is `!' it will
|
||
** log this as an ALERT message and exit immediately. This can
|
||
** leave queue files in an indeterminate state, so it should not
|
||
** be used lightly.
|
||
**
|
||
** Parameters:
|
||
** fmt -- the format string. If it does not begin with
|
||
** a three-digit SMTP reply code, either 554 or
|
||
** 451 is assumed depending on whether errno
|
||
** is set.
|
||
** (others) -- parameters
|
||
**
|
||
** Returns:
|
||
** none
|
||
** Through TopFrame if QuickAbort is set.
|
||
**
|
||
** Side Effects:
|
||
** increments Errors.
|
||
** sets ExitStat.
|
||
*/
|
||
|
||
char MsgBuf[BUFSIZ*2]; /* text of most recent message */
|
||
char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */
|
||
|
||
extern void putoutmsg __P((char *, bool, bool));
|
||
extern void puterrmsg __P((char *));
|
||
static void fmtmsg __P((char *, const char *, const char *, int, const char *, va_list));
|
||
|
||
#if NAMED_BIND && !defined(NO_DATA)
|
||
# define NO_DATA NO_ADDRESS
|
||
#endif
|
||
|
||
void
|
||
/*VARARGS1*/
|
||
#ifdef __STDC__
|
||
syserr(const char *fmt, ...)
|
||
#else
|
||
syserr(fmt, va_alist)
|
||
const char *fmt;
|
||
va_dcl
|
||
#endif
|
||
{
|
||
register char *p;
|
||
int olderrno = errno;
|
||
bool panic;
|
||
char *uname;
|
||
struct passwd *pw;
|
||
char ubuf[80];
|
||
VA_LOCAL_DECL
|
||
|
||
panic = *fmt == '!';
|
||
if (panic)
|
||
{
|
||
fmt++;
|
||
HoldErrs = FALSE;
|
||
}
|
||
|
||
/* format and output the error message */
|
||
if (olderrno == 0)
|
||
p = "554";
|
||
else
|
||
p = "451";
|
||
VA_START(fmt);
|
||
fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
|
||
VA_END;
|
||
puterrmsg(MsgBuf);
|
||
|
||
/* save this message for mailq printing */
|
||
if (!panic && CurEnv != NULL)
|
||
{
|
||
if (CurEnv->e_message != NULL)
|
||
free(CurEnv->e_message);
|
||
CurEnv->e_message = newstr(MsgBuf + 4);
|
||
}
|
||
|
||
/* determine exit status if not already set */
|
||
if (ExitStat == EX_OK)
|
||
{
|
||
if (olderrno == 0)
|
||
ExitStat = EX_SOFTWARE;
|
||
else
|
||
ExitStat = EX_OSERR;
|
||
if (tTd(54, 1))
|
||
printf("syserr: ExitStat = %d\n", ExitStat);
|
||
}
|
||
|
||
pw = sm_getpwuid(getuid());
|
||
if (pw != NULL)
|
||
uname = pw->pw_name;
|
||
else
|
||
{
|
||
uname = ubuf;
|
||
snprintf(ubuf, sizeof ubuf, "UID%d", getuid());
|
||
}
|
||
|
||
if (LogLevel > 0)
|
||
sm_syslog(panic ? LOG_ALERT : LOG_CRIT,
|
||
CurEnv == NULL ? NOQID : CurEnv->e_id,
|
||
"SYSERR(%s): %.900s",
|
||
uname, &MsgBuf[4]);
|
||
switch (olderrno)
|
||
{
|
||
case EBADF:
|
||
case ENFILE:
|
||
case EMFILE:
|
||
case ENOTTY:
|
||
#ifdef EFBIG
|
||
case EFBIG:
|
||
#endif
|
||
#ifdef ESPIPE
|
||
case ESPIPE:
|
||
#endif
|
||
#ifdef EPIPE
|
||
case EPIPE:
|
||
#endif
|
||
#ifdef ENOBUFS
|
||
case ENOBUFS:
|
||
#endif
|
||
#ifdef ESTALE
|
||
case ESTALE:
|
||
#endif
|
||
printopenfds(TRUE);
|
||
mci_dump_all(TRUE);
|
||
break;
|
||
}
|
||
if (panic)
|
||
{
|
||
#ifdef XLA
|
||
xla_all_end();
|
||
#endif
|
||
if (tTd(0, 1))
|
||
abort();
|
||
exit(EX_OSERR);
|
||
}
|
||
errno = 0;
|
||
if (QuickAbort)
|
||
longjmp(TopFrame, 2);
|
||
}
|
||
/*
|
||
** USRERR -- Signal user error.
|
||
**
|
||
** This is much like syserr except it is for user errors.
|
||
**
|
||
** Parameters:
|
||
** fmt -- the format string. If it does not begin with
|
||
** a three-digit SMTP reply code, 501 is assumed.
|
||
** (others) -- printf strings
|
||
**
|
||
** Returns:
|
||
** none
|
||
** Through TopFrame if QuickAbort is set.
|
||
**
|
||
** Side Effects:
|
||
** increments Errors.
|
||
*/
|
||
|
||
/*VARARGS1*/
|
||
void
|
||
#ifdef __STDC__
|
||
usrerr(const char *fmt, ...)
|
||
#else
|
||
usrerr(fmt, va_alist)
|
||
const char *fmt;
|
||
va_dcl
|
||
#endif
|
||
{
|
||
VA_LOCAL_DECL
|
||
|
||
if (SuprErrs)
|
||
return;
|
||
|
||
VA_START(fmt);
|
||
fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
|
||
VA_END;
|
||
|
||
/* save this message for mailq printing */
|
||
switch (MsgBuf[0])
|
||
{
|
||
case '4':
|
||
case '8':
|
||
if (CurEnv->e_message != NULL)
|
||
break;
|
||
|
||
/* fall through.... */
|
||
|
||
case '5':
|
||
case '6':
|
||
if (CurEnv->e_message != NULL)
|
||
free(CurEnv->e_message);
|
||
if (MsgBuf[0] == '6')
|
||
{
|
||
char buf[MAXLINE];
|
||
|
||
snprintf(buf, sizeof buf, "Postmaster warning: %.*s",
|
||
(int)sizeof buf - 22, MsgBuf + 4);
|
||
CurEnv->e_message = newstr(buf);
|
||
}
|
||
else
|
||
{
|
||
CurEnv->e_message = newstr(MsgBuf + 4);
|
||
}
|
||
break;
|
||
}
|
||
|
||
puterrmsg(MsgBuf);
|
||
|
||
if (LogLevel > 3 && LogUsrErrs)
|
||
sm_syslog(LOG_NOTICE, CurEnv->e_id,
|
||
"%.900s",
|
||
&MsgBuf[4]);
|
||
|
||
if (QuickAbort)
|
||
longjmp(TopFrame, 1);
|
||
}
|
||
/*
|
||
** MESSAGE -- print message (not necessarily an error)
|
||
**
|
||
** Parameters:
|
||
** msg -- the message (printf fmt) -- it can begin with
|
||
** an SMTP reply code. If not, 050 is assumed.
|
||
** (others) -- printf arguments
|
||
**
|
||
** Returns:
|
||
** none
|
||
**
|
||
** Side Effects:
|
||
** none.
|
||
*/
|
||
|
||
/*VARARGS1*/
|
||
void
|
||
#ifdef __STDC__
|
||
message(const char *msg, ...)
|
||
#else
|
||
message(msg, va_alist)
|
||
const char *msg;
|
||
va_dcl
|
||
#endif
|
||
{
|
||
VA_LOCAL_DECL
|
||
|
||
errno = 0;
|
||
VA_START(msg);
|
||
fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
|
||
VA_END;
|
||
putoutmsg(MsgBuf, FALSE, FALSE);
|
||
|
||
/* save this message for mailq printing */
|
||
switch (MsgBuf[0])
|
||
{
|
||
case '4':
|
||
case '8':
|
||
if (CurEnv->e_message != NULL)
|
||
break;
|
||
/* fall through.... */
|
||
|
||
case '5':
|
||
if (CurEnv->e_message != NULL)
|
||
free(CurEnv->e_message);
|
||
CurEnv->e_message = newstr(MsgBuf + 4);
|
||
break;
|
||
}
|
||
}
|
||
/*
|
||
** NMESSAGE -- print message (not necessarily an error)
|
||
**
|
||
** Just like "message" except it never puts the to... tag on.
|
||
**
|
||
** Parameters:
|
||
** msg -- the message (printf fmt) -- if it begins
|
||
** with a three digit SMTP reply code, that is used,
|
||
** otherwise 050 is assumed.
|
||
** (others) -- printf arguments
|
||
**
|
||
** Returns:
|
||
** none
|
||
**
|
||
** Side Effects:
|
||
** none.
|
||
*/
|
||
|
||
/*VARARGS1*/
|
||
void
|
||
#ifdef __STDC__
|
||
nmessage(const char *msg, ...)
|
||
#else
|
||
nmessage(msg, va_alist)
|
||
const char *msg;
|
||
va_dcl
|
||
#endif
|
||
{
|
||
VA_LOCAL_DECL
|
||
|
||
errno = 0;
|
||
VA_START(msg);
|
||
fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
|
||
VA_END;
|
||
putoutmsg(MsgBuf, FALSE, FALSE);
|
||
|
||
/* save this message for mailq printing */
|
||
switch (MsgBuf[0])
|
||
{
|
||
case '4':
|
||
case '8':
|
||
if (CurEnv->e_message != NULL)
|
||
break;
|
||
/* fall through.... */
|
||
|
||
case '5':
|
||
if (CurEnv->e_message != NULL)
|
||
free(CurEnv->e_message);
|
||
CurEnv->e_message = newstr(MsgBuf + 4);
|
||
break;
|
||
}
|
||
}
|
||
/*
|
||
** PUTOUTMSG -- output error message to transcript and channel
|
||
**
|
||
** Parameters:
|
||
** msg -- message to output (in SMTP format).
|
||
** holdmsg -- if TRUE, don't output a copy of the message to
|
||
** our output channel.
|
||
** heldmsg -- if TRUE, this is a previously held message;
|
||
** don't log it to the transcript file.
|
||
**
|
||
** Returns:
|
||
** none.
|
||
**
|
||
** Side Effects:
|
||
** Outputs msg to the transcript.
|
||
** If appropriate, outputs it to the channel.
|
||
** Deletes SMTP reply code number as appropriate.
|
||
*/
|
||
|
||
void
|
||
putoutmsg(msg, holdmsg, heldmsg)
|
||
char *msg;
|
||
bool holdmsg;
|
||
bool heldmsg;
|
||
{
|
||
char msgcode = msg[0];
|
||
|
||
/* display for debugging */
|
||
if (tTd(54, 8))
|
||
printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
|
||
heldmsg ? " (held)" : "");
|
||
|
||
/* map warnings to something SMTP can handle */
|
||
if (msgcode == '6')
|
||
msg[0] = '5';
|
||
else if (msgcode == '8')
|
||
msg[0] = '4';
|
||
|
||
/* output to transcript if serious */
|
||
if (!heldmsg && CurEnv != NULL && CurEnv->e_xfp != NULL &&
|
||
strchr("45", msg[0]) != NULL)
|
||
fprintf(CurEnv->e_xfp, "%s\n", msg);
|
||
|
||
if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
|
||
sm_syslog(LOG_INFO, CurEnv->e_id,
|
||
"--> %s%s",
|
||
msg, holdmsg ? " (held)" : "");
|
||
|
||
if (msgcode == '8')
|
||
msg[0] = '0';
|
||
|
||
/* output to channel if appropriate */
|
||
if (!Verbose && msg[0] == '0')
|
||
return;
|
||
if (holdmsg)
|
||
{
|
||
/* save for possible future display */
|
||
msg[0] = msgcode;
|
||
snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg);
|
||
return;
|
||
}
|
||
|
||
(void) fflush(stdout);
|
||
|
||
if (OutChannel == NULL)
|
||
return;
|
||
|
||
/* if DisConnected, OutChannel now points to the transcript */
|
||
if (!DisConnected &&
|
||
(OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
|
||
fprintf(OutChannel, "%s\r\n", msg);
|
||
else
|
||
fprintf(OutChannel, "%s\n", &msg[4]);
|
||
if (TrafficLogFile != NULL)
|
||
fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(),
|
||
(OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
|
||
if (msg[3] == ' ')
|
||
(void) fflush(OutChannel);
|
||
if (!ferror(OutChannel) || DisConnected)
|
||
return;
|
||
|
||
/*
|
||
** Error on output -- if reporting lost channel, just ignore it.
|
||
** Also, ignore errors from QUIT response (221 message) -- some
|
||
** rude servers don't read result.
|
||
*/
|
||
|
||
if (InChannel == NULL || feof(InChannel) || ferror(InChannel) ||
|
||
strncmp(msg, "221", 3) == 0)
|
||
return;
|
||
|
||
/* can't call syserr, 'cause we are using MsgBuf */
|
||
HoldErrs = TRUE;
|
||
if (LogLevel > 0)
|
||
sm_syslog(LOG_CRIT, CurEnv->e_id,
|
||
"SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
|
||
CurHostName == NULL ? "NO-HOST" : CurHostName,
|
||
shortenstring(msg, MAXSHORTSTR), errstring(errno));
|
||
}
|
||
/*
|
||
** PUTERRMSG -- like putoutmsg, but does special processing for error messages
|
||
**
|
||
** Parameters:
|
||
** msg -- the message to output.
|
||
**
|
||
** Returns:
|
||
** none.
|
||
**
|
||
** Side Effects:
|
||
** Sets the fatal error bit in the envelope as appropriate.
|
||
*/
|
||
|
||
void
|
||
puterrmsg(msg)
|
||
char *msg;
|
||
{
|
||
char msgcode = msg[0];
|
||
|
||
/* output the message as usual */
|
||
putoutmsg(msg, HoldErrs, FALSE);
|
||
|
||
/* be careful about multiple error messages */
|
||
if (OnlyOneError)
|
||
HoldErrs = TRUE;
|
||
|
||
/* signal the error */
|
||
Errors++;
|
||
|
||
if (CurEnv == NULL)
|
||
return;
|
||
|
||
if (msgcode == '6')
|
||
{
|
||
/* notify the postmaster */
|
||
CurEnv->e_flags |= EF_PM_NOTIFY;
|
||
}
|
||
else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
|
||
{
|
||
/* mark long-term fatal errors */
|
||
CurEnv->e_flags |= EF_FATALERRS;
|
||
}
|
||
}
|
||
/*
|
||
** FMTMSG -- format a message into buffer.
|
||
**
|
||
** Parameters:
|
||
** eb -- error buffer to get result.
|
||
** to -- the recipient tag for this message.
|
||
** num -- arpanet error number.
|
||
** en -- the error number to display.
|
||
** fmt -- format of string.
|
||
** a, b, c, d, e -- arguments.
|
||
**
|
||
** Returns:
|
||
** none.
|
||
**
|
||
** Side Effects:
|
||
** none.
|
||
*/
|
||
|
||
static void
|
||
fmtmsg(eb, to, num, eno, fmt, ap)
|
||
register char *eb;
|
||
const char *to;
|
||
const char *num;
|
||
int eno;
|
||
const char *fmt;
|
||
va_list ap;
|
||
{
|
||
char del;
|
||
int l;
|
||
int spaceleft = sizeof MsgBuf;
|
||
|
||
/* output the reply code */
|
||
if (isascii(fmt[0]) && isdigit(fmt[0]) &&
|
||
isascii(fmt[1]) && isdigit(fmt[1]) &&
|
||
isascii(fmt[2]) && isdigit(fmt[2]))
|
||
{
|
||
num = fmt;
|
||
fmt += 4;
|
||
}
|
||
if (num[3] == '-')
|
||
del = '-';
|
||
else
|
||
del = ' ';
|
||
(void) snprintf(eb, spaceleft, "%3.3s%c", num, del);
|
||
eb += 4;
|
||
spaceleft -= 4;
|
||
|
||
/* output the file name and line number */
|
||
if (FileName != NULL)
|
||
{
|
||
(void) snprintf(eb, spaceleft, "%s: line %d: ",
|
||
shortenstring(FileName, 83), LineNumber);
|
||
eb += (l = strlen(eb));
|
||
spaceleft -= l;
|
||
}
|
||
|
||
/* output the "to" person */
|
||
if (to != NULL && to[0] != '\0' &&
|
||
strncmp(num, "551", 3) != 0 &&
|
||
strncmp(num, "251", 3) != 0)
|
||
{
|
||
(void) snprintf(eb, spaceleft, "%s... ",
|
||
shortenstring(to, MAXSHORTSTR));
|
||
spaceleft -= strlen(eb);
|
||
while (*eb != '\0')
|
||
*eb++ &= 0177;
|
||
}
|
||
|
||
/* output the message */
|
||
(void) vsnprintf(eb, spaceleft, fmt, ap);
|
||
spaceleft -= strlen(eb);
|
||
while (*eb != '\0')
|
||
*eb++ &= 0177;
|
||
|
||
/* output the error code, if any */
|
||
if (eno != 0)
|
||
(void) snprintf(eb, spaceleft, ": %s", errstring(eno));
|
||
}
|
||
/*
|
||
** BUFFER_ERRORS -- arrange to buffer future error messages
|
||
**
|
||
** Parameters:
|
||
** none
|
||
**
|
||
** Returns:
|
||
** none.
|
||
*/
|
||
|
||
void
|
||
buffer_errors()
|
||
{
|
||
HeldMessageBuf[0] = '\0';
|
||
HoldErrs = TRUE;
|
||
}
|
||
/*
|
||
** FLUSH_ERRORS -- flush the held error message buffer
|
||
**
|
||
** Parameters:
|
||
** print -- if set, print the message, otherwise just
|
||
** delete it.
|
||
**
|
||
** Returns:
|
||
** none.
|
||
*/
|
||
|
||
void
|
||
flush_errors(print)
|
||
bool print;
|
||
{
|
||
if (print && HeldMessageBuf[0] != '\0')
|
||
putoutmsg(HeldMessageBuf, FALSE, TRUE);
|
||
HeldMessageBuf[0] = '\0';
|
||
HoldErrs = FALSE;
|
||
}
|
||
/*
|
||
** ERRSTRING -- return string description of error code
|
||
**
|
||
** Parameters:
|
||
** errnum -- the error number to translate
|
||
**
|
||
** Returns:
|
||
** A string description of errnum.
|
||
**
|
||
** Side Effects:
|
||
** none.
|
||
*/
|
||
|
||
const char *
|
||
errstring(errnum)
|
||
int errnum;
|
||
{
|
||
char *dnsmsg;
|
||
char *bp;
|
||
static char buf[MAXLINE];
|
||
# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
|
||
extern char *sys_errlist[];
|
||
extern int sys_nerr;
|
||
# endif
|
||
# if SMTP
|
||
extern char *SmtpPhase;
|
||
# endif /* SMTP */
|
||
|
||
/*
|
||
** Handle special network error codes.
|
||
**
|
||
** These are 4.2/4.3bsd specific; they should be in daemon.c.
|
||
*/
|
||
|
||
dnsmsg = NULL;
|
||
switch (errnum)
|
||
{
|
||
# if defined(DAEMON) && defined(ETIMEDOUT)
|
||
case ETIMEDOUT:
|
||
case ECONNRESET:
|
||
bp = buf;
|
||
#if HASSTRERROR
|
||
snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum));
|
||
#else
|
||
if (errnum >= 0 && errnum < sys_nerr)
|
||
snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]);
|
||
else
|
||
snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum);
|
||
#endif
|
||
bp += strlen(bp);
|
||
if (CurHostName != NULL)
|
||
{
|
||
if (errnum == ETIMEDOUT)
|
||
{
|
||
snprintf(bp, SPACELEFT(buf, bp), " with ");
|
||
bp += strlen(bp);
|
||
}
|
||
else
|
||
{
|
||
bp = buf;
|
||
snprintf(bp, SPACELEFT(buf, bp),
|
||
"Connection reset by ");
|
||
bp += strlen(bp);
|
||
}
|
||
snprintf(bp, SPACELEFT(buf, bp), "%s",
|
||
shortenstring(CurHostName, MAXSHORTSTR));
|
||
bp += strlen(buf);
|
||
}
|
||
if (SmtpPhase != NULL)
|
||
{
|
||
snprintf(bp, SPACELEFT(buf, bp), " during %s",
|
||
SmtpPhase);
|
||
}
|
||
return (buf);
|
||
|
||
case EHOSTDOWN:
|
||
if (CurHostName == NULL)
|
||
break;
|
||
(void) snprintf(buf, sizeof buf, "Host %s is down",
|
||
shortenstring(CurHostName, MAXSHORTSTR));
|
||
return (buf);
|
||
|
||
case ECONNREFUSED:
|
||
if (CurHostName == NULL)
|
||
break;
|
||
(void) snprintf(buf, sizeof buf, "Connection refused by %s",
|
||
shortenstring(CurHostName, MAXSHORTSTR));
|
||
return (buf);
|
||
# endif
|
||
|
||
# if NAMED_BIND
|
||
case HOST_NOT_FOUND + E_DNSBASE:
|
||
dnsmsg = "host not found";
|
||
break;
|
||
|
||
case TRY_AGAIN + E_DNSBASE:
|
||
dnsmsg = "host name lookup failure";
|
||
break;
|
||
|
||
case NO_RECOVERY + E_DNSBASE:
|
||
dnsmsg = "non-recoverable error";
|
||
break;
|
||
|
||
case NO_DATA + E_DNSBASE:
|
||
dnsmsg = "no data known";
|
||
break;
|
||
# endif
|
||
|
||
case EPERM:
|
||
/* SunOS gives "Not owner" -- this is the POSIX message */
|
||
return "Operation not permitted";
|
||
|
||
/*
|
||
** Error messages used internally in sendmail.
|
||
*/
|
||
|
||
case E_SM_OPENTIMEOUT:
|
||
return "Timeout on file open";
|
||
|
||
case E_SM_NOSLINK:
|
||
return "Symbolic links not allowed";
|
||
|
||
case E_SM_NOHLINK:
|
||
return "Hard links not allowed";
|
||
|
||
case E_SM_REGONLY:
|
||
return "Regular files only";
|
||
|
||
case E_SM_ISEXEC:
|
||
return "Executable files not allowed";
|
||
|
||
case E_SM_WWDIR:
|
||
return "World writable directory";
|
||
|
||
case E_SM_GWDIR:
|
||
return "Group writable directory";
|
||
|
||
case E_SM_FILECHANGE:
|
||
return "File changed after open";
|
||
|
||
case E_SM_WWFILE:
|
||
return "World writable file";
|
||
|
||
case E_SM_GWFILE:
|
||
return "Group writable file";
|
||
}
|
||
|
||
if (dnsmsg != NULL)
|
||
{
|
||
bp = buf;
|
||
strcpy(bp, "Name server: ");
|
||
bp += strlen(bp);
|
||
if (CurHostName != NULL)
|
||
{
|
||
snprintf(bp, SPACELEFT(buf, bp), "%s: ",
|
||
shortenstring(CurHostName, MAXSHORTSTR));
|
||
bp += strlen(bp);
|
||
}
|
||
snprintf(bp, SPACELEFT(buf, bp), "%s", dnsmsg);
|
||
return buf;
|
||
}
|
||
|
||
#if HASSTRERROR
|
||
return strerror(errnum);
|
||
#else
|
||
if (errnum > 0 && errnum < sys_nerr)
|
||
return (sys_errlist[errnum]);
|
||
|
||
(void) snprintf(buf, sizeof buf, "Error %d", errnum);
|
||
return (buf);
|
||
#endif
|
||
}
|