#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <err.h>
#include <sys/debug.h>
static FILE *stream = stderr;
typedef enum variant {
VARIANT_ = 0,
VARIANT_C,
VARIANT_X,
VARIANT_V,
VARIANT_VC,
VARIANT_VX,
} variant_t;
void
usage(void)
{
(void) fprintf(stderr,
"usage: err [-e errno] [-x code] [-v variant]\n");
exit(EXIT_FAILURE);
}
void
callback_func(int code)
{
(void) fprintf(stream, "CALLBACK %d\n", code);
}
void
xtest(variant_t variant, int errcode, int exitcode, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
switch (variant) {
case VARIANT_V:
errno = errcode;
if (exitcode != 0)
verr(exitcode, fmt, va);
else
vwarn(fmt, va);
break;
case VARIANT_VC:
errno = 0;
if (exitcode != 0)
verrc(exitcode, errcode, fmt, va);
else
vwarnc(errcode, fmt, va);
break;
case VARIANT_VX:
if (exitcode != 0)
verrx(exitcode, fmt, va);
else
vwarnx(fmt, va);
break;
default:
errx(EXIT_FAILURE, "Unhandled variant in %s", __func__);
}
va_end(va);
}
int
main(int argc, char **argv)
{
int errcode = 0;
int exitcode = 0;
variant_t variant = VARIANT_;
const char *errstr;
long long num;
int ch;
while ((ch = getopt(argc, argv, "e:v:x:")) != -1) {
switch (ch) {
case 'e':
num = strtonum(optarg, 0, 127, &errstr);
if (errstr != NULL)
errx(EXIT_FAILURE, "-x: %s", errstr);
errcode = (int)num;
break;
case 'v':
num = strtonum(optarg, 0, VARIANT_VX, &errstr);
if (errstr != NULL)
errx(EXIT_FAILURE, "-v: %s", errstr);
switch (num) {
case VARIANT_:
variant = VARIANT_;
break;
case VARIANT_C:
variant = VARIANT_C;
break;
case VARIANT_X:
variant = VARIANT_X;
break;
case VARIANT_V:
variant = VARIANT_V;
break;
case VARIANT_VC:
variant = VARIANT_VC;
break;
case VARIANT_VX:
variant = VARIANT_VX;
break;
default:
errx(EXIT_FAILURE, "Unknown variant %lld", num);
}
break;
case 'x':
num = strtonum(optarg, 0, 127, &errstr);
if (errstr != NULL)
errx(EXIT_FAILURE, "-x: %s", errstr);
exitcode = (int)num;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (argc > 0)
errx(EXIT_FAILURE, "Unexpected argument '%s'.", argv[1]);
switch (variant) {
case VARIANT_:
errno = errcode;
if (exitcode != 0)
err(exitcode, "E/%d/%d", variant, exitcode);
else
warn("W/%d", variant);
break;
case VARIANT_C:
errno = 0;
if (exitcode != 0)
errc(exitcode, errcode, "E/%d/%d", variant, exitcode);
else
warnc(errcode, "W/%d", variant);
break;
case VARIANT_X:
if (exitcode != 0)
errx(exitcode, "E/%d/%d", variant, exitcode);
else
warnx("W/%d", variant);
break;
case VARIANT_V:
case VARIANT_VC:
case VARIANT_VX:
if (exitcode != 0) {
xtest(variant, errcode, exitcode, "E/%d/%d", variant,
exitcode);
} else {
xtest(variant, errcode, exitcode, "W/%d", variant);
}
break;
}
return (0);
}