#include "namespace.h"
#include <sys/exterrvar.h>
#include <err.h>
#include <errno.h>
#include <exterr.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "un-namespace.h"
#include "libc_private.h"
static FILE *err_file;
static void (*err_exit)(int);
static void verrci(bool doexterr, int eval, int code, const char *fmt,
va_list ap) __printf0like(4, 0) __dead2;
static void vwarnci(bool doexterr, int code, const char *fmt, va_list ap)
__printf0like(3, 0);
void
err_set_file(void *fp)
{
if (fp)
err_file = fp;
else
err_file = stderr;
}
void
err_set_exit(void (*ef)(int))
{
err_exit = ef;
}
__weak_reference(_err, err);
void
_err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrci(true, eval, errno, fmt, ap);
va_end(ap);
}
void
verr(int eval, const char *fmt, va_list ap)
{
verrci(true, eval, errno, fmt, ap);
}
void
errc(int eval, int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrci(false, eval, code, fmt, ap);
va_end(ap);
}
void
verrc(int eval, int code, const char *fmt, va_list ap)
{
verrci(false, eval, code, fmt, ap);
}
static void
vexterr(bool doexterr, int code, const char *fmt, va_list ap)
{
char exterr[UEXTERROR_MAXLEN];
int extstatus;
if (doexterr)
extstatus = uexterr_gettext(exterr, sizeof(exterr));
if (err_file == NULL)
err_set_file(NULL);
fprintf(err_file, "%s: ", _getprogname());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s", strerror(code));
if (doexterr && extstatus == 0 && exterr[0] != '\0')
fprintf(err_file, " (%s)", exterr);
fprintf(err_file, "\n");
}
static void
verrci(bool doexterr, int eval, int code, const char *fmt, va_list ap)
{
vexterr(doexterr, code, fmt, ap);
if (err_exit)
err_exit(eval);
exit(eval);
}
void
errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrx(eval, fmt, ap);
va_end(ap);
}
void
verrx(int eval, const char *fmt, va_list ap)
{
if (err_file == NULL)
err_set_file(NULL);
fprintf(err_file, "%s: ", _getprogname());
if (fmt != NULL)
vfprintf(err_file, fmt, ap);
fprintf(err_file, "\n");
if (err_exit)
err_exit(eval);
exit(eval);
}
__weak_reference(_warn, warn);
void
_warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnci(true, errno, fmt, ap);
va_end(ap);
}
void
vwarn(const char *fmt, va_list ap)
{
vwarnci(true, errno, fmt, ap);
}
void
warnc(int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnc(code, fmt, ap);
va_end(ap);
}
void
vwarnc(int code, const char *fmt, va_list ap)
{
vwarnci(false, code, fmt, ap);
}
static void
vwarnci(bool doexterr, int code, const char *fmt, va_list ap)
{
int saved_errno;
saved_errno = errno;
vexterr(doexterr, code, fmt, ap);
errno = saved_errno;
}
void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(const char *fmt, va_list ap)
{
int saved_errno;
saved_errno = errno;
if (err_file == NULL)
err_set_file(NULL);
fprintf(err_file, "%s: ", _getprogname());
if (fmt != NULL)
vfprintf(err_file, fmt, ap);
fprintf(err_file, "\n");
errno = saved_errno;
}