diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2025-12-28 02:23:27 +0200 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2025-12-29 03:16:25 +0200 |
| commit | 42210fe8dcd4684a45e0e4db1b8194e291dc8fda (patch) | |
| tree | 8c478140af6c079762c73b14885fa76165b601c5 /lib | |
| parent | 8bff95f3ce0396ff40b4f7d943ea856ac3f846c3 (diff) | |
exterror: Add EXTERROR_VERBOSE env variable to control verbosity
If the variable is set and the process is not suid, __uexterr_format(),
used by err(3), prints errno/category/source line/pX always, not only
when there is no kernel message provided.
Requested by: mckusick
Reviewed by: emaste, mckusick
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D54380
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libc/gen/uexterr_format.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/lib/libc/gen/uexterr_format.c b/lib/libc/gen/uexterr_format.c index 68cd2abfe312..3321fd80616d 100644 --- a/lib/libc/gen/uexterr_format.c +++ b/lib/libc/gen/uexterr_format.c @@ -11,26 +11,69 @@ #include <sys/types.h> #include <sys/exterrvar.h> #include <exterr.h> +#include <stdbool.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <unistd.h> + +static const char exterror_verbose_name[] = "EXTERROR_VERBOSE"; +enum exterr_verbose_state { + EXTERR_VERBOSE_UNKNOWN = 100, + EXTERR_VERBOSE_DEFAULT, + EXTERR_VERBOSE_ALLOW, +}; +static enum exterr_verbose_state exterror_verbose = EXTERR_VERBOSE_UNKNOWN; + +static void +exterr_verbose_init(void) +{ + /* + * No need to care about thread-safety, the result is + * idempotent. + */ + if (exterror_verbose != EXTERR_VERBOSE_UNKNOWN) + return; + if (issetugid()) { + exterror_verbose = EXTERR_VERBOSE_DEFAULT; + } else if (getenv(exterror_verbose_name) != NULL) { + exterror_verbose = EXTERR_VERBOSE_ALLOW; + } else { + exterror_verbose = EXTERR_VERBOSE_DEFAULT; + } +} int __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz) { + bool has_msg; + if (bufsz > UEXTERROR_MAXLEN) bufsz = UEXTERROR_MAXLEN; if (ue->error == 0) { strlcpy(buf, "", bufsz); return (0); } - if (ue->msg[0] == '\0') { - snprintf(buf, bufsz, + exterr_verbose_init(); + has_msg = ue->msg[0] != '\0'; + + if (has_msg) { + snprintf(buf, bufsz, ue->msg, (uintmax_t)ue->p1, + (uintmax_t)ue->p2); + } else { + strlcpy(buf, "", bufsz); + } + + if (exterror_verbose == EXTERR_VERBOSE_ALLOW || !has_msg) { + char lbuf[128]; + + snprintf(lbuf, sizeof(lbuf), "errno %d category %u (src line %u) p1 %#jx p2 %#jx", ue->error, ue->cat, ue->src_line, (uintmax_t)ue->p1, (uintmax_t)ue->p2); - } else { - snprintf(buf, bufsz, ue->msg, (uintmax_t)ue->p1, - (uintmax_t)ue->p2); + if (has_msg) + strlcat(buf, " ", bufsz); + strlcat(buf, lbuf, bufsz); } return (0); } |
