Skip to content
Snippets Groups Projects
elog.c 55 KiB
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.
				 */
				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 */
Bruce Momjian's avatar
Bruce Momjian committed
	const char *str;
#ifdef WIN32
	/* Winsock error code range, per WinError.h */
	if (errnum >= 10000 && errnum <= 11999)
		return pgwin32_socket_strerror(errnum);
#endif
	 * Some strerror()s return an empty string for out-of-range errno. This is
	 * ANSI C spec compliant, but not exactly useful.
		snprintf(errorstr_buf, sizeof(errorstr_buf),
				 /*------
				   translator: This string will be truncated at 47
				   characters expanded. */
				 _("operating system error %d"), errnum);
/*
 * error_severity --- get localized string representing elevel
 */
		case DEBUG1:
		case DEBUG2:
		case DEBUG3:
		case DEBUG4:
		case DEBUG5:
Bruce Momjian's avatar
Bruce Momjian committed
		case WARNING:
Bruce Momjian's avatar
Bruce Momjian committed
			break;
 *	Append the string to the StringInfo buffer, inserting a tab after any
 *	newline.
static void
append_with_tabs(StringInfo buf, const char *str)
Bruce Momjian's avatar
Bruce Momjian committed
	char		ch;
	while ((ch = *str++) != '\0')
		appendStringInfoCharMacro(buf, ch);
		if (ch == '\n')
			appendStringInfoCharMacro(buf, '\t');
Bruce Momjian's avatar
Bruce Momjian committed
/*
 * Write errors to stderr (or by equal means when stderr is
 * not available). Used before ereport/elog can be used
Bruce Momjian's avatar
Bruce Momjian committed
 * safely (memory context, GUC load etc)
Bruce Momjian's avatar
Bruce Momjian committed
	va_list		ap;

	va_start(ap, fmt);
#ifndef WIN32
	/* On Unix, we just fprintf to stderr */
	vfprintf(stderr, fmt, ap);
Bruce Momjian's avatar
Bruce Momjian committed

	/*
	 * 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 */
Bruce Momjian's avatar
Bruce Momjian committed
		char		errbuf[2048];		/* Arbitrary size? */

		vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
		write_eventlog(ERROR, errbuf);
Bruce Momjian's avatar
Bruce Momjian committed
	else
		/* Not running as service, write to stderr */

/*
 * 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;
}