### 5.24 `strerror`—convert error number to string

Synopsis

         #include <string.h>
         char *strerror(int errnum);
         char *_strerror_r(struct _reent ptr, int errnum,
             int internal, int *error);

Description
`strerror` converts the error number errnum into a string. The value of errnum is usually a copy of `errno`. If `errnum` is not a known error number, the result points to an empty string.

This implementation of `strerror` prints out the following strings for each of the values defined in ``errno.h`':

`0`
  Success
`E2BIG`
  Arg list too long
`EACCES`
  Permission denied
`EADDRINUSE`
  Address already in use
`EADV`
  Advertise error
`EAFNOSUPPORT`
  Address family not supported by protocol family
`EAGAIN`
  No more processes
`EALREADY`
  Socket already connected
`EBADF`
  Bad file number
`EBADMSG`
  Bad message
`EBUSY`
  Device or resource busy
`ECHILD`
  No children
`ECOMM`
  Communication error
`ECONNABORTED`
  Software caused connection abort
`ECONNREFUSED`
  Connection refused
`EDEADLK`
  Deadlock
`EDESTADDRREQ`
  Destination address required
`EEXIST`
  File exists
`EDOM`
  Math argument
`EFAULT`
  Bad address
`EFBIG`
  File too large
`EHOSTDOWN`
  Host is down
`EHOSTUNREACH`
  Host is unreachable
`EIDRM`
  Identifier removed
`EINPROGRESS`
  Connection already in progress
`EINTR`
  Interrupted system call
`EINVAL`
  Invalid argument
`EIO`
  I/O error
`EISCONN`
  Socket is already connected
`EISDIR`
  Is a directory
`ELIBACC`
  Cannot access a needed shared library
`ELIBBAD`
  Accessing a corrupted shared library
`ELIBEXEC`
  Cannot exec a shared library directly
`ELIBMAX`
  Attempting to link in more shared libraries than system limit
`ELIBSCN`
  `.lib` section in a.out corrupted
`EMFILE`
  Too many open files
`EMLINK`
  Too many links
`EMSGSIZE`
  Message too long
`EMULTIHOP`
  Multihop attempted
`ENAMETOOLONG`
  File or path name too long
`ENETDOWN`
  Network interface not configured
`ENETUNREACH`
  Network is unreachable
`ENFILE`
  Too many open files in system
`ENODEV`
  No such device
`ENOENT`
  No such file or directory
`ENOEXEC`
  Exec format error
`ENOLCK`
  No lock
`ENOLINK`
  Virtual circuit is gone
`ENOMEM`
  Not enough space
`ENOMSG`
  No message of desired type
`ENONET`
  Machine is not on the network
`ENOPKG`
  No package
`ENOPROTOOPT`
  Protocol not available
`ENOSPC`
  No space left on device
`ENOSR`
  No stream resources
`ENOSTR`
  Not a stream
`ENOSYS`
  Function not implemented
`ENOTBLK`
  Block device required
`ENOTCONN`
  Socket is not connected
`ENOTDIR`
  Not a directory
`ENOTEMPTY`
  Directory not empty
`ENOTSOCK`
  Socket operation on non-socket
`ENOTSUP`
  Not supported
`ENOTTY`
  Not a character device
`ENXIO`
  No such device or address
`EPERM`
  Not owner
`EPIPE`
  Broken pipe
`EPROTO`
  Protocol error
`EPROTOTYPE`
  Protocol wrong type for socket
`EPROTONOSUPPORT`
  Unknown protocol
`ERANGE`
  Result too large
`EREMOTE`
  Resource is remote
`EROFS`
  Read-only file system
`ESHUTDOWN`
  Can't send after socket shutdown
`ESOCKTNOSUPPORT`
  Socket type not supported
`ESPIPE`
  Illegal seek
`ESRCH`
  No such process
`ESRMNT`
  Srmount error
`ETIME`
  Stream ioctl timeout
`ETIMEDOUT`
  Connection timed out
`ETXTBSY`
  Text file busy
`EXDEV`
  Cross-device link
`ECANCELED`
  Operation canceled
`ENOTRECOVERABLE`
  State not recoverable
`EOWNERDEAD`
  Previous owner died
`ESTRPIPE`
  Strings pipe error

`_strerror_r` is a reentrant version of the above.

Returns
This function returns a pointer to a string. Your application must not modify that string.

Portability
ANSI C requires `strerror`, but does not specify the strings used for each error number.

Although this implementation of `strerror` is reentrant (depending on `_user_strerror`), ANSI C declares that subsequent calls to `strerror` may overwrite the result string; therefore portable code cannot depend on the reentrancy of this subroutine.

Although this implementation of `strerror` guarantees a non-null result with a NUL-terminator, some implementations return `NULL` on failure. Although POSIX allows `strerror` to set `errno` to EINVAL on failure, this implementation does not do so (unless you provide `_user_strerror`).

POSIX recommends that unknown errnum result in a message including that value, however it is not a requirement and this implementation does not provide that information (unless you provide `_user_strerror`).

This implementation of `strerror` provides for user-defined extensibility. `errno.h` defines __ELASTERROR, which can be used as a base for user-defined error values. If the user supplies a routine named `_user_strerror`, and errnum passed to `strerror` does not match any of the supported values, `_user_strerror` is called with three arguments. The first is of type int, and is the errnum value unknown to `strerror`. The second is of type int, and matches the internal argument of `_strerror_r`; this should be zero if called from `strerror` and non-zero if called from any other function; `_user_strerror` can use this information to satisfy the POSIX rule that no other standardized function can overwrite a static buffer reused by `strerror`. The third is of type int *, and matches the error argument of `_strerror_r`; if a non-zero value is stored into that location (usually EINVAL), then `strerror` will set `errno` to that value, and the XPG variant of `strerror_r` will return that value instead of zero or ERANGE. `_user_strerror` returns a char * value; returning NULL implies that the user function did not choose to handle errnum. The default `_user_strerror` returns NULL for all input values. Note that `_user_sterror` must be thread-safe, and only denote errors via the third argument rather than modifying `errno`, if `strerror` and `strerror_r` are are to comply with POSIX.

`strerror` requires no supporting OS subroutines.