6

I have seen Symbolic errno to String - Stack Overflow, so even if that question is bash related, I can already tell that this isn't trivial; but just to confirm:

Is there a C API function, which like strerror() will accept the numeric errno as argument - but which will print the mnemonic (e.g. EINVAL) instead of the error description string (e.g. "Invalid argument")?

As an example, I'd like

printf("Number: %d (%s): '%s'\n", 22, strerror_mnemonic(22), strerror(22) );

... to print:

Number: 22 (EINVAL): 'Invalid argument'

... where strerror_mnemonic is pseudocode for the C function I'm looking for.

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278
  • 1
    "Invalid argument" is useful. "EINVAL" is not. Do not bother to do this, please. It is not helpful. – William Pursell Feb 24 '14 at 17:48
  • 2
    EINVAL is useful to certain audiences. For example, you can grep for EINVAL in code. – slim Feb 24 '14 at 17:50
  • 2
    There's no function that does this. – nos Feb 24 '14 at 17:51
  • 2
    there is no standard way to do this. However, if the error codes are guaranteed to be identical on the platforms you develop for, you could manually create an array of `const char*`s and print the array at the index of `errno`. – Andreas Grapentin Feb 24 '14 at 17:51
  • 2
    I think it *is* useful to add `EINVAL` etc. Otherwise if you are wondering why `select` (or similar) is returning a given string, you need to first translate back from that string into an error code, then look at the documentation. As for not being useful to end users, how does "Invalid argument" help an end user? – abligh Feb 24 '14 at 18:01

5 Answers5

4

The second part of your question is answered by strerror (as you point out), or better strerror_r, but in glibc at least you can simply use %m as a format specifier.

The first part is more interesting, i.e. how do you get the name of the C constant for the error. I believe there is no way to do that using standard glibc. You could construct your own static array or hash table to do this relatively easily.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • Thanks for the answer @abligh - I accepted the other answer since it mentions that you'd need an extra lookup table, which is what the scripting solutions do. Cheers! – sdaau Feb 24 '14 at 18:30
2

Unfortunately not; there is no introspection support for the E error macros.

You can do this trivially in Python:

import errno
print(errno.errorcode[errno.EPERM])

This is because the Python maintainers have gone to the trouble of generating a lookup table: http://hg.python.org/cpython/file/tip/Modules/errnomodule.c

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Thanks for the answer, @ecatmur - I will be accepting this because it confirms there is no such support, and how come Python has it. Cheers! – sdaau Feb 24 '14 at 18:29
2

What's the problem?

perl -ne 'print "$1\n" if /^#\s*define\s+(E[A-Z0-9]+)/' < /usr/include/sys/errno.h | sort | uniq | perl -ne 'chomp; print "    { $_, \"$_\" }\n"'

This unix shell command printa out E* defines from /usr/include/sys/errno.h (where actual defines live) in form { EINVAL, "EINVAL" },. You may then wrap it into an array:

struct errno_str_t {
    int code;
    const char *str;
} errnos[] = {
    { EINVAL, "EINVAL" },
    ...
};

And sort by errno value at runtime if needed. If you want to be portable (to some extent), consider making this a part of build process. Do not worry, that's the true unix way of doing this :)

user3125367
  • 2,920
  • 1
  • 17
  • 17
  • Thanks for that @user3125367 - your approach (and others) require an extra scripting step, in order generate a lookup table ; but I was wandering if there was already a standard "built-in" C method. Cheers! – sdaau Feb 24 '14 at 18:34
  • 2
    This is not portable; in fact, `sys/errno.h` is a nonstandard location and need not even exist. There are semi-portable ways to generate a list by passing the right preprocessor options and processing `#include ` but this is also rather ugly and hackish. – R.. GitHub STOP HELPING ICE Feb 24 '14 at 19:04
  • 2
    @R.. I know, the whole point is in the second line of my answer, not pretending to be absolutely portable (thus *to some extent*). But not having that mapping in standards at all or defining it by hand is even less portable. – user3125367 Feb 24 '14 at 20:23
1

You want strerror(3). You may sometimes be interested by perror(3). BTW, the errno(3) man page mentions them.

You probably don't need to display the EINVAL mnemonic (unless you care about C code generation). If you did, make a function for that (essentially, a switch statement).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    OP knows what strerror is. I'm sure they know how they could write a switch statement based on errno.h. They are asking if there is an implementation of this already. My guess is not. – slim Feb 24 '14 at 17:52
  • Thanks for that, @ BasileStarynkevitch ; like @slim commented, I was wandering if an implementation existed, and now it seems it is confirmed it does not. Cheers! – sdaau Feb 24 '14 at 18:31
1

Here is the function that returns errno as mnemonic: https://paste.ubuntu.com/26170061/

Thank me later.

the kamilz
  • 1,860
  • 1
  • 15
  • 19