warnx: Save errno across calls that might change it.

When warn() family of functions is being used after err_set_file() has
been set to, for example, /dev/null, errno is being clobbered,
rendering it unreliable after, for example, procstat_getpathname()
when it is supposed to emit a warning. Then the errno is changed to
Inappropriate ioctl for device, destroying the original value (via
calls to fprintf()functions).

Submitted by: Juraj Lutter
Differential Revision: https://reviews.freebsd.org/D26871
This commit is contained in:
Warner Losh 2020-10-23 23:56:00 +00:00
parent 3e7449a37b
commit 4e0771b2da

View File

@ -161,6 +161,9 @@ warnc(int code, const char *fmt, ...)
void void
vwarnc(int code, const char *fmt, va_list ap) vwarnc(int code, const char *fmt, va_list ap)
{ {
static int saved_errno;
saved_errno = errno;
if (err_file == NULL) if (err_file == NULL)
err_set_file(NULL); err_set_file(NULL);
fprintf(err_file, "%s: ", _getprogname()); fprintf(err_file, "%s: ", _getprogname());
@ -169,6 +172,7 @@ vwarnc(int code, const char *fmt, va_list ap)
fprintf(err_file, ": "); fprintf(err_file, ": ");
} }
fprintf(err_file, "%s\n", strerror(code)); fprintf(err_file, "%s\n", strerror(code));
errno = saved_errno;
} }
void void
@ -183,10 +187,14 @@ warnx(const char *fmt, ...)
void void
vwarnx(const char *fmt, va_list ap) vwarnx(const char *fmt, va_list ap)
{ {
static int saved_errno;
saved_errno = errno;
if (err_file == NULL) if (err_file == NULL)
err_set_file(NULL); err_set_file(NULL);
fprintf(err_file, "%s: ", _getprogname()); fprintf(err_file, "%s: ", _getprogname());
if (fmt != NULL) if (fmt != NULL)
vfprintf(err_file, fmt, ap); vfprintf(err_file, fmt, ap);
fprintf(err_file, "\n"); fprintf(err_file, "\n");
errno = saved_errno;
} }