cprintferrnostrerror

How can I print the symbolic name of an errno in C?


I can use perror() or strerror() to print the "human readable" error message belonging to an errno, but what if I also want to print the symbolic name (e.g., "EAGAIN") of the errno?

Any convenient function or macro to do that?

Re-edit from the future: You're better off using the strerrorname_np() recently added to glibc (see accepted answer), or the errnoname library (previously accepted answer), rather than this hacky code I came up with before those options existed:

#include <ctype.h>
#include <errno.h>
#include <stdio.h>

int get_errno_name(char *buf, int buf_size) {
    // Using the linux-only gawk instead of awk, because of the convenient
    // match() functionality. For Posix portability, use a different recipe...
    char cmd[] = "e=       && " // errno to be inserted here (max digits = 6)
                 "echo '#include <errno.h>' | "
                 "gcc -dM -E - | " // optionally, use $CC inead of gcc
                 "gawk \"match(\\$0, /^#[[:space:]]*define[[:space:]]+"
                     "(E[[:alnum:]]+)[[:space:]]+$e($|[^[:alnum:]])/, m) "
                     "{ print m[1] }\"";
    {
        // Insert the errno as the "e" shell variable in the command above.
        int errno_digit_c = snprintf(cmd + 2, 6, "%d", errno);
        if (errno_digit_c < 1) {
            fprintf(stderr, "Failed to stringify an errno "
                            "in get_errno_name().\n");
            return -1;
        }
        // Replace the inserted terminating '\0' with whitespace
        cmd[errno_digit_c + 2] = ' ';
    }
    FILE *f = popen(cmd, "r");
    if (f == NULL) {
        perror("Failed to popen() in get_errno_name()");
        return -1;
    }
    int read_size = 0, c;
    while ((c = getc(f)) != EOF) {
        if (isalnum(c)) {
            buf[read_size++] = c;
            if (read_size + 1 > buf_size) {
                fprintf(stderr, "Read errno name is larger than the character "
                                "buffer supplied to get_errno_name().\n");
                return -1;
            }
        }
    }
    buf[read_size++] = '\0';
    if (pclose(f) == -1) {
        perror("Failed to pclose() in get_errno_name()");
        return -1;
    }
    return read_size;
}

Solution

  • glibc provides a function for that (a GNU extension): strerrorname_np().

    It is declared in <string.h>.

    It returns the errno name for valid values, or NULL for invalid ones.

    man strerrorname_np

    It was added in glibc 2.32.