extern unsigned char pg_ascii_toupper(unsigned char ch);
extern unsigned char pg_ascii_tolower(unsigned char ch);
-#ifdef USE_REPL_SNPRINTF
-
/*
- * Versions of libintl >= 0.13 try to replace printf() and friends with
- * macros to their own versions that understand the %$ format. We do the
- * same, so disable their macros, if they exist.
+ * Capture macro-compatible calls to printf() and friends, and redirect them
+ * to wrappers that throw errors in lieu of reporting failure in a return
+ * value. Versions of libintl >= 0.13 similarly redirect to versions that
+ * understand the %$ format, so disable libintl macros first.
*/
#ifdef vsnprintf
#undef vsnprintf
#undef printf
#endif
-extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-extern int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
-extern int pg_vsprintf(char *str, const char *fmt, va_list args);
-extern int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2, 3);
-extern int pg_vfprintf(FILE *stream, const char *fmt, va_list args);
-extern int pg_fprintf(FILE *stream, const char *fmt,...) pg_attribute_printf(2, 3);
-extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2);
+extern int
+vsnprintf_throw_on_fail(char *str, size_t count, const char *fmt, va_list args)
+pg_attribute_printf(3, 0);
+extern int
+snprintf_throw_on_fail(char *str, size_t count, const char *fmt,...)
+pg_attribute_printf(3, 4);
+extern int
+vsprintf_throw_on_fail(char *str, const char *fmt, va_list args)
+pg_attribute_printf(2, 0);
+extern int
+sprintf_throw_on_fail(char *str, const char *fmt,...)
+pg_attribute_printf(2, 3);
+extern int
+vfprintf_throw_on_fail(FILE *stream, const char *fmt, va_list args)
+pg_attribute_printf(2, 0);
+extern int
+fprintf_throw_on_fail(FILE *stream, const char *fmt,...)
+pg_attribute_printf(2, 3);
+extern int
+printf_throw_on_fail(const char *fmt,...)
+pg_attribute_printf(1, 2);
/*
* The GCC-specific code below prevents the pg_attribute_printf above from
* being replaced, and this is required because gcc doesn't know anything
- * about pg_printf.
+ * about printf_throw_on_fail.
*/
#ifdef __GNUC__
-#define vsnprintf(...) pg_vsnprintf(__VA_ARGS__)
-#define snprintf(...) pg_snprintf(__VA_ARGS__)
-#define vsprintf(...) pg_vsprintf(__VA_ARGS__)
-#define sprintf(...) pg_sprintf(__VA_ARGS__)
-#define vfprintf(...) pg_vfprintf(__VA_ARGS__)
-#define fprintf(...) pg_fprintf(__VA_ARGS__)
-#define printf(...) pg_printf(__VA_ARGS__)
+#define vsnprintf(...) vsnprintf_throw_on_fail(__VA_ARGS__)
+#define snprintf(...) snprintf_throw_on_fail(__VA_ARGS__)
+#define vsprintf(...) vsprintf_throw_on_fail(__VA_ARGS__)
+#define sprintf(...) sprintf_throw_on_fail(__VA_ARGS__)
+#define vfprintf(...) vfprintf_throw_on_fail(__VA_ARGS__)
+#define fprintf(...) fprintf_throw_on_fail(__VA_ARGS__)
+#define printf(...) printf_throw_on_fail(__VA_ARGS__)
#else
-#define vsnprintf pg_vsnprintf
-#define snprintf pg_snprintf
-#define vsprintf pg_vsprintf
-#define sprintf pg_sprintf
-#define vfprintf pg_vfprintf
-#define fprintf pg_fprintf
-#define printf pg_printf
+#define vsnprintf vsnprintf_throw_on_fail
+#define snprintf snprintf_throw_on_fail
+#define vsprintf vsprintf_throw_on_fail
+#define sprintf sprintf_throw_on_fail
+#define vfprintf vfprintf_throw_on_fail
+#define fprintf fprintf_throw_on_fail
+#define printf printf_throw_on_fail
#endif
+
+#ifdef USE_REPL_SNPRINTF
+
+/* Code outside syswrap.c should not call these. */
+
+extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
+extern int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
+extern int pg_vsprintf(char *str, const char *fmt, va_list args);
+extern int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2, 3);
+extern int pg_vfprintf(FILE *stream, const char *fmt, va_list args);
+extern int pg_fprintf(FILE *stream, const char *fmt,...) pg_attribute_printf(2, 3);
+extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2);
+
#endif /* USE_REPL_SNPRINTF */
#if defined(WIN32)
# Shared library stuff
include $(top_srcdir)/src/Makefile.shlib
+# XXX This library uses no symbols from snprintf.c.
snprintf.c: % : $(top_srcdir)/src/port/%
rm -f $@ && $(LN_S) $< .
/pgstrcasecmp.c
/snprintf.c
/strlcpy.c
+/syswrap.c
/thread.c
/win32setlocale.c
/isinf.c
LIBS := $(filter-out -lpgport, $(LIBS))
OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \
- connect.o misc.o path.o pgstrcasecmp.o \
+ connect.o misc.o path.o pgstrcasecmp.o syswrap.o \
$(filter snprintf.o strlcpy.o win32setlocale.o isinf.o, $(LIBOBJS)) $(WIN32RES)
# thread.c is needed only for non-WIN32 implementation of path.c
# necessarily use the same object files as the backend uses. Instead,
# symlink the source files in here and build our own object file.
-path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/%
+path.c pgstrcasecmp.c snprintf.c strlcpy.c syswrap.c thread.c win32setlocale.c isinf.c: % : $(top_srcdir)/src/port/%
rm -f $@ && $(LN_S) $< .
misc.o: misc.c $(top_builddir)/src/port/pg_config_paths.h
clean distclean: clean-lib
rm -f $(OBJS)
- rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c thread.c win32setlocale.c isinf.c
+ rm -f path.c pgstrcasecmp.c snprintf.c strlcpy.c syswrap.c thread.c win32setlocale.c isinf.c
maintainer-clean: distclean maintainer-clean-lib
/pgstrcasecmp.c
/rint.c
/snprintf.c
+/syswrap.c
SHLIB_EXPORTS = exports.txt
OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o \
- pgstrcasecmp.o \
+ pgstrcasecmp.o syswrap.o \
$(filter rint.o snprintf.o, $(LIBOBJS)) $(WIN32RES)
all: all-lib
# necessarily use the same object files as the backend uses. Instead,
# symlink the source files in here and build our own object file.
-pgstrcasecmp.c rint.c snprintf.c: % : $(top_srcdir)/src/port/%
+pgstrcasecmp.c rint.c snprintf.c syswrap.c: % : $(top_srcdir)/src/port/%
rm -f $@ && $(LN_S) $< .
install: all installdirs install-lib
uninstall: uninstall-lib
clean distclean: clean-lib
- rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c
+ rm -f $(OBJS) pgstrcasecmp.c rint.c snprintf.c syswrap.c
maintainer-clean: distclean maintainer-clean-lib
/strerror.c
/strlcpy.c
/system.c
+/syswrap.c
/thread.c
/win32error.c
/win32setlocale.c
libpq-events.o
# libpgport C files we always use
OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \
- thread.o
+ syswrap.o thread.o
# libpgport C files that are needed if identified by configure
OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strerror.o strlcpy.o win32error.o win32setlocale.o, $(LIBOBJS))
# backend/libpq
# For some libpgport modules, this only happens if configure decides
# the module is needed (see filter hack in OBJS, above).
-chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
+chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c syswrap.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
rm -f $@ && $(LN_S) $< .
ip.c md5.c: % : $(backend_src)/libpq/%
# Might be left over from a Win32 client-only build
rm -f pg_config_paths.h
rm -f inet_net_ntop.c noblock.c pgstrcasecmp.c pqsignal.c thread.c
- rm -f chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c open.c system.c snprintf.c strerror.c strlcpy.c win32error.c win32setlocale.c
+ rm -f chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c open.c system.c snprintf.c strerror.c strlcpy.c syswrap.c win32error.c win32setlocale.c
rm -f pgsleep.c
rm -f md5.c ip.c
rm -f encnames.c wchar.c
-@erase "$(INTDIR)\pgsleep.obj"
-@erase "$(INTDIR)\open.obj"
-@erase "$(INTDIR)\system.obj"
+ -@erase "$(INTDIR)\syswrap.obj"
-@erase "$(INTDIR)\win32error.obj"
-@erase "$(OUTDIR)\$(OUTFILENAME).lib"
-@erase "$(OUTDIR)\$(OUTFILENAME)dll.lib"
"$(INTDIR)\pgsleep.obj" \
"$(INTDIR)\open.obj" \
"$(INTDIR)\system.obj" \
+ "$(INTDIR)\syswrap.obj" \
"$(INTDIR)\win32error.obj" \
"$(INTDIR)\pthread-win32.obj"
$(CPP_PROJ) /I"." ..\..\port\system.c
<<
+"$(INTDIR)\syswrap.obj" : ..\..\port\syswrap.c
+ $(CPP) @<<
+ $(CPP_PROJ) ..\..\port\syswrap.c
+<<
+
"$(INTDIR)\win32error.obj" : ..\..\port\win32error.c
$(CPP) @<<
$(CPP_PROJ) /I"." ..\..\port\win32error.c
-@erase "$(INTDIR)\pgsleep.obj"
-@erase "$(INTDIR)\open.obj"
-@erase "$(INTDIR)\system.obj"
+ -@erase "$(INTDIR)\syswrap.obj"
-@erase "$(INTDIR)\win32error.obj"
-@erase "$(INTDIR)\win32setlocale.obj"
-@erase "$(OUTDIR)\$(OUTFILENAME).lib"
"$(INTDIR)\pgsleep.obj" \
"$(INTDIR)\open.obj" \
"$(INTDIR)\system.obj" \
+ "$(INTDIR)\syswrap.obj" \
"$(INTDIR)\win32error.obj" \
"$(INTDIR)\win32setlocale.obj" \
"$(INTDIR)\pthread-win32.obj"
$(CPP_PROJ) /I"." ..\..\port\system.c
<<
+"$(INTDIR)\syswrap.obj" : ..\..\port\syswrap.c
+ $(CPP) @<<
+ $(CPP_PROJ) ..\..\port\syswrap.c
+<<
+
"$(INTDIR)\win32error.obj" : ..\..\port\win32error.c
$(CPP) @<<
$(CPP_PROJ) /I"." ..\..\port\win32error.c
* So we undefine them here and redefine them after it's done its dirty deed.
*/
-#ifdef USE_REPL_SNPRINTF
#undef snprintf
#undef vsnprintf
-#endif
/* required for perl API */
#include "XSUB.h"
/* put back our snprintf and vsnprintf */
-#ifdef USE_REPL_SNPRINTF
#ifdef snprintf
#undef snprintf
#endif
#undef vsnprintf
#endif
#ifdef __GNUC__
-#define vsnprintf(...) pg_vsnprintf(__VA_ARGS__)
-#define snprintf(...) pg_snprintf(__VA_ARGS__)
+#define vsnprintf(...) vsnprintf_throw_on_fail(__VA_ARGS__)
+#define snprintf(...) snprintf_throw_on_fail(__VA_ARGS__)
#else
-#define vsnprintf pg_vsnprintf
-#define snprintf pg_snprintf
+#define vsnprintf vsnprintf_throw_on_fail
+#define snprintf snprintf_throw_on_fail
#endif /* __GNUC__ */
-#endif /* USE_REPL_SNPRINTF */
/* perl version and platform portability */
#define NEED_eval_pv
* So we undefine them here and redefine them after it's done its dirty deed.
*/
-#ifdef USE_REPL_SNPRINTF
#undef snprintf
#undef vsnprintf
-#endif
#if defined(_MSC_VER) && defined(_DEBUG)
/* Python uses #pragma to bring in a non-default libpython on VC++ if
#include <eval.h>
/* put back our snprintf and vsnprintf */
-#ifdef USE_REPL_SNPRINTF
#ifdef snprintf
#undef snprintf
#endif
#undef vsnprintf
#endif
#ifdef __GNUC__
-#define vsnprintf(...) pg_vsnprintf(__VA_ARGS__)
-#define snprintf(...) pg_snprintf(__VA_ARGS__)
+#define vsnprintf(...) vsnprintf_throw_on_fail(__VA_ARGS__)
+#define snprintf(...) snprintf_throw_on_fail(__VA_ARGS__)
#else
-#define vsnprintf pg_vsnprintf
-#define snprintf pg_snprintf
+#define vsnprintf vsnprintf_throw_on_fail
+#define snprintf snprintf_throw_on_fail
#endif /* __GNUC__ */
-#endif /* USE_REPL_SNPRINTF */
/*
* Used throughout, and also by the Python 2/3 porting layer, so it's easier to
OBJS = $(LIBOBJS) $(PG_CRC32C_OBJS) chklocale.o erand48.o inet_net_ntop.o \
noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o \
pgstrcasecmp.o pqsignal.o \
- qsort.o qsort_arg.o quotes.o sprompt.o tar.o thread.o
+ qsort.o qsort_arg.o quotes.o sprompt.o syswrap.o tar.o thread.o
# foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND
OBJS_SRV = $(OBJS:%.o=%_srv.o)
/* bufend == NULL is for sprintf, where we assume buf is big enough */
FILE *stream; /* eventual output destination, or NULL */
int nchars; /* # chars already sent to stream */
+ bool failed; /* call is a failure; errno is set */
} PrintfTarget;
/*
static void flushbuffer(PrintfTarget *target);
-static int dopr(PrintfTarget *target, const char *format, va_list args);
+static void dopr(PrintfTarget *target, const char *format, va_list args);
int
target.bufend = str + count - 1;
target.stream = NULL;
/* target.nchars is unused in this case */
- if (dopr(&target, fmt, args))
- {
- *(target.bufptr) = '\0';
- errno = EINVAL; /* bad format */
- return -1;
- }
+ target.failed = false;
+ dopr(&target, fmt, args);
*(target.bufptr) = '\0';
- return target.bufptr - target.bufstart;
+ return target.failed ? -1 : (target.bufptr - target.bufstart);
}
int
target.bufend = NULL;
target.stream = NULL;
/* target.nchars is unused in this case */
- if (dopr(&target, fmt, args))
- {
- *(target.bufptr) = '\0';
- errno = EINVAL; /* bad format */
- return -1;
- }
+ target.failed = false;
+ dopr(&target, fmt, args);
*(target.bufptr) = '\0';
- return target.bufptr - target.bufstart;
+ return target.failed ? -1 : (target.bufptr - target.bufstart);
}
int
target.bufend = buffer + sizeof(buffer) - 1;
target.stream = stream;
target.nchars = 0;
- if (dopr(&target, fmt, args))
- {
- errno = EINVAL; /* bad format */
- return -1;
- }
+ target.failed = false;
+ dopr(&target, fmt, args);
/* dump any remaining buffer contents */
flushbuffer(&target);
- return target.nchars;
+ return target.failed ? -1 : target.nchars;
}
int
return len;
}
-/* call this only when stream is defined */
+/*
+ * Attempt to write the entire buffer to target->stream; discard the entire
+ * buffer in any case. Call this only when target->stream is defined.
+ */
static void
flushbuffer(PrintfTarget *target)
{
size_t nc = target->bufptr - target->bufstart;
- if (nc > 0)
- target->nchars += fwrite(target->bufstart, 1, nc, target->stream);
+ if (!target->failed && nc > 0)
+ {
+ size_t written;
+
+ written = fwrite(target->bufstart, 1, nc, target->stream);
+ target->nchars += written;
+ if (written != nc)
+ target->failed = true;
+ }
target->bufptr = target->bufstart;
}
/*
* dopr(): poor man's version of doprintf
*/
-static int
+static void
dopr(PrintfTarget *target, const char *format, va_list args)
{
const char *format_start = format;
case '$':
have_dollar = true;
if (accum <= 0 || accum > NL_ARGMAX)
- return -1;
+ goto bad_format;
if (afterstar)
{
if (argtypes[accum] &&
argtypes[accum] != ATYPE_INT)
- return -1;
+ goto bad_format;
argtypes[accum] = ATYPE_INT;
last_dollar = Max(last_dollar, accum);
afterstar = false;
atype = ATYPE_INT;
if (argtypes[fmtpos] &&
argtypes[fmtpos] != atype)
- return -1;
+ goto bad_format;
argtypes[fmtpos] = atype;
last_dollar = Max(last_dollar, fmtpos);
}
{
if (argtypes[fmtpos] &&
argtypes[fmtpos] != ATYPE_INT)
- return -1;
+ goto bad_format;
argtypes[fmtpos] = ATYPE_INT;
last_dollar = Max(last_dollar, fmtpos);
}
{
if (argtypes[fmtpos] &&
argtypes[fmtpos] != ATYPE_CHARPTR)
- return -1;
+ goto bad_format;
argtypes[fmtpos] = ATYPE_CHARPTR;
last_dollar = Max(last_dollar, fmtpos);
}
{
if (argtypes[fmtpos] &&
argtypes[fmtpos] != ATYPE_DOUBLE)
- return -1;
+ goto bad_format;
argtypes[fmtpos] = ATYPE_DOUBLE;
last_dollar = Max(last_dollar, fmtpos);
}
/* Per spec, you use either all dollar or all not. */
if (have_dollar && have_non_dollar)
- return -1;
+ goto bad_format;
/*
* In dollar mode, collect the arguments in physical order.
switch (argtypes[i])
{
case ATYPE_NONE:
- return -1; /* invalid format */
+ goto bad_format;
case ATYPE_INT:
argvalues[i].i = va_arg(args, int);
break;
format = format_start;
while ((ch = *format++) != '\0')
{
+ if (target->failed)
+ break;
+
if (ch != '%')
{
dopr_outch(ch, target);
}
}
- return 0;
+ return;
+
+bad_format:
+ errno = EINVAL;
+ target->failed = true;
}
static size_t
/* we rely on regular C library's sprintf to do the basic conversion */
vallen = sprintf(convert, "%p", value);
-
- dostr(convert, vallen, target);
+ if (vallen < 0)
+ target->failed = true;
+ else
+ dostr(convert, vallen, target);
}
static void
if (pointflag)
{
- sprintf(fmt, "%%.%d%c", prec, type);
+ if (sprintf(fmt, "%%.%d%c", prec, type) < 0)
+ goto fail;
zeropadlen = precision - prec;
}
- else
- sprintf(fmt, "%%%c", type);
+ else if (sprintf(fmt, "%%%c", type) < 0)
+ goto fail;
if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
value = -value;
vallen = sprintf(convert, fmt, value);
+ if (vallen < 0)
+ goto fail;
/* If it's infinity or NaN, forget about doing any zero-padding */
if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
}
trailing_pad(&padlen, target);
+ return;
+
+fail:
+ target->failed = true;
}
static void
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * syswrap.c
+ * error-throwing wrappers around POSIX functions that rarely fail
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/syswrap.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+/* Prevent recursion */
+#undef vsnprintf
+#undef snprintf
+#undef vsprintf
+#undef sprintf
+#undef vfprintf
+#undef fprintf
+#undef printf
+
+/* When the libc primitives are lacking, use our own. */
+#ifdef USE_REPL_SNPRINTF
+#ifdef __GNUC__
+#define vsnprintf(...) pg_vsnprintf(__VA_ARGS__)
+#define snprintf(...) pg_snprintf(__VA_ARGS__)
+#define vsprintf(...) pg_vsprintf(__VA_ARGS__)
+#define sprintf(...) pg_sprintf(__VA_ARGS__)
+#define vfprintf(...) pg_vfprintf(__VA_ARGS__)
+#define fprintf(...) pg_fprintf(__VA_ARGS__)
+#define printf(...) pg_printf(__VA_ARGS__)
+#else
+#define vsnprintf pg_vsnprintf
+#define snprintf pg_snprintf
+#define vsprintf pg_vsprintf
+#define sprintf pg_sprintf
+#define vfprintf pg_vfprintf
+#define fprintf pg_fprintf
+#define printf pg_printf
+#endif
+#endif /* USE_REPL_SNPRINTF */
+
+/*
+ * We abort() in the frontend, rather than exit(), because libpq in particular
+ * has no business calling exit(). These failures had better be rare.
+ */
+#ifdef FRONTEND
+#define LIB_ERR(func) \
+do { \
+ int discard = fprintf(stderr, "%s failed: %s\n", func, strerror(errno)); \
+ (void) discard; \
+ abort(); \
+} while (0)
+#else
+#define LIB_ERR(func) elog(ERROR, "%s failed: %m", func)
+#endif
+
+int
+vsnprintf_throw_on_fail(char *str, size_t count, const char *fmt, va_list args)
+{
+ int save_errno;
+ int ret;
+
+ /*
+ * On HP-UX B.11.31, a call that truncates output returns -1 without
+ * setting errno. (SUSv2 allowed this until the approval of Base Working
+ * Group Resolution BWG98-006.) We could avoid the save and restore of
+ * errno on most platforms.
+ */
+ save_errno = errno;
+ errno = 0;
+ ret = vsnprintf(str, count, fmt, args);
+ if (ret < 0 && errno != 0)
+ LIB_ERR("vsnprintf");
+ errno = save_errno;
+ return ret;
+}
+
+int
+snprintf_throw_on_fail(char *str, size_t count, const char *fmt,...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = vsnprintf_throw_on_fail(str, count, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+int
+vsprintf_throw_on_fail(char *str, const char *fmt, va_list args)
+{
+ int ret;
+
+ ret = vsprintf(str, fmt, args);
+ if (ret < 0)
+ LIB_ERR("vsprintf");
+ return ret;
+}
+
+int
+sprintf_throw_on_fail(char *str, const char *fmt,...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = vsprintf_throw_on_fail(str, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+int
+vfprintf_throw_on_fail(FILE *stream, const char *fmt, va_list args)
+{
+ int ret;
+
+ ret = vfprintf(stream, fmt, args);
+ if (ret < 0)
+ LIB_ERR("vfprintf");
+ return ret;
+}
+
+int
+fprintf_throw_on_fail(FILE *stream, const char *fmt,...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = vfprintf_throw_on_fail(stream, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+int
+printf_throw_on_fail(const char *fmt,...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = vfprintf_throw_on_fail(stdout, fmt, args);
+ va_end(args);
+ return ret;
+}
erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
- sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
+ sprompt.c syswrap.c tar.c thread.c getopt.c getopt_long.c dirent.c
win32env.c win32error.c win32setlocale.c);
push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');