1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/src/ulib/base/base_error.c
stefanocasazza 9c8b17c297 fix
2018-04-05 19:00:12 +02:00

832 lines
22 KiB
C

/* ============================================================================
//
// = LIBRARY
// ULib - c library
//
// = FILENAME
// base_error.c
//
// = AUTHOR
// Stefano Casazza
//
// ============================================================================ */
/*
#define DEBUG_DEBUG
*/
#include <ulib/base/error.h>
#ifdef HAVE_SYSEXITS_H
# include <sysexits.h>
#else
# include <ulib/base/replace/sysexits.h>
#endif
#define U_STR_ERROR "\n" \
" ----------------------------------- \n" \
"| ***** **** **** *** **** |\n" \
"| * * * * * * * * * |\n" \
"| ***** **** **** * * **** |\n" \
"| * * * * * * * * * |\n" \
"| ***** * * * * *** * * |\n" \
" ----------------------------------- \n"
void u_printError(void)
{
U_INTERNAL_TRACE("u_printError()")
#ifndef _MSWINDOWS_
if (u_is_tty) (void) write(STDERR_FILENO, U_CONSTANT_TO_PARAM(U_RED_STR));
#endif
(void) write(STDERR_FILENO, U_CONSTANT_TO_PARAM(U_STR_ERROR));
#ifndef _MSWINDOWS_
if (u_is_tty) (void) write(STDERR_FILENO, U_CONSTANT_TO_PARAM(U_RESET_STR));
#endif
}
/**
* Maps errno number to an error message string, the contents of which are implementation defined.
* The returned string is only guaranteed to be valid only until the next call to function
*/
void u_getSysError(uint32_t* restrict len)
{
/**
* Translation table for errno values. See intro(2) in most UNIX systems Programmers Reference Manuals.
* Note that this table is generally only accessed when it is used at runtime to initialize errno name and
* message tables that are indexed by errno value.
* Not all of these errnos will exist on all systems. This table is the only thing that should have to be
* updated as new error numbers are introduced. It's sort of ugly, but at least its portable
*/
struct error_info
{
int value; /* The numeric value from <errno.h> */
const char* restrict name; /* The equivalent symbolic value */
# ifndef HAVE_STRERROR
const char* restrict msg; /* Short message about this value */
# endif
};
#ifdef HAVE_STRERROR
# define U_ERR_ENTRY(name,msg) {name, #name}
#else
# define U_ERR_ENTRY(name,msg) {name, #name, msg}
#endif
static const struct error_info error_table[] = {
#if defined(EPERM)
U_ERR_ENTRY(EPERM, "Not owner"),
#endif
#if defined(ENOENT)
U_ERR_ENTRY(ENOENT, "No such file or directory"),
#endif
#if defined(ESRCH)
U_ERR_ENTRY(ESRCH, "No such process"),
#endif
#if defined(EINTR)
U_ERR_ENTRY(EINTR, "Interrupted system call"),
#endif
#if defined(EIO)
U_ERR_ENTRY(EIO, "I/O error"),
#endif
#if defined(ENXIO)
U_ERR_ENTRY(ENXIO, "No such device or address"),
#endif
#if defined(E2BIG)
U_ERR_ENTRY(E2BIG, "Argument list too long"),
#endif
#if defined(ENOEXEC)
U_ERR_ENTRY(ENOEXEC, "Exec format error"),
#endif
#if defined(EBADF)
U_ERR_ENTRY(EBADF, "Bad file number"),
#endif
#if defined(ECHILD)
U_ERR_ENTRY(ECHILD, "No child processes"),
#endif
#if defined(EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */
U_ERR_ENTRY(EWOULDBLOCK, "Operation would block"),
#endif
#if defined(EAGAIN)
U_ERR_ENTRY(EAGAIN, "No more processes"),
#endif
#if defined(ENOMEM)
U_ERR_ENTRY(ENOMEM, "Cannot allocate memory"),
#endif
#if defined(EACCES)
U_ERR_ENTRY(EACCES, "Permission denied"),
#endif
#if defined(EFAULT)
U_ERR_ENTRY(EFAULT, "Bad address"),
#endif
#if defined(ENOTBLK)
U_ERR_ENTRY(ENOTBLK, "Block device required"),
#endif
#if defined(EBUSY)
U_ERR_ENTRY(EBUSY, "Device busy"),
#endif
#if defined(EEXIST)
U_ERR_ENTRY(EEXIST, "File exists"),
#endif
#if defined(EXDEV)
U_ERR_ENTRY(EXDEV, "Cross-device link"),
#endif
#if defined(ENODEV)
U_ERR_ENTRY(ENODEV, "No such device"),
#endif
#if defined(ENOTDIR)
U_ERR_ENTRY(ENOTDIR, "Not a directory"),
#endif
#if defined(EISDIR)
U_ERR_ENTRY(EISDIR, "Is a directory"),
#endif
#if defined(EINVAL)
U_ERR_ENTRY(EINVAL, "Invalid argument"),
#endif
#if defined(ENFILE)
U_ERR_ENTRY(ENFILE, "File table overflow"),
#endif
#if defined(EMFILE)
U_ERR_ENTRY(EMFILE, "Too many open files"),
#endif
#if defined(ENOTTY)
U_ERR_ENTRY(ENOTTY, "Not a typewriter"),
#endif
#if defined(ETXTBSY)
U_ERR_ENTRY(ETXTBSY, "Text file busy"),
#endif
#if defined(EFBIG)
U_ERR_ENTRY(EFBIG, "File too large"),
#endif
#if defined(ENOSPC)
U_ERR_ENTRY(ENOSPC, "No space left on device"),
#endif
#if defined(ESPIPE)
U_ERR_ENTRY(ESPIPE, "Illegal seek"),
#endif
#if defined(EROFS)
U_ERR_ENTRY(EROFS, "Read-only file system"),
#endif
#if defined(EMLINK)
U_ERR_ENTRY(EMLINK, "Too many links"),
#endif
#if defined(EPIPE)
U_ERR_ENTRY(EPIPE, "Broken pipe"),
#endif
#if defined(EDOM)
U_ERR_ENTRY(EDOM, "Math argument out of domain of func"),
#endif
#if defined(ERANGE)
U_ERR_ENTRY(ERANGE, "Math result not representable"),
#endif
#if defined(ENOMSG)
U_ERR_ENTRY(ENOMSG, "No message of desired type"),
#endif
#if defined(EIDRM)
U_ERR_ENTRY(EIDRM, "Identifier removed"),
#endif
#if defined(ECHRNG)
U_ERR_ENTRY(ECHRNG, "Channel number out of range"),
#endif
#if defined(EL2NSYNC)
U_ERR_ENTRY(EL2NSYNC, "Level 2 not synchronized"),
#endif
#if defined(EL3HLT)
U_ERR_ENTRY(EL3HLT, "Level 3 halted"),
#endif
#if defined(EL3RST)
U_ERR_ENTRY(EL3RST, "Level 3 reset"),
#endif
#if defined(ELNRNG)
U_ERR_ENTRY(ELNRNG, "Link number out of range"),
#endif
#if defined(EUNATCH)
U_ERR_ENTRY(EUNATCH, "Protocol driver not attached"),
#endif
#if defined(ENOCSI)
U_ERR_ENTRY(ENOCSI, "No CSI structure available"),
#endif
#if defined(EL2HLT)
U_ERR_ENTRY(EL2HLT, "Level 2 halted"),
#endif
#if defined(EDEADLK)
U_ERR_ENTRY(EDEADLK, "Deadlock condition"),
#endif
#if defined(ENOLCK)
U_ERR_ENTRY(ENOLCK, "No record locks available"),
#endif
#if defined(EBADE)
U_ERR_ENTRY(EBADE, "Invalid exchange"),
#endif
#if defined(EBADR)
U_ERR_ENTRY(EBADR, "Invalid request descriptor"),
#endif
#if defined(EXFULL)
U_ERR_ENTRY(EXFULL, "Exchange full"),
#endif
#if defined(ENOANO)
U_ERR_ENTRY(ENOANO, "No anode"),
#endif
#if defined(EBADRQC)
U_ERR_ENTRY(EBADRQC, "Invalid request code"),
#endif
#if defined(EBADSLT)
U_ERR_ENTRY(EBADSLT, "Invalid slot"),
#endif
#if defined(EDEADLOCK)
U_ERR_ENTRY(EDEADLOCK, "File locking deadlock error"),
#endif
#if defined(EBFONT)
U_ERR_ENTRY(EBFONT, "Bad font file format"),
#endif
#if defined(ENOSTR)
U_ERR_ENTRY(ENOSTR, "Device not a stream"),
#endif
#if defined(ENODATA)
U_ERR_ENTRY(ENODATA, "No data available"),
#endif
#if defined(ETIME)
U_ERR_ENTRY(ETIME, "Timer expired"),
#endif
#if defined(ENOSR)
U_ERR_ENTRY(ENOSR, "Out of streams resources"),
#endif
#if defined(ENONET)
U_ERR_ENTRY(ENONET, "Machine is not on the network"),
#endif
#if defined(ENOPKG)
U_ERR_ENTRY(ENOPKG, "Package not installed"),
#endif
#if defined(EREMOTE)
U_ERR_ENTRY(EREMOTE, "Object is remote"),
#endif
#if defined(ENOLINK)
U_ERR_ENTRY(ENOLINK, "Link has been severed"),
#endif
#if defined(EADV)
U_ERR_ENTRY(EADV, "Advertise error"),
#endif
#if defined(ESRMNT)
U_ERR_ENTRY(ESRMNT, "Srmount error"),
#endif
#if defined(ECOMM)
U_ERR_ENTRY(ECOMM, "Communication error on send"),
#endif
#if defined(EPROTO)
U_ERR_ENTRY(EPROTO, "Protocol error"),
#endif
#if defined(EMULTIHOP)
U_ERR_ENTRY(EMULTIHOP, "Multihop attempted"),
#endif
#if defined(EDOTDOT)
U_ERR_ENTRY(EDOTDOT, "RFS specific error"),
#endif
#if defined(EBADMSG)
U_ERR_ENTRY(EBADMSG, "Not a data message"),
#endif
#if defined(ENAMETOOLONG)
U_ERR_ENTRY(ENAMETOOLONG, "File name too long"),
#endif
#if defined(EOVERFLOW)
U_ERR_ENTRY(EOVERFLOW, "Value too large for defined data type"),
#endif
#if defined(ENOTUNIQ)
U_ERR_ENTRY(ENOTUNIQ, "Name not unique on network"),
#endif
#if defined(EBADFD)
U_ERR_ENTRY(EBADFD, "File descriptor in bad state"),
#endif
#if defined(EREMCHG)
U_ERR_ENTRY(EREMCHG, "Remote address changed"),
#endif
#if defined(ELIBACC)
U_ERR_ENTRY(ELIBACC, "Cannot access a needed shared library"),
#endif
#if defined(ELIBBAD)
U_ERR_ENTRY(ELIBBAD, "Accessing a corrupted shared library"),
#endif
#if defined(ELIBSCN)
U_ERR_ENTRY(ELIBSCN, ".lib section in a.out corrupted"),
#endif
#if defined(ELIBMAX)
U_ERR_ENTRY(ELIBMAX, "Attempting to link in too many shared libraries"),
#endif
#if defined(ELIBEXEC)
U_ERR_ENTRY(ELIBEXEC, "Cannot exec a shared library directly"),
#endif
#if defined(EILSEQ)
U_ERR_ENTRY(EILSEQ, "Illegal byte sequence"),
#endif
#if defined(ENOSYS)
U_ERR_ENTRY(ENOSYS, "Operation not applicable"),
#endif
#if defined(ELOOP)
U_ERR_ENTRY(ELOOP, "Too many symbolic links encountered"),
#endif
#if defined(ERESTART)
U_ERR_ENTRY(ERESTART, "Interrupted system call should be restarted"),
#endif
#if defined(ESTRPIPE)
U_ERR_ENTRY(ESTRPIPE, "Streams pipe error"),
#endif
#if defined(ENOTEMPTY)
U_ERR_ENTRY(ENOTEMPTY, "Directory not empty"),
#endif
#if defined(EUSERS)
U_ERR_ENTRY(EUSERS, "Too many users"),
#endif
#if defined(ENOTSOCK)
U_ERR_ENTRY(ENOTSOCK, "Socket operation on non-socket"),
#endif
#if defined(EDESTADDRREQ)
U_ERR_ENTRY(EDESTADDRREQ, "Destination address required"),
#endif
#if defined(EMSGSIZE)
U_ERR_ENTRY(EMSGSIZE, "Message too long"),
#endif
#if defined(EPROTOTYPE)
U_ERR_ENTRY(EPROTOTYPE, "Protocol wrong type for socket"),
#endif
#if defined(ENOPROTOOPT)
U_ERR_ENTRY(ENOPROTOOPT, "Protocol not available"),
#endif
#if defined(EPROTONOSUPPORT)
U_ERR_ENTRY(EPROTONOSUPPORT, "Protocol not supported"),
#endif
#if defined(ESOCKTNOSUPPORT)
U_ERR_ENTRY(ESOCKTNOSUPPORT, "Socket type not supported"),
#endif
#if defined(EOPNOTSUPP)
U_ERR_ENTRY(EOPNOTSUPP, "Operation not supported on transport endpoint"),
#endif
#if defined(EPFNOSUPPORT)
U_ERR_ENTRY(EPFNOSUPPORT, "Protocol family not supported"),
#endif
#if defined(EAFNOSUPPORT)
U_ERR_ENTRY(EAFNOSUPPORT, "Address family not supported by protocol"),
#endif
#if defined(EADDRINUSE)
U_ERR_ENTRY(EADDRINUSE, "Address already in use"),
#endif
#if defined(EADDRNOTAVAIL)
U_ERR_ENTRY(EADDRNOTAVAIL, "Cannot assign requested address"),
#endif
#if defined(ENETDOWN)
U_ERR_ENTRY(ENETDOWN, "Network is down"),
#endif
#if defined(ENETUNREACH)
U_ERR_ENTRY(ENETUNREACH, "Network is unreachable"),
#endif
#if defined(ENETRESET)
U_ERR_ENTRY(ENETRESET, "Network dropped connection because of reset"),
#endif
#if defined(ECONNABORTED)
U_ERR_ENTRY(ECONNABORTED, "Software caused connection abort"),
#endif
#if defined(ECONNRESET)
U_ERR_ENTRY(ECONNRESET, "Connection reset by peer"),
#endif
#if defined(ENOBUFS)
U_ERR_ENTRY(ENOBUFS, "No buffer space available"),
#endif
#if defined(EISCONN)
U_ERR_ENTRY(EISCONN, "Transport endpoint is already connected"),
#endif
#if defined(ENOTCONN)
U_ERR_ENTRY(ENOTCONN, "Transport endpoint is not connected"),
#endif
#if defined(ESHUTDOWN)
U_ERR_ENTRY(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
#endif
#if defined(ETOOMANYREFS)
U_ERR_ENTRY(ETOOMANYREFS, "Too many references: cannot splice"),
#endif
#if defined(ETIMEDOUT)
U_ERR_ENTRY(ETIMEDOUT, "Connection timed out"),
#endif
#if defined(ECONNREFUSED)
U_ERR_ENTRY(ECONNREFUSED, "Connection refused"),
#endif
#if defined(EHOSTDOWN)
U_ERR_ENTRY(EHOSTDOWN, "Host is down"),
#endif
#if defined(EHOSTUNREACH)
U_ERR_ENTRY(EHOSTUNREACH, "No route to host"),
#endif
#if defined(EALREADY)
U_ERR_ENTRY(EALREADY, "Operation already in progress"),
#endif
#if defined(EINPROGRESS)
U_ERR_ENTRY(EINPROGRESS, "Operation now in progress"),
#endif
#if defined(ESTALE)
U_ERR_ENTRY(ESTALE, "Stale NFS file handle"),
#endif
#if defined(EUCLEAN)
U_ERR_ENTRY(EUCLEAN, "Structure needs cleaning"),
#endif
#if defined(ENOTNAM)
U_ERR_ENTRY(ENOTNAM, "Not a XENIX named type file"),
#endif
#if defined(ENAVAIL)
U_ERR_ENTRY(ENAVAIL, "No XENIX semaphores available"),
#endif
#if defined(EISNAM)
U_ERR_ENTRY(EISNAM, "Is a named type file"),
#endif
#if defined(EREMOTEIO)
U_ERR_ENTRY(EREMOTEIO, "Remote I/O error"),
#endif
#if defined(EDQUOT)
U_ERR_ENTRY(EDQUOT, "Quota exceeded"),
#endif
#if defined(ENOMEDIUM)
U_ERR_ENTRY(ENOMEDIUM, "No medium found"),
#endif
#if defined(EMEDIUMTYPE)
U_ERR_ENTRY(EMEDIUMTYPE, "Wrong medium type"),
#endif
#if defined(ENMFILE)
U_ERR_ENTRY(ENMFILE, "No more files"),
#endif
#if defined(ENOSHARE)
U_ERR_ENTRY(ENOSHARE, "No such host or network path"),
#endif
#if defined(EPROCLIM)
U_ERR_ENTRY(EPROCLIM, "Too many processes")
#endif
};
#ifdef EVMSERR
/* This is not in the table, because the numeric value of EVMSERR (32767) lies outside the range of sys_errlist[] */
if (errno == EVMSERR) return "EVMSERR (32767, VMS-specific error)";
#endif
const char* restrict msg = "Unknown error";
const char* restrict name = "???";
U_INTERNAL_TRACE("u_getSysError(%p)", len)
if ((errno > 0) &&
(errno < (int)U_NUM_ELEMENTS(error_table))) /* check if in range */
{
# ifdef HAVE_STRERROR
msg = strerror(errno);
# endif
if (error_table[errno].value == errno)
{
# ifndef HAVE_STRERROR
msg = error_table[errno].msg;
# endif
name = error_table[errno].name;
}
else
{
unsigned int i;
for (i = 0; i < U_NUM_ELEMENTS(error_table); ++i)
{
if (error_table[i].value == errno)
{
# ifndef HAVE_STRERROR
msg = error_table[i].msg;
# endif
name = error_table[i].name;
break;
}
}
}
}
*len = snprintf(u_err_buffer, U_CONSTANT_SIZE(u_err_buffer), "%s (%d, %s)", name, errno, msg);
}
/**
* Maps an signal number to an signal message string, the contents of which are implementation defined.
* The returned string is only guaranteed to be valid only until the next call to strsignal
*/
void u_getSysSignal(int signo, uint32_t* restrict len)
{
/**
* Translation table for signal values. Note that this table is generally only accessed when
* it is used at runtime to initialize signal name and message tables that are indexed by signal value.
* Not all of these signals will exist on all systems. This table is the only thing that should have to
* be updated as new signal numbers are introduced. It's sort of ugly, but at least its portable
*/
struct signal_info {
int value; /* The numeric value from <signal.h> */
const char* restrict name; /* The equivalent symbolic value */
# ifndef HAVE_STRSIGNAL
const char* restrict msg; /* Short message about this value */
# endif
};
#undef U_ERR_ENTRY
#ifdef HAVE_STRSIGNAL
# define U_SIG_ENTRY(name,msg) {name, #name}
#else
# define U_SIG_ENTRY(name,msg) {name, #name, msg}
#endif
static const struct signal_info signal_table[] = {
#if defined(SIGHUP)
U_SIG_ENTRY(SIGHUP, "Hangup"),
#endif
#if defined(SIGINT)
U_SIG_ENTRY(SIGINT, "Interrupt"),
#endif
#if defined(SIGQUIT)
U_SIG_ENTRY(SIGQUIT, "Quit"),
#endif
#if defined(SIGILL)
U_SIG_ENTRY(SIGILL, "Illegal instruction"),
#endif
#if defined(SIGTRAP)
U_SIG_ENTRY(SIGTRAP, "Trace/breakpoint trap"),
#endif
/* Put SIGIOT before SIGABRT, so that if SIGIOT == SIGABRT then SIGABRT overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't */
#if defined(SIGIOT)
U_SIG_ENTRY(SIGIOT, "IOT trap"),
#endif
#if defined(SIGABRT)
U_SIG_ENTRY(SIGABRT, "Aborted"),
#endif
#if defined(SIGEMT)
U_SIG_ENTRY(SIGEMT, "Emulation trap"),
#endif
#if defined(SIGFPE)
U_SIG_ENTRY(SIGFPE, "Arithmetic exception"),
#endif
#if defined(SIGKILL)
U_SIG_ENTRY(SIGKILL, "Killed"),
#endif
#if defined(SIGBUS)
U_SIG_ENTRY(SIGBUS, "Bus error"),
#endif
#if defined(SIGSEGV)
U_SIG_ENTRY(SIGSEGV, "Segmentation fault"),
#endif
#if defined(SIGSYS)
U_SIG_ENTRY(SIGSYS, "Bad system call"),
#endif
#if defined(SIGPIPE)
U_SIG_ENTRY(SIGPIPE, "Broken pipe"),
#endif
#if defined(SIGALRM)
U_SIG_ENTRY(SIGALRM, "Alarm clock"),
#endif
#if defined(SIGTERM)
U_SIG_ENTRY(SIGTERM, "Terminated"),
#endif
#if defined(SIGUSR1)
U_SIG_ENTRY(SIGUSR1, "User defined signal 1"),
#endif
#if defined(SIGUSR2)
U_SIG_ENTRY(SIGUSR2, "User defined signal 2"),
#endif
/* Put SIGCLD before SIGCHLD, so that if SIGCLD == SIGCHLD then SIGCHLD overrides SIGCLD. SIGCHLD is in POXIX.1 */
#if defined(SIGCLD)
U_SIG_ENTRY(SIGCLD, "Child status changed"),
#endif
#if defined(SIGCHLD)
U_SIG_ENTRY(SIGCHLD, "Child status changed"),
#endif
#if defined(SIGPWR)
U_SIG_ENTRY(SIGPWR, "Power fail/restart"),
#endif
#if defined(SIGWINCH)
U_SIG_ENTRY(SIGWINCH, "Window size changed"),
#endif
#if defined(SIGURG)
U_SIG_ENTRY(SIGURG, "Urgent I/O condition"),
#endif
#if defined(SIGIO)
/* I/O pending has also been suggested, but is misleading since the signal only happens when the process has asked for it, not everytime I/O is pending */
U_SIG_ENTRY(SIGIO, "I/O possible"),
#endif
#if defined(SIGPOLL)
U_SIG_ENTRY(SIGPOLL, "Pollable event occurred"),
#endif
#if defined(SIGSTKFLT)
U_SIG_ENTRY(SIGSTKFLT, "Stack fault"),
#endif
#if defined(SIGSTOP)
U_SIG_ENTRY(SIGSTOP, "Stopped (signal)"),
#endif
#if defined(SIGTSTP)
U_SIG_ENTRY(SIGTSTP, "Stopped (user)"),
#endif
#if defined(SIGCONT)
U_SIG_ENTRY(SIGCONT, "Continued"),
#endif
#if defined(SIGTTIN)
U_SIG_ENTRY(SIGTTIN, "Stopped (tty input)"),
#endif
#if defined(SIGTTOU)
U_SIG_ENTRY(SIGTTOU, "Stopped (tty output)"),
#endif
#if defined(SIGVTALRM)
U_SIG_ENTRY(SIGVTALRM, "Virtual timer expired"),
#endif
#if defined(SIGPROF)
U_SIG_ENTRY(SIGPROF, "Profiling timer expired"),
#endif
#if defined(SIGXCPU)
U_SIG_ENTRY(SIGXCPU, "CPU time limit exceeded"),
#endif
#if defined(SIGXFSZ)
U_SIG_ENTRY(SIGXFSZ, "File size limit exceeded"),
#endif
#if defined(SIGWIND)
U_SIG_ENTRY(SIGWIND, "SIGWIND"),
#endif
#if defined(SIGPHONE)
U_SIG_ENTRY(SIGPHONE, "SIGPHONE"),
#endif
#if defined(SIGLOST)
U_SIG_ENTRY(SIGLOST, "Resource lost"),
#endif
#if defined(SIGWAITING)
U_SIG_ENTRY(SIGWAITING, "Process's LWPs are blocked"),
#endif
#if defined(SIGLWP)
U_SIG_ENTRY(SIGLWP, "Signal LWP"),
#endif
#if defined(SIGDANGER)
U_SIG_ENTRY(SIGDANGER, "Swap space dangerously low"),
#endif
#if defined(SIGGRANT)
U_SIG_ENTRY(SIGGRANT, "Monitor mode granted"),
#endif
#if defined(SIGRETRACT)
U_SIG_ENTRY(SIGRETRACT, "Need to relinguish monitor mode"),
#endif
#if defined(SIGMSG)
U_SIG_ENTRY(SIGMSG, "Monitor mode data available"),
#endif
#if defined(SIGSOUND)
U_SIG_ENTRY(SIGSOUND, "Sound completed"),
#endif
#if defined(SIGSAK)
U_SIG_ENTRY(SIGSAK, "Secure attention")
#endif
};
const char* restrict msg = "Unknown signal";
const char* restrict name = "???";
U_INTERNAL_TRACE("u_getSysSignal(%d,%p)", signo, len)
if ((signo > 0) &&
(signo < (int)U_NUM_ELEMENTS(signal_table))) /* check if in range */
{
# ifdef HAVE_STRSIGNAL
msg = strsignal(signo);
# endif
if (signal_table[signo].value == signo)
{
# ifndef HAVE_STRSIGNAL
msg = signal_table[signo].msg;
# endif
name = signal_table[signo].name;
}
else
{
unsigned int i;
for (i = 0; i < U_NUM_ELEMENTS(signal_table); ++i)
{
if (signal_table[i].value == signo)
{
# ifndef HAVE_STRSIGNAL
msg = signal_table[i].msg;
# endif
name = signal_table[i].name;
break;
}
}
}
}
*len = snprintf(u_err_buffer, U_CONSTANT_SIZE(u_err_buffer), "%s (%d, %s)", name, signo, msg);
}
#undef U_SIG_ENTRY
#define U_EXIT_ENTRY(name,msg) {name, #name, msg}
void u_getExitStatus(int exitno, uint32_t* restrict len)
{
/* Translation table for exit status codes for system programs */
struct exit_value_info {
int value; /* The numeric value from <sysexits.h> */
const char* restrict name; /* The equivalent symbolic value */
const char* restrict msg; /* Short message about this value */
};
static const struct exit_value_info exit_value_table[] = {
#if defined(EX_USAGE)
U_EXIT_ENTRY(EX_USAGE, "command line usage error"),
#endif
#if defined(EX_DATAERR)
U_EXIT_ENTRY(EX_DATAERR, "data format error"),
#endif
#if defined(EX_NOINPUT)
U_EXIT_ENTRY(EX_NOINPUT, "cannot open input"),
#endif
#if defined(EX_NOUSER)
U_EXIT_ENTRY(EX_NOUSER, "addresse unknown"),
#endif
#if defined(EX_NOHOST)
U_EXIT_ENTRY(EX_NOHOST, "host name unknown"),
#endif
#if defined(EX_UNAVAILABLE)
U_EXIT_ENTRY(EX_UNAVAILABLE, "service unavailable"),
#endif
#if defined(EX_SOFTWARE)
U_EXIT_ENTRY(EX_SOFTWARE, "internal software error"),
#endif
#if defined(EX_OSERR)
U_EXIT_ENTRY(EX_OSERR, "system error (e.g., can't fork)"),
#endif
#if defined(EX_OSFILE)
U_EXIT_ENTRY(EX_OSFILE, "critical OS file missing"),
#endif
#if defined(EX_CANTCREAT)
U_EXIT_ENTRY(EX_CANTCREAT, "can't create (user) output file"),
#endif
#if defined(EX_IOERR)
U_EXIT_ENTRY(EX_IOERR, "input/output error"),
#endif
#if defined(EX_TEMPFAIL)
U_EXIT_ENTRY(EX_TEMPFAIL, "temp failure; user is invited to retry"),
#endif
#if defined(EX_PROTOCOL)
U_EXIT_ENTRY(EX_PROTOCOL, "remote error in protocol"),
#endif
#if defined(EX_NOPERM)
U_EXIT_ENTRY(EX_NOPERM, "permission denied"),
#endif
#if defined(EX_CONFIG)
U_EXIT_ENTRY(EX_CONFIG, "configuration error")
#endif
};
#undef U_EXIT_ENTRY
const char* restrict msg;
const char* restrict name;
U_INTERNAL_TRACE("u_getExitStatus(%d,%p)", exitno, len)
if (exitno == 0)
{
msg = "successful termination";
name = "EX_OK";
}
else
{
msg = "Unknown value";
name = "???";
}
if ((exitno >= EX__BASE) &&
(exitno <= EX__MAX)) // check if in range
{
int _index = exitno - EX__BASE;
if (exit_value_table[_index].value == exitno)
{
msg = exit_value_table[_index].msg;
name = exit_value_table[_index].name;
}
else
{
unsigned int i;
for (i = 0; i < U_NUM_ELEMENTS(exit_value_table); ++i)
{
if (exit_value_table[i].value == exitno)
{
msg = exit_value_table[i].msg;
name = exit_value_table[i].name;
break;
}
}
}
}
*len = snprintf(u_err_buffer, U_CONSTANT_SIZE(u_err_buffer), "%s (%d, %s)", name, exitno, msg);
}