Newer
Older
if (cp[0] == '%' && cp[1] != '\0')
{
cp++;
if (*cp == 'm')
{
/*
* Replace %m by system error string. If there are any %'s in
* the string, we'd better double them so that vsnprintf won't
* misinterpret.
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
*/
const char *cp2;
cp2 = useful_strerror(edata->saved_errno);
for (; *cp2; cp2++)
{
if (*cp2 == '%')
appendStringInfoCharMacro(&buf, '%');
appendStringInfoCharMacro(&buf, *cp2);
}
}
else
{
/* copy % and next char --- this avoids trouble with %%m */
appendStringInfoCharMacro(&buf, '%');
appendStringInfoCharMacro(&buf, *cp);
}
}
else
appendStringInfoCharMacro(&buf, *cp);
}
return buf.data;
}
/*
* A slightly cleaned-up version of strerror()
*/
static const char *
useful_strerror(int errnum)
{
/* this buffer is only used if errno has a bogus value */
static char errorstr_buf[48];
#ifdef WIN32
/* Winsock error code range, per WinError.h */
if (errnum >= 10000 && errnum <= 11999)
return pgwin32_socket_strerror(errnum);
#endif
str = strerror(errnum);
/*
* Some strerror()s return an empty string for out-of-range errno. This is
* ANSI C spec compliant, but not exactly useful.
*/
if (str == NULL || *str == '\0')
{
snprintf(errorstr_buf, sizeof(errorstr_buf),
Peter Eisentraut
committed
/*------
translator: This string will be truncated at 47
characters expanded. */
_("operating system error %d"), errnum);
str = errorstr_buf;
}
return str;
}
/*
* error_severity --- get localized string representing elevel
*/
static const char *
error_severity(int elevel)
{
const char *prefix;
switch (elevel)
{
case DEBUG1:
case DEBUG2:
case DEBUG3:
case DEBUG4:
case DEBUG5:
prefix = _("DEBUG");
break;
case LOG:
case COMMERROR:
prefix = _("LOG");
break;
case INFO:
prefix = _("INFO");
break;
case NOTICE:
prefix = _("NOTICE");
break;
prefix = _("WARNING");
case ERROR:
prefix = _("ERROR");
break;
case FATAL:
prefix = _("FATAL");
break;
case PANIC:
prefix = _("PANIC");
break;
default:
prefix = "???";
break;
}
return prefix;
}
/*
* append_with_tabs
* Append the string to the StringInfo buffer, inserting a tab after any
* newline.
*/
static void
append_with_tabs(StringInfo buf, const char *str)
while ((ch = *str++) != '\0')
appendStringInfoCharMacro(buf, ch);
if (ch == '\n')
appendStringInfoCharMacro(buf, '\t');
}
}
* Write errors to stderr (or by equal means when stderr is
* not available). Used before ereport/elog can be used
*/
void
write_stderr(const char *fmt,...)
{
fmt = _(fmt);
va_start(ap, fmt);
#ifndef WIN32
/* On Unix, we just fprintf to stderr */
vfprintf(stderr, fmt, ap);
Andrew Dunstan
committed
fflush(stderr);
#else
/*
* On Win32, we print to stderr if running on a console, or write to
* eventlog if running as a service
*/
if (pgwin32_is_service()) /* Running as a service */
vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
write_eventlog(ERROR, errbuf);
Andrew Dunstan
committed
{
/* Not running as service, write to stderr */
vfprintf(stderr, fmt, ap);
Andrew Dunstan
committed
fflush(stderr);
}
#endif
va_end(ap);
}
/*
* is_log_level_output -- is elevel logically >= log_min_level?
*
* We use this for tests that should consider LOG to sort out-of-order,
* between ERROR and FATAL. Generally this is the right thing for testing
* whether a message should go to the postmaster log, whereas a simple >=
* test is correct for testing whether the message should go to the client.
*/
static bool
is_log_level_output(int elevel, int log_min_level)
{
if (elevel == LOG || elevel == COMMERROR)
{
if (log_min_level == LOG || log_min_level <= ERROR)
return true;
}
else if (log_min_level == LOG)
{
/* elevel != LOG */
if (elevel >= FATAL)
return true;
}
/* Neither is LOG */
else if (elevel >= log_min_level)
return true;
return false;
}