diff options
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | libsimple.c | 619 | ||||
-rw-r--r-- | libsimple.h | 841 |
3 files changed, 1401 insertions, 69 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..35e122e --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +.POSIX: + +all: libsimple.a +libsimple.o: libsimple.h +libsimple.a: libsimple.o + +clean: + -rm -r -- libsimple.o libsimple.a libsimple.so libsimple.so.* + +.PHONY: all clean diff --git a/libsimple.c b/libsimple.c index 9a58ba1..ac7432a 100644 --- a/libsimple.c +++ b/libsimple.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #include "libsimple.h" +#include <ifaddrs.h> extern char *argv0; @@ -441,11 +442,14 @@ vweprintf(const char *fmt, va_list ap) va_end(ap2); va_end(ap1); - if (*end == ':') { + if (!*fmt) { + suffix1 = strerror(saved_errno); + suffix2 = "\n"; + } else if (end[-1] == ':') { suffix1 = " "; suffix2 = strerror(saved_errno); suffix3 = "\n"; - } else if (*end != '\n') { + } else if (end[-1] != '\n') { suffix1 = "\n"; } @@ -460,3 +464,614 @@ vweprintf(const char *fmt, va_list ap) errno = saved_errno; } + + + +int +libsimple_sendfd(int sock, int fd) +{ + char buf[1]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(fd))]; + + buf[0] = 0; + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = CMSG_LEN(sizeof(fd)); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + return -(sendmsg(sock, &msg, 0) != (ssize_t)iov.iov_len); +} + + +int +libsimple_recvfd(int sock) +{ + int fd; + char buf[1]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(fd))]; + + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = sizeof(cms); + + switch (recvmsg(sock, &msg, 0)) { + case -1: + return -1; + case 0: + errno = ECONNRESET; + return -1; + default: + break; + } + + cmsg = CMSG_FIRSTHDR(&msg); + memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + return fd; +} + + +ssize_t +libsimple_recvfrom_timestamped(int fd, void *restrict buf, size_t n, int flags, struct sockaddr *restrict addr, + socklen_t addrlen, struct timespec *restrict ts) +{ + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(*ts))]; + size_t r; + + iov.iov_base = buf; + iov.iov_len = n; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = addr; + msg.msg_namelen = addrlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = sizeof(cms); + + switch ((r = recvmsg(fd, &msg, flags))) { + case -1: + return -1; + case 0: + errno = ECONNRESET; + return -1; + default: + break; + } + + if (!ts) + return r; + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg && + cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_TIMESTAMPNS && + cmsg->cmsg_len == CMSG_LEN(sizeof(*ts))) { + memcpy(ts, CMSG_DATA(cmsg), sizeof(*ts)); + } else if (cmsg && + cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_TIMESTAMP && + cmsg->cmsg_len == CMSG_LEN(sizeof(*ts))) { + memcpy(ts, CMSG_DATA(cmsg), sizeof(*ts)); + ts->tv_nsec *= 1000; + } else { + memset(ts, 0, sizeof(*ts)); + } + + return r; +} + + +int +libsimple_sumtimespec(struct timespec *sum, const struct timespec *augend, const struct timespec *addend) +{ + long int ns = augend->tv_nsec + addend->tv_nsec; + time_t s; + int ret = 0; + + s = augend->tv_sec + addend->tv_sec; + if ((augend->tv_sec < 0) == (addend->tv_sec < 0)) { + if (augend->tv_sec >= 0 && augend->tv_sec > TIME_MAX - addend->tv_sec) { + s = TIME_MAX; + ns = 999999999L; + errno = ERANGE; + ret = -1; + } else if (augend->tv_sec < 0 && augend->tv_sec + addend->tv_sec < TIME_MIN) { + s = TIME_MIN; + ns = 0; + errno = ERANGE; + ret = -1; + } + } + + if (ns < 0) { + if (s == TIME_MIN) { + ns = 0L; + errno = ERANGE; + ret = -1; + } else { + s -= 1; + ns += 1000000000L; + } + } else if (ns >= 1000000000L) { + if (s == TIME_MAX) { + ns = 999999999L; + errno = ERANGE; + ret = -1; + } else { + s += 1; + ns -= 1000000000L; + } + } + + sum->tv_sec = s; + sum->tv_nsec = ns; + return ret; +} + + +int +libsimple_difftimespec(struct timespec *diff, const struct timespec *minuend, const struct timespec *subtrahend) +{ + long int ns = minuend->tv_nsec - subtrahend->tv_nsec; + time_t s; + int ret = 0; + + s = minuend->tv_sec - subtrahend->tv_sec; + if ((minuend->tv_sec <= 0) != (subtrahend->tv_sec <= 0)) { + if (minuend->tv_sec < 0 && minuend->tv_sec < TIME_MIN + subtrahend->tv_sec) { + s = TIME_MIN; + ns = 0; + errno = ERANGE; + ret = -1; + } else if (minuend->tv_sec >= 0 && minuend->tv_sec > TIME_MAX + subtrahend->tv_sec) { + s = TIME_MAX; + ns = 999999999L; + errno = ERANGE; + ret = -1; + } + } + + if (ns < 0) { + if (s == TIME_MIN) { + ns = 0L; + errno = ERANGE; + ret = -1; + } else { + s -= 1; + ns += 1000000000L; + } + } else if (ns >= 1000000000L) { + if (s == TIME_MAX) { + ns = 999999999L; + errno = ERANGE; + ret = -1; + } else { + s += 1; + ns -= 1000000000L; + } + } + + diff->tv_sec = s; + diff->tv_nsec = ns; + return ret; +} + + +int +libsimple_multimespec(struct timespec *prod, const struct timespec *multiplicand, int multiplier) +{ + time_t s = multiplicand->tv_sec; + long long int ns = (long long int)(multiplicand->tv_nsec); + long long int xs; + int neg = (s < 0) ^ (multiplier < 0); + + if (multiplier == 0 || multiplier == 1) { + prod->tv_sec = multiplier * multiplicand->tv_sec; + prod->tv_nsec = multiplier * multiplicand->tv_nsec; + return 0; + } + + if (s < 0) { + if (TIME_MIN != -TIME_MAX && s == TIME_MIN) + goto overflow; + s = -s; + if (ns) + ns = 1000000000L - ns; + } + if (multiplier < 0) + multiplier = -multiplier; + + ns *= multiplier; + xs /= 1000000000L; + ns %= 1000000000L; + + if (s > TIME_MAX / multiplier) + goto overflow; + s *= multiplier; + + if (s > TIME_MAX - (time_t)xs) + goto overflow; + s += (time_t)xs; + + if (neg) { + s = -s; + if (ns) { + if (s == TIME_MIN) + goto overflow; + ns = 1000000000L - ns; + s -= 1; + } + } + + prod->tv_sec = s; + prod->tv_nsec = ns; + return 0; + +overflow: + if (neg) { + prod->tv_sec = TIME_MIN; + prod->tv_nsec = 0; + } else { + prod->tv_sec = TIME_MAX; + prod->tv_nsec = 999999999L; + } + errno = ERANGE; + return -1; +} + + +int +libsimple_sumtimeval(struct timeval *sum, const struct timeval *augend, const struct timeval *addend) +{ + struct timespec a, b, s; + int r; + libsimple_timeval2timespec(&a, augend); + libsimple_timeval2timespec(&b, addend); + r = libsimple_sumtimespec(&s, &a, &b); + if (r && errno != ERANGE) + return r; + return r | libsimple_timespec2timeval(sum, &s); +} + + +int +libsimple_difftimeval(struct timeval *diff, const struct timeval *minuend, const struct timeval *subtrahend) +{ + struct timespec a, b, d; + int r; + libsimple_timeval2timespec(&a, minuend); + libsimple_timeval2timespec(&b, subtrahend); + r = libsimple_difftimespec(&d, &a, &b); + if (r && errno != ERANGE) + return r; + return r | libsimple_timespec2timeval(diff, &d); +} + + +int +libsimple_multimeval(struct timeval *prod, const struct timeval *multiplicand, int multiplier) +{ + struct timespec a, p; + int r; + libsimple_timeval2timespec(&a, multiplicand); + r = libsimple_multimespec(&p, &a, multiplier); + if (r && errno != ERANGE) + return r; + return r | libsimple_timespec2timeval(prod, &p); +} + + +int +libsimple_timespec2timeval(struct timeval *restrict tv, const struct timespec *restrict ts) +{ + tv->tv_sec = ts->tv_sec; + tv->tv_usec = ts->tv_nsec / 1000L; + if ((ts->tv_nsec % 1000L) >= 500L) { + if (++(tv->tv_usec) == 1000000L) { + tv->tv_usec = 0; + if (tv->tv_sec == TIME_MAX) { + tv->tv_usec = 999999L; + errno = EOVERFLOW; + return -1; + } else { + tv->tv_sec += 1; + } + } + } + return 0; +} + + +int +libsimple_strtotimespec(struct timespec *restrict ts, const char *restrict s, char **restrict end) +{ + int neg = 0, bracket = 0; + time_t sec = 0; + long int nsec = 0; + long int mul = 100000000L; + const char *p; + + if (end) + *end = (void *)s; + + while (isspace(*s)) + s++; + + if (!isdigit(s) && *s != '+' && *s != '-' && *s != '.') { + errno = EINVAL; + return -1; + } + + if (*s == '-') { + neg = 1; + s++; + } else if (*s == '+') { + s++; + } + + if (*s == '.') { + if (s[1] == '.' || s[1] == '(') { + if (!isdigit(s[2])) { + errno = EINVAL; + return -1; + } + } else if (!isdigit(s[1])) { + errno = EINVAL; + return -1; + } + } + + for (; isdigit(*s); s++) { + if (sec < TIME_MIN / 10) + goto overflow; + sec *= 10; + if (sec < TIME_MIN + (*s & 15)) + goto overflow; + sec -= *s & 15; + } + + if (!neg) { + if (TIME_MIN != -TIME_MAX && sec == TIME_MIN) + goto overflow; + sec = -sec; + } + + if (*s != '.') { + ts->tv_sec = sec; + ts->tv_nsec = 0; + if (end) + *end = (void *)s; + return 0; + } + + for (s++; mul && isdigit(*s); s++) { + nsec += (*s & 15) * mul; + mul /= 10; + } + + if (*s == '.' || *s == '(') { + bracket = *s++ == '('; + p = s; + if (!isdigit(*s)) { + errno = EINVAL; + return -1; + } + for (p = s; isdigit(*p); p++); + if (bracket) { + if (*p == ')') { + p++; + } else { + errno = EINVAL; + return -1; + } + } + if (end) + *end = (void *)p; + p = s; + while (mul) { + for (s = p; mul && isdigit(*s); s++) { + nsec += (*s & 15) * mul; + mul /= 10; + } + } + if (!isdigit(*s)) + s = p; + if (*s >= '5') { + nsec += 1; + if (nsec == 1000000000L) { + if (sec == TIME_MAX) + goto overflow; + sec += 1; + nsec = 0; + } + } + } else { + if (isdigit(*s)) { + if (*s >= '5') { + nsec += 1; + if (nsec == 1000000000L) { + if (sec == TIME_MAX) + goto overflow; + sec += 1; + nsec = 0; + } + } + while (isdigit(*s)) + s++; + } + if (end) + *end = (void *)s; + } + + if (neg && nsec) { + if (sec == TIME_MIN) + goto overflow; + nsec = 1000000000L - nsec; + sec -= 1; + } + + return 0; +overflow: + if (neg) { + ts->tv_sec = TIME_MIN; + ts->tv_nsec = 0; + } else { + ts->tv_sec = TIME_MAX; + ts->tv_nsec = 999999999L; + } + errno = ERANGE; + return -1; +} + + +int +libsimple_strtotimeval(struct timeval *restrict tv, const char *restrict s, char **restrict end) +{ + struct timespec ts; + int r = libsimple_strtotimespec(&ts, s, end); + if (r && errno != ERANGE) + return r; + return r | libsimple_timespec2timeval(tv, &ts); +} + + +char * +libsimple_timespectostr(char *restrict buf, const struct timespec *restrict ts) +{ + time_t s = ts->tv_sec; + long int ns = ts->tv_nsec; + char sign[2] = "+"; + + if (!s) { + buf = malloc(INTSTRLEN(time_t) + sizeof("-.999999999")); + if (!buf) + return NULL; + } + + if (ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000L) { + errno = EINVAL; + return NULL; + } + + if (s == TIME_MIN && !ns) { + sprintf(buf, "%lli.000000000", (long long int)s); + return buf; + } + + if (s < 0) { + s = -s; + *sign == '-'; + if (ns) { + s -= 1; + ns = 1000000000L - ns; + } + } + + sprintf(buf, "%s%lli.%09li", sign, (long long int)s, ns); + return buf; +} + + +char * +libsimple_timevaltostr(char *restrict buf, const struct timeval *restrict tv) +{ + time_t s = tv->tv_sec; + long int us = tv->tv_usec; + char sign[2] = "+"; + + if (!s) { + buf = malloc(INTSTRLEN(time_t) + sizeof("-.999999")); + if (!buf) + return NULL; + } + + if (tv->tv_usec < 0 || tv->tv_usec >= 1000000L) { + errno = EINVAL; + return NULL; + } + + if (s == TIME_MIN && !us) { + sprintf(buf, "%lli.000000", (long long int)s); + return buf; + } + + if (s < 0) { + s = -s; + *sign == '-'; + if (us) { + s -= 1; + us = 1000000L - us; + } + } + + sprintf(buf, "%s%lli.%06li", sign, (long long int)s, us); + return buf; +} + + +void +libsimple_doubletotimespec(struct timespec *ts, double d) +{ + double ns = (long long int)d; + long int nsi; + ns = d - ns; + ns *= (double)1000000000L; + nsi = (long int)ns; + if (2 * (ns - (double)nsi) >= 1) { + nsi += 1; + if (nsi == 1000000000L) { + nsi == 0; + d += 1; + } + } + ts->tv_sec = (time_t)d; + ts->tv_nsec = nsi; +} + + +void +libsimple_doubletotimeval(struct timeval *tv, double d) +{ + double ns = (long long int)d; + long int nsi; + ns = d - ns; + ns *= (double)1000000L; + nsi = (long int)ns; + if (2 * (ns - (double)nsi) >= 1) { + nsi += 1; + if (nsi == 1000000L) { + nsi == 0; + d += 1; + } + } + tv->tv_sec = (time_t)d; + tv->tv_usec = nsi; +} diff --git a/libsimple.h b/libsimple.h index 02fc912..893ba72 100644 --- a/libsimple.h +++ b/libsimple.h @@ -3,17 +3,40 @@ #define LIBSIMPLE_H +#include <arpa/inet.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/mman.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <sys/wait.h> +#include <aio.h> #include <alloca.h> +#include <ctype.h> +#include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <grp.h> #include <inttypes.h> #include <limits.h> +#include <netdb.h> +#include <poll.h> +#include <pwd.h> +#include <setjmp.h> +#include <signal.h> #include <stdarg.h> +#include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> +#include <time.h> #include <unistd.h> @@ -27,63 +50,523 @@ extern int libsimple_default_failure_exit; -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +#ifndef CLOCK_MONOTONIC_RAW +# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC +#endif + + +#ifdef AF_LOCAL +# ifndef AF_UNIX +# define AF_UNIX AF_LOCAL +# endif +# ifndef AF_FILE +# define AF_FILE AF_LOCAL +# endif +#endif + +#ifdef AF_UNIX +# ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +# endif +# ifndef AF_FILE +# define AF_FILE AF_UNIX +# endif +#endif + +#ifdef AF_FILE +# ifndef AF_LOCAL +# define AF_LOCAL AF_FILE +# endif +# ifndef AF_UNIX +# define AF_UNIX AF_FILE +# endif +#endif + +#ifdef AF_NETLINK +# ifndef AF_ROUTE +# define AF_ROUTE AF_NETLINK +# endif +#endif + +#ifdef AF_ROUTE +# ifndef AF_NETLINK +# define AF_NETLINK AF_ROUTE +# endif +#endif + +#ifdef PF_LOCAL +# ifndef PF_UNIX +# define PF_UNIX PF_LOCAL +# endif +# ifndef PF_FILE +# define PF_FILE PF_LOCAL +# endif +#endif + +#ifdef PF_UNIX +# ifndef PF_LOCAL +# define PF_LOCAL PF_UNIX +# endif +# ifndef PF_FILE +# define PF_FILE PF_UNIX +# endif +#endif + +#ifdef PF_FILE +# ifndef PF_LOCAL +# define PF_LOCAL PF_FILE +# endif +# ifndef PF_UNIX +# define PF_UNIX PF_FILE +# endif +#endif + +#ifdef PF_NETLINK +# ifndef PF_ROUTE +# define PF_ROUTE PF_NETLINK +# endif +#endif + +#ifdef PF_ROUTE +# ifndef PF_NETLINK +# define PF_NETLINK PF_ROUTE +# endif +#endif + +#if !defined(PF_UNIX) && defined(AF_UNIX) +# define PF_UNIX AF_UNIX +#endif +#if !defined(PF_LOCAL) && defined(AF_LOCAL) +# define PF_LOCAL AF_LOCAL +#endif +#if !defined(PF_FILE) && defined(AF_FILE) +# define PF_FILE AF_FILE +#endif +#if !defined(PF_INET) && defined(AF_INET) +# define PF_INET AF_INET +#endif +#if !defined(PF_INET6) && defined(AF_INET6) +# define PF_INET6 AF_INET6 +#endif +#if !defined(PF_NETLINK) && defined(AF_NETLINK) +# define PF_NETLINK AF_NETLINK +#endif +#if !defined(PF_ROUTE) && defined(AF_ROUTE) +# define PF_ROUTE AF_ROUTE +#endif + + +#ifndef MIN +# define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + + +#ifndef MAX +# define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif + + +#ifndef MIN3 +# define MIN3(A, B, C) MIN(MIN((A), (B)), (C)) +#endif + + +#ifndef MAX3 +# define MAX3(A, B, C) MAX(MAX((A), (B)), (C)) +#endif + + +#ifndef ELEMSOF +# define ELEMSOF(ARR) (sizeof(ARR) / (sizeof(*(ARR)))) +#endif + + +#ifndef STRLEN +# define STRLEN(STR) (sizeof(STR) - 1) +#endif + + +#ifndef INTSTRLEN +# define INTSTRLEN(TYPE) ((sizeof(TYPE) == 1 ? 3 : 5 * (sizeof(TYPE) / 2)) + ((TYPE)-1 > 0)) +#endif + + +#ifndef TYPE_MAX +# define TYPE_MAX(TYPE) ((TYPE)(((1ULL << (8 * sizeof(TYPE) - 1)) - 1) << ((TYPE)-1 > 0) | 1)) +#endif + + +#ifndef TYPE_MIN +# define TYPE_MIN(TYPE) ((TYPE)((TYPE)-1 > 0 ? 0 : (TYPE)~0 < (TYPE)-1 ? (TYPE)~0 : (TYPE)(1ULL << (8 * sizeof(TYPE) - 1)))) +#endif + + +#ifndef BLKCNT64_MAX +# define BLKCNT64_MAX TYPE_MAX(blkcnt64_t) +#endif + +#ifndef BLKCNT_MAX +# define BLKCNT_MAX TYPE_MAX(blkcnt_t) +#endif + +#ifndef BLKSIZE_MAX +# define BLKSIZE_MAX TYPE_MAX(blksize_t) +#endif + +#ifndef CC_MAX +# define CC_MAX TYPE_MAX(cc_t) +#endif + +#ifndef CLOCKID_MAX +# define CLOCKID_MAX TYPE_MAX(clockid_t) +#endif + +#ifndef CLOCK_MAX +# define CLOCK_MAX TYPE_MAX(clock_t) +#endif + +#ifndef DEV_MAX +# define DEV_MAX TYPE_MAX(dev_t) +#endif + +#ifndef FSBLKCNT64_MAX +# define FSBLKCNT64_MAX TYPE_MAX(fsblkcnt64_t) +#endif + +#ifndef FSBLKCNT_MAX +# define FSBLKCNT_MAX TYPE_MAX(fsblkcnt_t) +#endif + +#ifndef FSFILCNT64_MAX +# define FSFILCNT64_MAX TYPE_MAX(fsfilcnt64_t) +#endif + +#ifndef FSFILCNT_MAX +# define FSFILCNT_MAX TYPE_MAX(fsfilcnt_t) +#endif + +#ifndef FSID_MAX +# define FSID_MAX TYPE_MAX(fsid_t) +#endif + +#ifndef FSWORD_MAX +# define FSWORD_MAX TYPE_MAX(fsword_t) +#endif + +#ifndef GID_MAX +# define GID_MAX TYPE_MAX(gid_t) +#endif + +#ifndef ID_MAX +# define ID_MAX TYPE_MAX(id_t) +#endif + +#ifndef INO64_MAX +# define INO64_MAX TYPE_MAX(ino64_t) +#endif + +#ifndef INO_MAX +# define INO_MAX TYPE_MAX(ino_t) +#endif + +#ifndef KEY_MAX +# define KEY_MAX TYPE_MAX(key_t) +#endif + +#ifndef LOFF_MAX +# define LOFF_MAX TYPE_MAX(loff_t) +#endif + +#ifndef MODE_MAX +# define MODE_MAX TYPE_MAX(mode_t) +#endif + +#ifndef NLINK_MAX +# define NLINK_MAX TYPE_MAX(nlink_t) +#endif + +#ifndef OFF64_MAX +# define OFF64_MAX TYPE_MAX(off64_t) +#endif + +#ifndef OFF_MAX +# define OFF_MAX TYPE_MAX(off_t) +#endif + +#ifndef PID_MAX +# define PID_MAX TYPE_MAX(pid_t) +#endif + +#ifndef QUAD_MAX +# define QUAD_MAX TYPE_MAX(quad_t) +#endif + +#ifndef REGISTER_MAX +# define REGISTER_MAX TYPE_MAX(register_t) +#endif + +#ifndef RLIM64_MAX +# define RLIM64_MAX TYPE_MAX(rlim64_t) +#endif + +#ifndef RLIM_MAX +# define RLIM_MAX TYPE_MAX(rlim_t) +#endif + +#ifndef SOCKLEN_MAX +# define SOCKLEN_MAX TYPE_MAX(socklen_t) +#endif + +#ifndef SPEED_MAX +# define SPEED_MAX TYPE_MAX(speed_t) +#endif + +#ifndef SUSECONDS_MAX +# define SUSECONDS_MAX TYPE_MAX(suseconds_t) +#endif + +#ifndef TCFLAG_MAX +# define TCFLAG_MAX TYPE_MAX(tcflag_t) +#endif + +#ifndef TIMER_MAX +# define TIMER_MAX TYPE_MAX(timer_t) +#endif + +#ifndef TIME_MAX +# define TIME_MAX TYPE_MAX(time_t) +#endif + +#ifndef UID_MAX +# define UID_MAX TYPE_MAX(uid_t) +#endif + +#ifndef USECONDS_MAX +# define USECONDS_MAX TYPE_MAX(useconds_t) +#endif + +#ifndef U_QUAD_MAX +# define U_QUAD_MAX TYPE_MAX(u_quad_t) +#endif + + +#ifndef BLKCNT64_MIN +# define BLKCNT64_MIN TYPE_MIN(blkcnt64_t) +#endif + +#ifndef BLKCNT_MIN +# define BLKCNT_MIN TYPE_MIN(blkcnt_t) +#endif + +#ifndef BLKSIZE_MIN +# define BLKSIZE_MIN TYPE_MIN(blksize_t) +#endif + +#ifndef CC_MIN +# define CC_MIN TYPE_MIN(cc_t) +#endif + +#ifndef CLOCKID_MIN +# define CLOCKID_MIN TYPE_MIN(clockid_t) +#endif + +#ifndef CLOCK_MIN +# define CLOCK_MIN TYPE_MIN(clock_t) +#endif + +#ifndef DEV_MIN +# define DEV_MIN TYPE_MIN(dev_t) +#endif + +#ifndef FSBLKCNT64_MIN +# define FSBLKCNT64_MIN TYPE_MIN(fsblkcnt64_t) +#endif + +#ifndef FSBLKCNT_MIN +# define FSBLKCNT_MIN TYPE_MIN(fsblkcnt_t) +#endif + +#ifndef FSFILCNT64_MIN +# define FSFILCNT64_MIN TYPE_MIN(fsfilcnt64_t) +#endif + +#ifndef FSFILCNT_MIN +# define FSFILCNT_MIN TYPE_MIN(fsfilcnt_t) +#endif + +#ifndef FSID_MIN +# define FSID_MIN TYPE_MIN(fsid_t) +#endif + +#ifndef FSWORD_MIN +# define FSWORD_MIN TYPE_MIN(fsword_t) +#endif + +#ifndef GID_MIN +# define GID_MIN TYPE_MIN(gid_t) +#endif + +#ifndef ID_MIN +# define ID_MIN TYPE_MIN(id_t) +#endif + +#ifndef INO64_MIN +# define INO64_MIN TYPE_MIN(ino64_t) +#endif + +#ifndef INO_MIN +# define INO_MIN TYPE_MIN(ino_t) +#endif + +#ifndef KEY_MIN +# define KEY_MIN TYPE_MIN(key_t) +#endif + +#ifndef LOFF_MIN +# define LOFF_MIN TYPE_MIN(loff_t) +#endif + +#ifndef MODE_MIN +# define MODE_MIN TYPE_MIN(mode_t) +#endif + +#ifndef NLINK_MIN +# define NLINK_MIN TYPE_MIN(nlink_t) +#endif + +#ifndef OFF64_MIN +# define OFF64_MIN TYPE_MIN(off64_t) +#endif + +#ifndef OFF_MIN +# define OFF_MIN TYPE_MIN(off_t) +#endif + +#ifndef PID_MIN +# define PID_MIN TYPE_MIN(pid_t) +#endif + +#ifndef QUAD_MIN +# define QUAD_MIN TYPE_MIN(quad_t) +#endif + +#ifndef REGISTER_MIN +# define REGISTER_MIN TYPE_MIN(register_t) +#endif + +#ifndef RLIM64_MIN +# define RLIM64_MIN TYPE_MIN(rlim64_t) +#endif + +#ifndef RLIM_MIN +# define RLIM_MIN TYPE_MIN(rlim_t) +#endif + +#ifndef SOCKLEN_MIN +# define SOCKLEN_MIN TYPE_MIN(socklen_t) +#endif + +#ifndef SPEED_MIN +# define SPEED_MIN TYPE_MAX(speed_t) +#endif + +#ifndef SUSECONDS_MIN +# define SUSECONDS_MIN TYPE_MIN(suseconds_t) +#endif + +#ifndef TCFLAG_MIN +# define TCFLAG_MIN TYPE_MAX(tcflag_t) +#endif + +#ifndef TIMER_MIN +# define TIMER_MIN TYPE_MIN(timer_t) +#endif + +#ifndef TIME_MIN +# define TIME_MIN TYPE_MIN(time_t) +#endif + +#ifndef UID_MIN +# define UID_MIN TYPE_MIN(uid_t) +#endif + +#ifndef USECONDS_MIN +# define USECONDS_MIN TYPE_MIN(useconds_t) +#endif + +#ifndef U_QUAD_MIN +# define U_QUAD_MIN TYPE_MIN(u_quad_t) +#endif + + +#define LIBSIMPLE_INTERFACE 0x0001 +#define LIBSIMPLE_NO_HOSTNAME 0x0002 + + +#define FREE(PTR) (free(PTR), (PTR) = NULL, 0) + + +#define CLOSE(FD) ((FD) >= 0 ? (close(FD), (FD) = -1, 0) : 0) + + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) void *libsimple_rawmemchr(const void *, int); #ifndef rawmemchr # define rawmemchr libsimple_rawmemchr #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) void *libsimple_memrchr(const void *, int, size_t); #ifndef memrchr # define memrchr libsimple_memrchr #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) void *libsimple_rawmemrchr(const void *, int, size_t); #ifndef rawmemrchr # define rawmemrchr libsimple_rawmemrchr #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) char *libsimple_strchrnul(const char *, int); #ifndef strchrnul # define strchrnul libsimple_strchrnul #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) static inline char *libsimple_strend(const char *__s) { return strchr(__s, '\0'); } #ifndef strend # define strend libsimple_strend #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) static inline int libsimple_inchrset(int __c, const char *__s) { return __c && strchr(__s, __c); } #ifndef inchrset # define inchrset libsimple_inchrset #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) void *libsimple_memdup(const void *, size_t); #ifndef memdup # define memdup libsimple_memdup #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) char *libsimple_strndup(const char *, size_t); #ifndef strndup # define strndup libsimple_strndup #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void *libsimple_mempcpy(void *__d, const void *__s, size_t __n) { return &((char *)memcpy(__d, __s, __n))[__n]; } #ifndef mempcpy @@ -142,21 +625,21 @@ static inline void *libsimple_mempcpy(void *__d, const void *__s, size_t __n) * @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL * @return 1 if good, 0 on encoding error */ -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) int libsimple_isutf8(const char *, int); #ifndef isutf8 # define isutf8 libsimple_isutf8 #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1, 2), format(printf, 2, 3)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2), __format__(__printf__, 2, 3)))) int libsimple_asprintf(char **, const char *, ...); #ifndef asprintf # define asprintf libsimple_asprintf #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1, 2)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) int libsimple_vasprintf(char **, const char *, va_list); #ifndef vasprintf # define vasprintf libsimple_vasprintf @@ -210,62 +693,70 @@ int libsimple_vasprintf(char **, const char *, va_list); #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) void *libsimple_memmem(const void *, size_t, const void *, size_t); #ifndef memmem # define memmem libsimple_memmem #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) int libsimple_memstarts(const void *, size_t, const void *, size_t); #ifndef memstarts # define memstarts libsimple_memstarts #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) int libsimple_memends(const void *, size_t, const void *, size_t); #ifndef memends # define memends libsimple_memends #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) int libsimple_strstarts(const char *, const char *); #ifndef strstarts # define strstarts libsimple_strstarts #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) int libsimple_strends(const char *, const char *); #ifndef strends # define strends libsimple_strends #endif -_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) char *libsimple_strcasestr(const char *, const char *); #ifndef strcasestr # define strcasestr libsimple_strcasestr #endif +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int streq(const char *__a, const char *__b) { return !strcmp(__a, __b); } + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int strneq(const char *__a, const char *__b, size_t __n) { return !strncmp(__a, __b, __n); } + + #define malloczn(CLEAR, ...) _libsimple_malloczn((CLEAR), __VA_ARGS__, (size_t)0) #define mallocn(...) malloczn(0, __VA_ARGS__) #define callocn(...) malloczn(1, __VA_ARGS__) -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) void *libsimple_vmalloczn(int, size_t, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void *libsimple_vmallocn(size_t __n, va_list __ap) { return libsimple_vmalloczn(0, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void *libsimple_vcallocn(size_t __n, va_list __ap) { return libsimple_vmalloczn(1, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void * libsimple_malloczn(int __clear, size_t __n, ...) { @@ -275,7 +766,7 @@ libsimple_malloczn(int __clear, size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void * libsimple_mallocn(size_t __n, ...) { @@ -285,7 +776,7 @@ libsimple_mallocn(size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void * libsimple_callocn(size_t __n, ...) { @@ -297,10 +788,10 @@ libsimple_callocn(size_t __n, ...) #define reallocn(PTR, ...) _libsimple_reallocn((PTR), __VA_ARGS__, (size_t)0) -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) void *libsimple_vreallocn(void *, size_t, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) static inline void * libsimple_reallocn(void *__ptr, size_t __n, ...) { @@ -311,22 +802,22 @@ libsimple_reallocn(void *__ptr, size_t __n, ...) } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) void *enmalloc(int, size_t); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) void *encalloc(int, size_t, size_t); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) void *enrealloc(int, void *, size_t); -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __returns_nonnull__))) char *enstrdup(int, const char *); -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __returns_nonnull__))) char *enstrndup(int, const char *, size_t); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) void *enmemdup(int, const void *, size_t); #define enmalloczn(STATUS, CLEAR, ...) _libsimple_enmalloczn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0) @@ -334,19 +825,19 @@ void *enmemdup(int, const void *, size_t); #define encallocn(STATUS, ...) _libsimple_encallocn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0) #define enreallocn(STATUS, PTR, ...) _libsimple_enreallocn((STATUS), (PTR), __VA_ARGS__, (size_t)0) -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) void *libsimple_envmalloczn(int, int, size_t, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) void *libsimple_envreallocn(int, void *, size_t, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envmallocn(int __st, size_t __n, va_list __ap) { return libsimple_envmalloczn(__st, 0, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envcallocn(int __st, size_t __n, va_list __ap) { return libsimple_envmalloczn(__st, 1, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enmalloczn(int __status, int __clear, size_t __n, ...) { @@ -356,7 +847,7 @@ libsimple_enmalloczn(int __status, int __clear, size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enmallocn(int __status, size_t __n, ...) { @@ -366,7 +857,7 @@ libsimple_enmallocn(int __status, size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_encallocn(int __status, size_t __n, ...) { @@ -376,7 +867,7 @@ libsimple_encallocn(int __status, size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enreallocn(int __status, void *__ptr, size_t __n, ...) { @@ -387,22 +878,22 @@ libsimple_enreallocn(int __status, void *__ptr, size_t __n, ...) } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *emalloc(size_t __n) { return enmalloc(libsimple_default_failure_exit, __n); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *ecalloc(size_t __n, size_t __m) { return encalloc(libsimple_default_failure_exit, __n, __m); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *erealloc(void *__ptr, size_t __n) { return enrealloc(libsimple_default_failure_exit, __ptr, __n); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, __warn_unused_result__, __returns_nonnull__))) static inline char *estrdup(const char *__s) { return enstrdup(libsimple_default_failure_exit, __s); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, __warn_unused_result__, __returns_nonnull__))) static inline char *estrndup(const char *__s, size_t __n) { return enstrndup(libsimple_default_failure_exit, __s, __n); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *ememdup(const void *__s, size_t __n) { return enmemdup(libsimple_default_failure_exit, __s, __n); } #define emalloczn(CLEAR, ...) enmalloczn(libsimple_default_failure_exit, (CLEAR), __VA_ARGS__) @@ -410,23 +901,23 @@ static inline void *ememdup(const void *__s, size_t __n) { return enmemdup(libsi #define ecallocn(...) encallocn(libsimple_default_failure_exit, __VA_ARGS__) #define ereallocn(PTR, ...) enreallocn(libsimple_default_failure_exit, (PTR), __VA_ARGS__) -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evmalloczn(int __clear, size_t __n, va_list __ap) { return libsimple_envmalloczn(libsimple_default_failure_exit, __clear, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evmallocn(size_t __n, va_list __ap) { return libsimple_envcallocn(libsimple_default_failure_exit, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evcallocn(size_t __n, va_list __ap) { return libsimple_envmallocn(libsimple_default_failure_exit, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evreallocn(void *__ptr, size_t __n, va_list __ap) { return libsimple_envreallocn(libsimple_default_failure_exit, __ptr, __n, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_emalloczn(int __c, size_t __n, ...) { @@ -436,7 +927,7 @@ libsimple_emalloczn(int __c, size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_emallocn(size_t __n, ...) { @@ -446,7 +937,7 @@ libsimple_emallocn(size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_ecallocn(size_t __n, ...) { @@ -456,7 +947,7 @@ libsimple_ecallocn(size_t __n, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_ereallocn(void *__p, size_t __n, ...) { @@ -467,7 +958,13 @@ libsimple_ereallocn(void *__p, size_t __n, ...) } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) +/** + * Read an environment variable, but handle it as undefined if empty + * + * @param var The environment variable's name + * @return The environment variable's value, `NULL` if empty or not defined + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) static inline char * getenv_ne(const char *__name) { @@ -476,13 +973,13 @@ getenv_ne(const char *__name) } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) int vputenvf(const char *, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) void envputenvf(int, const char *, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 1, 2)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 1, 2)))) static inline int putenvf(const char *__fmt, ...) { @@ -492,7 +989,7 @@ putenvf(const char *__fmt, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 1, 2)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 1, 2)))) static inline void eputenvf(const char *__fmt, ...) { @@ -502,14 +999,14 @@ eputenvf(const char *__fmt, ...) va_end(__ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) static inline void evputenvf(const char *__fmt, va_list __ap) { envputenvf(libsimple_default_failure_exit, __fmt, __ap); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 2, 3)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 2, 3)))) static inline void enputenvf(int __status, const char *__fmt, ...) { @@ -521,10 +1018,10 @@ enputenvf(int __status, const char *__fmt, ...) -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) void vweprintf(const char *, va_list); -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), format(printf, 1, 2), noreturn))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2), __noreturn__))) static inline void eprintf(const char *__fmt, ...) { @@ -535,7 +1032,7 @@ eprintf(const char *__fmt, ...) exit(libsimple_default_failure_exit); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), noreturn))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __noreturn__))) static inline void veprintf(const char *__fmt, va_list __ap) { @@ -543,7 +1040,7 @@ veprintf(const char *__fmt, va_list __ap) exit(libsimple_default_failure_exit); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(2), format(printf, 2, 3), noreturn))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __format__(__printf__, 2, 3), __noreturn__))) static inline void enprintf(int __status, const char *__fmt, ...) { @@ -554,7 +1051,7 @@ enprintf(int __status, const char *__fmt, ...) exit(__status); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(2), noreturn))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __noreturn__))) static inline void venprintf(int __status, const char *__fmt, va_list __ap) { @@ -562,7 +1059,7 @@ venprintf(int __status, const char *__fmt, va_list __ap) exit(__status); } -_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), format(printf, 1, 2)))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2)))) static inline void weprintf(const char *__fmt, ...) { @@ -573,4 +1070,214 @@ weprintf(const char *__fmt, ...) } +int libsimple_sendfd(int, int); +#ifndef sendfd +# define sendfd libsimple_sendfd +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +int libsimple_recvfd(int); +#ifndef recvfd +# define recvfd libsimple_recvfd +#endif + + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +ssize_t libsimple_recvfrom_timestamped(int, void *restrict, size_t, int, struct sockaddr *restrict, + socklen_t, struct timespec *restrict); +#ifndef recvfrom_timestamped +# define recvfrom_timestamped libsimple_recvfrom_timestamped +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +static inline ssize_t +libsimple_recv_timestamped(int __fd, void *restrict __buf, size_t __n, + int __flags, struct timespec *restrict __ts) +{ + return libsimple_recvfrom_timestamped(__fd, __buf, __n, __flags, NULL, 0, __ts); +} +#ifndef recv_timestamped +# define recv_timestamped libsimple_recv_timestamped +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_sumtimespec(struct timespec *, const struct timespec *, const struct timespec *); +#ifndef sumtimespec +# define sumtimespec libsimple_sumtimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_difftimespec(struct timespec *, const struct timespec *, const struct timespec *); +#ifndef difftimespec +# define difftimespec libsimple_difftimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_multimespec(struct timespec *, const struct timespec *, int); +#ifndef multimespec +# define multimespec libsimple_multimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) +static inline int +libsimple_cmptimespec(const struct timespec *__a, const struct timespec *__b) +{ + if (__a->tv_sec != __b->tv_sec) + return __a->tv_sec < __b->tv_sec ? -1 : +1; + return __a->tv_nsec < __b->tv_nsec ? -1 : __a->tv_nsec > __b->tv_nsec; +} +#ifndef cmptimespec +# define cmptimespec libsimple_cmptimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_sumtimeval(struct timeval *, const struct timeval *, const struct timeval *); +#ifndef sumtimeval +# define sumtimeval libsimple_sumtimeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_difftimeval(struct timeval *, const struct timeval *, const struct timeval *); +#ifndef difftimeval +# define difftimeval libsimple_difftimeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_multimeval(struct timeval *, const struct timeval *, int); +#ifndef multimeval +# define multimeval libsimple_multimeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) +static inline int +libsimple_cmptimeval(const struct timeval *__a, const struct timeval *__b) +{ + if (__a->tv_sec != __b->tv_sec) + return __a->tv_sec < __b->tv_sec ? -1 : +1; + return __a->tv_usec < __b->tv_usec ? -1 : __a->tv_usec > __b->tv_usec; +} +#ifndef cmptimeval +# define cmptimeval libsimple_cmptimeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline void +libsimple_timeval2timespec(struct timespec *restrict __ts, const struct timeval *restrict __tv) +{ + __ts->tv_sec = __tv->tv_sec; + __ts->tv_nsec = __tv->tv_usec; + __ts->tv_nsec *= 1000L; +} +#ifndef timeval2timespec +# define timeval2timespec libsimple_timeval2timespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_timespec2timeval(struct timeval *restrict, const struct timespec *restrict); +#ifndef timespec2timeval +# define timespec2timeval libsimple_timespec2timeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) +int libsimple_strtotimespec(struct timespec *restrict, const char *restrict, char **restrict); +#ifndef strtotimespec +# define strtotimespec libsimple_strtotimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) +int libsimple_strtotimeval(struct timeval *restrict, const char *restrict, char **restrict); +#ifndef strtotimeval +# define strtotimeval libsimple_strtotimeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +char *libsimple_timespectostr(char *restrict, const struct timespec *restrict); +#ifndef timespectostr +# define timespectostr libsimple_timespectostr +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +char *libsimple_timevaltostr(char *restrict, const struct timeval *restrict); +#ifndef timevaltostr +# define timevaltostr libsimple_timevaltostr +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline double +libsimple_timespectodouble(const struct timespec *__ts) +{ + double __ret = (double)(__ts->tv_nsec); + __ret /= (double)1000000000L; + __ret += (double)(__ts->tv_sec); + return __ret; +} +#ifndef timespectodouble +# define timespectodouble libsimple_timespectodouble +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline double +libsimple_timevaltodouble(const struct timeval *__tv) +{ + double __ret = (double)(__tv->tv_usec); + __ret /= (double)1000000L; + __ret += (double)(__tv->tv_sec); + return __ret; +} +#ifndef timevaltodouble +# define timevaltodouble libsimple_timevaltodouble +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +void libsimple_doubletotimespec(struct timespec *, double); +#ifndef doubletotimespec +# define doubletotimespec libsimple_doubletotimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +void libsimple_doubletotimeval(struct timeval *, double); +#ifndef doubletotimeval +# define doubletotimeval libsimple_doubletotimeval +#endif + + +#define LIBSIMPLE_UNLIST(LIST, I, NP) libsimple_unlist((LIST), (I), (NP), sizeof(*(LIST))) +#ifndef UNLIST +# define UNLIST(LIST, I, NP) libsimple_unlist((LIST), (I), (NP), sizeof(*(LIST))) +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline void +libsimple_unlist(void *__list, size_t __i, size_t *__np, size_t __width) +{ + char *__lst = __list; + memmove(&__lst[__i * __width], &__lst[(__i + 1) * __width], (--*__np - __i) * __width); +} +#ifndef unlist +# define unlist libsimple_unlist +#endif + + #endif |