diff options
| author | Roy Marples <roy@marples.name> | 2017-03-19 15:00:45 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2017-03-19 15:00:45 +0000 |
| commit | 353acd9d554b4020e6eb44644b05d660f8381343 (patch) | |
| tree | 57cb9e2a7e7ff204f1f67f0db18e51507e9f3c4a /compat | |
| parent | a49c2b1962e41fb7e6d5c6ef9b424bd58e2dfd2b (diff) | |
| download | dhcpcd-353acd9d554b4020e6eb44644b05d660f8381343.tar.xz | |
Move compat out of src.
Diffstat (limited to 'compat')
| -rw-r--r-- | compat/arc4random.c | 158 | ||||
| -rw-r--r-- | compat/arc4random.h | 34 | ||||
| -rw-r--r-- | compat/arc4random_uniform.c | 56 | ||||
| -rw-r--r-- | compat/arc4random_uniform.h | 34 | ||||
| -rw-r--r-- | compat/bitops.h | 188 | ||||
| -rw-r--r-- | compat/dprintf.c | 65 | ||||
| -rw-r--r-- | compat/dprintf.h | 43 | ||||
| -rw-r--r-- | compat/endian.h | 71 | ||||
| -rw-r--r-- | compat/getline.c | 75 | ||||
| -rw-r--r-- | compat/getline.h | 36 | ||||
| -rw-r--r-- | compat/pidfile.c | 269 | ||||
| -rw-r--r-- | compat/pidfile.h | 37 | ||||
| -rw-r--r-- | compat/posix_spawn.c | 157 | ||||
| -rw-r--r-- | compat/posix_spawn.h | 53 | ||||
| -rw-r--r-- | compat/queue.h | 175 | ||||
| -rw-r--r-- | compat/reallocarray.c | 46 | ||||
| -rw-r--r-- | compat/reallocarray.h | 33 | ||||
| -rw-r--r-- | compat/strlcpy.c | 52 | ||||
| -rw-r--r-- | compat/strlcpy.h | 34 | ||||
| -rw-r--r-- | compat/strtoi.c | 112 | ||||
| -rw-r--r-- | compat/strtoi.h | 37 |
21 files changed, 1765 insertions, 0 deletions
diff --git a/compat/arc4random.c b/compat/arc4random.c new file mode 100644 index 00000000..ab06df04 --- /dev/null +++ b/compat/arc4random.c @@ -0,0 +1,158 @@ +/* + * Arc4 random number generator for OpenBSD. + * Copyright 1996 David Mazieres <dm@lcs.mit.edu>. + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +/* + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include the time + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#include <sys/time.h> + +#include <fcntl.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> + +#include "arc4random.h" + +struct arc4_stream { + uint8_t i; + uint8_t j; + uint8_t s[256]; + size_t count; + pid_t stir_pid; +}; + +#define S(n) (n) +#define S4(n) S(n), S(n + 1), S(n + 2), S(n + 3) +#define S16(n) S4(n), S4(n + 4), S4(n + 8), S4(n + 12) +#define S64(n) S16(n), S16(n + 16), S16(n + 32), S16(n + 48) +#define S256 S64(0), S64(64), S64(128), S64(192) + +static struct arc4_stream rs = { .i = 0xff, .j = 0, .s = { S256 }, + .count = 0, .stir_pid = 0 }; + +#undef S +#undef S4 +#undef S16 +#undef S64 +#undef S256 + +static void +arc4_addrandom(struct arc4_stream *as, unsigned char *dat, int datlen) +{ + int n; + uint8_t si; + + as->i--; + for (n = 0; n < 256; n++) { + as->i = (uint8_t)(as->i + 1); + si = as->s[as->i]; + as->j = (uint8_t)(as->j + si + dat[n % datlen]); + as->s[as->i] = as->s[as->j]; + as->s[as->j] = si; + } + as->j = as->i; +} + +static uint8_t +arc4_getbyte(struct arc4_stream *as) +{ + uint8_t si, sj; + + as->i = (uint8_t)(as->i + 1); + si = as->s[as->i]; + as->j = (uint8_t)(as->j + si); + sj = as->s[as->j]; + as->s[as->i] = sj; + as->s[as->j] = si; + return (as->s[(si + sj) & 0xff]); +} + +static uint32_t +arc4_getword(struct arc4_stream *as) +{ + int val; + + val = arc4_getbyte(as) << 24; + val |= arc4_getbyte(as) << 16; + val |= arc4_getbyte(as) << 8; + val |= arc4_getbyte(as); + return (uint32_t)val; +} + +/* We don't care about any error on read, just use what we have + * on the stack. So mask off this GCC warning. */ +#pragma GCC diagnostic ignored "-Wunused-result" +static void +arc4_stir(struct arc4_stream *as) +{ + int fd; + struct { + struct timeval tv; + unsigned int rnd[(128 - sizeof(struct timeval)) / + sizeof(unsigned int)]; + } rdat; + size_t n; + + gettimeofday(&rdat.tv, NULL); + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + /* If there is an error reading, just use what is + * on the stack. */ + /* coverity[check_return] */ + (void)read(fd, rdat.rnd, sizeof(rdat.rnd)); + close(fd); + } + + /* fd < 0? Ah, what the heck. We'll just take + * whatever was on the stack... */ + /* coverity[uninit_use_in_call] */ + arc4_addrandom(as, (void *) &rdat, sizeof(rdat)); + + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. (N = 256 in our case.) + */ + for (n = 0; n < 256 * sizeof(uint32_t); n++) + arc4_getbyte(as); + as->count = 1600000; +} + +static void +arc4_stir_if_needed(struct arc4_stream *as) +{ + pid_t pid; + + pid = getpid(); + if (as->count <= sizeof(uint32_t) || as->stir_pid != pid) { + as->stir_pid = pid; + arc4_stir(as); + } else + as->count -= sizeof(uint32_t); +} + +uint32_t +arc4random() +{ + + arc4_stir_if_needed(&rs); + return arc4_getword(&rs); +} diff --git a/compat/arc4random.h b/compat/arc4random.h new file mode 100644 index 00000000..d8ae3c78 --- /dev/null +++ b/compat/arc4random.h @@ -0,0 +1,34 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ARC4RANDOM_H +#define ARC4RANDOM_H + +#include <stdint.h> + +uint32_t arc4random(void); +#endif diff --git a/compat/arc4random_uniform.c b/compat/arc4random_uniform.c new file mode 100644 index 00000000..b5975512 --- /dev/null +++ b/compat/arc4random_uniform.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008, Damien Miller <djm@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdint.h> +#include <stdlib.h> + +/* We need to include config.h so we pickup either the system arc4random + * or our compat one. */ +#include "../config.h" + +/* + * Calculate a uniformly distributed random number less than upper_bound + * avoiding "modulo bias". + * + * Uniformity is achieved by generating new random numbers until the one + * returned is outside the range [0, 2**32 % upper_bound). This + * guarantees the selected random number will be inside + * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) + * after reduction modulo upper_bound. + */ +uint32_t +arc4random_uniform(uint32_t upper_bound) +{ + uint32_t r, min; + + if (upper_bound < 2) + return 0; + + /* 2**32 % x == (2**32 - x) % x */ + min = -upper_bound % upper_bound; + + /* + * This could theoretically loop forever but each retry has + * p > 0.5 (worst case, usually far better) of selecting a + * number inside the range we need, so it should rarely need + * to re-roll. + */ + do + r = arc4random(); + while (r < min); + + return r % upper_bound; +} diff --git a/compat/arc4random_uniform.h b/compat/arc4random_uniform.h new file mode 100644 index 00000000..e6a9b744 --- /dev/null +++ b/compat/arc4random_uniform.h @@ -0,0 +1,34 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ARC4RANDOM_UNIFORM_H +#define ARC4RANDOM_UNIFORM_H + +#include <stdint.h> + +uint32_t arc4random_uniform(uint32_t); +#endif diff --git a/compat/bitops.h b/compat/bitops.h new file mode 100644 index 00000000..d67fa848 --- /dev/null +++ b/compat/bitops.h @@ -0,0 +1,188 @@ +/* $NetBSD: bitops.h,v 1.11 2012/12/07 02:27:58 christos Exp $ */ + +/*- + * Copyright (c) 2007, 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas and Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef COMPAT_BITOPS_H +#define COMPAT_BITOPS_H + +#include <stdint.h> +#include "../common.h" + +/* + * Find First Set functions + */ +#ifndef ffs32 +static inline int __unused +ffs32(uint32_t _n) +{ + int _v; + + if (!_n) + return 0; + + _v = 1; + if ((_n & 0x0000FFFFU) == 0) { + _n >>= 16; + _v += 16; + } + if ((_n & 0x000000FFU) == 0) { + _n >>= 8; + _v += 8; + } + if ((_n & 0x0000000FU) == 0) { + _n >>= 4; + _v += 4; + } + if ((_n & 0x00000003U) == 0) { + _n >>= 2; + _v += 2; + } + if ((_n & 0x00000001U) == 0) { + //_n >>= 1; + _v += 1; + } + return _v; +} +#endif + +#ifndef ffs64 +static inline int __unused +ffs64(uint64_t _n) +{ + int _v; + + if (!_n) + return 0; + + _v = 1; + if ((_n & 0x00000000FFFFFFFFULL) == 0) { + _n >>= 32; + _v += 32; + } + if ((_n & 0x000000000000FFFFULL) == 0) { + _n >>= 16; + _v += 16; + } + if ((_n & 0x00000000000000FFULL) == 0) { + _n >>= 8; + _v += 8; + } + if ((_n & 0x000000000000000FULL) == 0) { + _n >>= 4; + _v += 4; + } + if ((_n & 0x0000000000000003ULL) == 0) { + _n >>= 2; + _v += 2; + } + if ((_n & 0x0000000000000001ULL) == 0) { + //_n >>= 1; + _v += 1; + } + return _v; +} +#endif + +/* + * Find Last Set functions + */ +#ifndef fls32 +static __inline int __unused +fls32(uint32_t _n) +{ + int _v; + + if (!_n) + return 0; + + _v = 32; + if ((_n & 0xFFFF0000U) == 0) { + _n <<= 16; + _v -= 16; + } + if ((_n & 0xFF000000U) == 0) { + _n <<= 8; + _v -= 8; + } + if ((_n & 0xF0000000U) == 0) { + _n <<= 4; + _v -= 4; + } + if ((_n & 0xC0000000U) == 0) { + _n <<= 2; + _v -= 2; + } + if ((_n & 0x80000000U) == 0) { + //_n <<= 1; + _v -= 1; + } + return _v; +} +#endif + +#ifndef fls64 +static int __unused +fls64(uint64_t _n) +{ + int _v; + + if (!_n) + return 0; + + _v = 64; + if ((_n & 0xFFFFFFFF00000000ULL) == 0) { + _n <<= 32; + _v -= 32; + } + if ((_n & 0xFFFF000000000000ULL) == 0) { + _n <<= 16; + _v -= 16; + } + if ((_n & 0xFF00000000000000ULL) == 0) { + _n <<= 8; + _v -= 8; + } + if ((_n & 0xF000000000000000ULL) == 0) { + _n <<= 4; + _v -= 4; + } + if ((_n & 0xC000000000000000ULL) == 0) { + _n <<= 2; + _v -= 2; + } + if ((_n & 0x8000000000000000ULL) == 0) { + //_n <<= 1; + _v -= 1; + } + return _v; +} +#endif + +#endif /* COMPAT_BITOPS_H_ */ diff --git a/compat/dprintf.c b/compat/dprintf.c new file mode 100644 index 00000000..610a8f0b --- /dev/null +++ b/compat/dprintf.c @@ -0,0 +1,65 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> + +#include "dprintf.h" + +int +vdprintf(int fd, const char * __restrict fmt, va_list va) +{ + int e; + FILE *fp; + + if ((e = dup(fd)) == -1) + return -1; + + if ((fp = fdopen(e, "w")) == NULL) { + close(e); + return -1; + } + + e = vfprintf(fp, fmt, va); + fclose(fp); + return e; +} + +int +dprintf(int fd, const char * __restrict fmt, ...) +{ + int e; + va_list va; + + va_start(va, fmt); + e = vdprintf(fd, fmt, va); + va_end(va); + return e; +} + diff --git a/compat/dprintf.h b/compat/dprintf.h new file mode 100644 index 00000000..b8cd4971 --- /dev/null +++ b/compat/dprintf.h @@ -0,0 +1,43 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef DPRINTF_H +#define DPRINTF_H + +#include <stdarg.h> + +#ifndef __printflike +# if __GNUC__ > 2 || defined(__INTEL_COMPILER) +# define __printflike(a, b) __attribute__((format(printf, a, b))) +# else +# define __printflike(a, b) +# endif +#endif + +__printflike(2, 0) int vdprintf(int, const char * __restrict, va_list); +__printflike(2, 3) int dprintf(int, const char * __restrict, ...); +#endif diff --git a/compat/endian.h b/compat/endian.h new file mode 100644 index 00000000..8d01738b --- /dev/null +++ b/compat/endian.h @@ -0,0 +1,71 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2014 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ENDIAN_H +#define ENDIAN_H + +#include <stdint.h> + +inline static void +be32enc(uint8_t *buf, uint32_t u) +{ + + buf[0] = (uint8_t)((u >> 24) & 0xff); + buf[1] = (uint8_t)((u >> 16) & 0xff); + buf[2] = (uint8_t)((u >> 8) & 0xff); + buf[3] = (uint8_t)(u & 0xff); +} + +inline static void +be64enc(uint8_t *buf, uint64_t u) +{ + + be32enc(buf, (uint32_t)(u >> 32)); + be32enc(buf + sizeof(uint32_t), (uint32_t)(u & 0xffffffffULL)); +} + +inline static uint16_t +be16dec(const uint8_t *buf) +{ + + return (uint16_t)(buf[0] << 8 | buf[1]); +} + +inline static uint32_t +be32dec(const uint8_t *buf) +{ + + return (uint32_t)((uint32_t)be16dec(buf) << 16 | be16dec(buf + 2)); +} + +inline static uint64_t +be64dec(const uint8_t *buf) +{ + + return (uint64_t)((uint64_t)be32dec(buf) << 32 | be32dec(buf + 4)); +} +#endif diff --git a/compat/getline.c b/compat/getline.c new file mode 100644 index 00000000..8c0cbdff --- /dev/null +++ b/compat/getline.c @@ -0,0 +1,75 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "getline.h" + +/* Redefine a small buffer for our simple text config files */ +#undef BUFSIZ +#define BUFSIZ 128 + +ssize_t +getline(char ** __restrict buf, size_t * __restrict buflen, + FILE * __restrict fp) +{ + size_t bytes, newlen; + char *newbuf, *p; + + if (buf == NULL || buflen == NULL) { + errno = EINVAL; + return -1; + } + if (*buf == NULL) + *buflen = 0; + + bytes = 0; + do { + if (feof(fp)) + break; + if (*buf == NULL || bytes != 0 || *buflen < BUFSIZ) { + newlen = *buflen + BUFSIZ; + newbuf = realloc(*buf, newlen); + if (newbuf == NULL) + return -1; + *buf = newbuf; + *buflen = newlen; + } + p = *buf + bytes; + memset(p, 0, BUFSIZ); + if (fgets(p, BUFSIZ, fp) == NULL) + break; + bytes += strlen(p); + } while (bytes == 0 || *(*buf + (bytes - 1)) != '\n'); + if (bytes == 0) + return -1; + return bytes; +} diff --git a/compat/getline.h b/compat/getline.h new file mode 100644 index 00000000..3db807a8 --- /dev/null +++ b/compat/getline.h @@ -0,0 +1,36 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef GETLINE_H +#define GETLINE_H + +#include <sys/types.h> +#include <stdio.h> + +ssize_t getline(char ** __restrict buf, size_t * __restrict buflen, + FILE * __restrict fp); +#endif diff --git a/compat/pidfile.c b/compat/pidfile.c new file mode 100644 index 00000000..20302c29 --- /dev/null +++ b/compat/pidfile.c @@ -0,0 +1,269 @@ +/* $NetBSD: pidfile.c,v 1.14 2016/04/12 20:40:43 roy Exp $ */ + +/*- + * Copyright (c) 1999, 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe, Matthias Scheler, Julio Merino and Roy Marples. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> + +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> +#include <paths.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <sys/file.h> /* for flock(2) */ +#include "../config.h" +#include "../defs.h" + +static pid_t pidfile_pid; +static char pidfile_path[PATH_MAX]; +static int pidfile_fd = -1; + +/* Closes pidfile resources. + * + * Returns 0 on success, otherwise -1. */ +static int +pidfile_close(void) +{ + int error; + + pidfile_pid = 0; + error = close(pidfile_fd); + pidfile_fd = -1; + pidfile_path[0] = '\0'; + return error; +} + +/* Truncate, close and unlink an existent pidfile, + * if and only if it was created by this process. + * The pidfile is truncated because we may have dropped permissions + * or entered a chroot and thus unable to unlink it. + * + * Returns 0 on truncation success, otherwise -1. */ +int +pidfile_clean(void) +{ + int error; + + if (pidfile_fd == -1) { + errno = EBADF; + return -1; + } + + if (pidfile_pid != getpid()) + error = EPERM; + else if (ftruncate(pidfile_fd, 0) == -1) + error = errno; + else { + (void) unlink(pidfile_path); + error = 0; + } + + (void) pidfile_close(); + + if (error != 0) { + errno = error; + return -1; + } + return 0; +} + +/* atexit shim for pidfile_clean */ +static void +pidfile_cleanup(void) +{ + + pidfile_clean(); +} + +/* Constructs a name for a pidfile in the default location (/var/run). + * If 'bname' is NULL, uses the name of the current program for the name of + * the pidfile. + * + * Returns 0 on success, otherwise -1. */ +static int +pidfile_varrun_path(char *path, size_t len, const char *bname) +{ + + if (bname == NULL) + bname = PACKAGE; + + /* _PATH_VARRUN includes trailing / */ + if ((size_t)snprintf(path, len, "%s%s.pid", _PATH_VARRUN, bname) >= len) + { + errno = ENAMETOOLONG; + return -1; + } + return 0; +} + +/* Returns the process ID inside path on success, otherwise -1. + * If no path is given, use the last pidfile path, othewise the default one. */ +pid_t +pidfile_read(const char *path) +{ + char dpath[PATH_MAX], buf[16], *eptr; + int fd, error; + ssize_t n; + pid_t pid; + + if (path == NULL && pidfile_path[0] != '\0') + path = pidfile_path; + if (path == NULL || strchr(path, '/') == NULL) { + if (pidfile_varrun_path(dpath, sizeof(dpath), path) == -1) + return -1; + path = dpath; + } + + if ((fd = open(path, O_RDONLY | O_NONBLOCK)) == -1) + return -1; + n = read(fd, buf, sizeof(buf) - 1); + error = errno; + (void) close(fd); + if (n == -1) { + errno = error; + return -1; + } + buf[n] = '\0'; + pid = (pid_t)strtoi(buf, &eptr, 10, 1, INT_MAX, &error); + if (error && !(error == ENOTSUP && *eptr == '\n')) { + errno = error; + return -1; + } + return pid; +} + +/* Locks the pidfile specified by path and writes the process pid to it. + * The new pidfile is "registered" in the global variables pidfile_fd, + * pidfile_path and pidfile_pid so that any further call to pidfile_lock(3) + * can check if we are recreating the same file or a new one. + * + * Returns 0 on success, otherwise the pid of the process who owns the + * lock if it can be read, otherwise -1. */ +pid_t +pidfile_lock(const char *path) +{ + char dpath[PATH_MAX]; + static bool registered_atexit = false; + + /* Register for cleanup with atexit. */ + if (!registered_atexit) { + if (atexit(pidfile_cleanup) == -1) + return -1; + registered_atexit = true; + } + + if (path == NULL || strchr(path, '/') == NULL) { + if (pidfile_varrun_path(dpath, sizeof(dpath), path) == -1) + return -1; + path = dpath; + } + + /* If path has changed (no good reason), clean up the old pidfile. */ + if (pidfile_fd != -1 && strcmp(pidfile_path, path) != 0) + pidfile_clean(); + + if (pidfile_fd == -1) { + int fd, opts; + + opts = O_WRONLY | O_CREAT | O_NONBLOCK; +#ifdef O_CLOEXEC + opts |= O_CLOEXEC; +#endif +#ifdef O_EXLOCK + opts |= O_EXLOCK; +#endif + if ((fd = open(path, opts, 0644)) == -1) + goto return_pid; +#ifndef O_CLOEXEC + if ((opts = fcntl(fd, F_GETFD)) == -1 || + fctnl(fd, F_SETFL, opts | FD_CLOEXEC) == -1) + { + int error = errno; + + (void) close(fd); + errno = error; + return -1; + } +#endif +#ifndef O_EXLOCK + if (flock(fd, LOCK_EX | LOCK_NB) == -1) { + int error = errno; + + (void) close(fd); + if (error != EAGAIN) { + errno = error; + return -1; + } + fd = -1; + } +#endif + +return_pid: + if (fd == -1) { + pid_t pid; + + if (errno == EAGAIN) { + /* The pidfile is locked, return the process ID + * it contains. + * If sucessful, set errno to EEXIST. */ + if ((pid = pidfile_read(path)) != -1) + errno = EEXIST; + } else + pid = -1; + + return pid; + } + pidfile_fd = fd; + strlcpy(pidfile_path, path, sizeof(pidfile_path)); + } + + pidfile_pid = getpid(); + + /* Truncate the file, as we could be re-writing it. + * Then write the process ID. */ + if (ftruncate(pidfile_fd, 0) == -1 || + lseek(pidfile_fd, 0, SEEK_SET) == -1 || + dprintf(pidfile_fd, "%d\n", pidfile_pid) == -1) + { + int error = errno; + + pidfile_cleanup(); + errno = error; + return -1; + } + + /* Hold the fd open to persist the lock. */ + return 0; +} diff --git a/compat/pidfile.h b/compat/pidfile.h new file mode 100644 index 00000000..89ebad81 --- /dev/null +++ b/compat/pidfile.h @@ -0,0 +1,37 @@ +/* + * pidfile_lock and pidfile_read + * Copyright (c) 2016 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PIDFILE_H +#define PIDFILE_H + +#include <unistd.h> + +int pidfile_clean(void); +pid_t pidfile_lock(const char *); +pid_t pidfile_read(const char *); + +#endif diff --git a/compat/posix_spawn.c b/compat/posix_spawn.c new file mode 100644 index 00000000..0cb142e5 --- /dev/null +++ b/compat/posix_spawn.c @@ -0,0 +1,157 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2012 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* This implementation of posix_spawn is only suitable for the needs of dhcpcd + * but it could easily be extended to other applications. */ + +#include <sys/types.h> +#include <sys/wait.h> + +#include <errno.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "../common.h" +#include "posix_spawn.h" + +#ifndef _NSIG +#ifdef _SIG_MAXSIG +#define _NSIG _SIG_MAXSIG + 1 +#else +/* Guess */ +#define _NSIG SIGPWR + 1 +#endif +#endif + +extern char **environ; + +static int +posix_spawnattr_handle(const posix_spawnattr_t *attrp) +{ + struct sigaction sa; + int i; + + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) + sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL); + + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGDEF) { + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + for (i = 1; i < _NSIG; i++) { + if (sigismember(&attrp->posix_attr_sigdefault, i)) { + if (sigaction(i, &sa, NULL) == -1) + return -1; + } + } + } + + return 0; +} + +inline static int +is_vfork_safe(short int flags) +{ + return !(flags & (POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK)); +} + +int +posix_spawn(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, + char *const argv[], char *const envp[]) +{ + short int flags; + pid_t p; + volatile int error; + + error = 0; + flags = attrp ? attrp->posix_attr_flags : 0; + if (file_actions == NULL && is_vfork_safe(flags)) + p = vfork(); + else +#ifdef THERE_IS_NO_FORK + return ENOSYS; +#else + p = fork(); +#endif + switch (p) { + case -1: + return errno; + case 0: + if (attrp) { + error = posix_spawnattr_handle(attrp); + if (error) + _exit(127); + } + execve(path, argv, envp); + error = errno; + _exit(127); + default: + if (error != 0) + waitpid(p, NULL, WNOHANG); + else if (pid != NULL) + *pid = p; + return error; + } +} + +int +posix_spawnattr_init(posix_spawnattr_t *attr) +{ + + memset(attr, 0, sizeof(*attr)); + attr->posix_attr_flags = 0; + sigprocmask(0, NULL, &attr->posix_attr_sigmask); + sigemptyset(&attr->posix_attr_sigdefault); + return 0; +} + +int +posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) +{ + + attr->posix_attr_flags = flags; + return 0; +} + +int +posix_spawnattr_setsigmask(posix_spawnattr_t *attr, const sigset_t *sigmask) +{ + + attr->posix_attr_sigmask = *sigmask; + return 0; +} + +int +posix_spawnattr_setsigdefault(posix_spawnattr_t *attr, const sigset_t *sigmask) +{ + + attr->posix_attr_sigdefault = *sigmask; + return 0; +} diff --git a/compat/posix_spawn.h b/compat/posix_spawn.h new file mode 100644 index 00000000..ccfb0f0c --- /dev/null +++ b/compat/posix_spawn.h @@ -0,0 +1,53 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2012 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef POSIX_SPAWN_H +#define POSIX_SPAWN_H + +#include <signal.h> + +typedef struct { + short posix_attr_flags; +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + sigset_t posix_attr_sigmask; + sigset_t posix_attr_sigdefault; +} posix_spawnattr_t; + +typedef struct { +// int unused; +} posix_spawn_file_actions_t; + +int posix_spawn(pid_t *, const char *, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *, + char *const [], char *const []); +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *); +int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *); + +#endif diff --git a/compat/queue.h b/compat/queue.h new file mode 100644 index 00000000..99ac6b94 --- /dev/null +++ b/compat/queue.h @@ -0,0 +1,175 @@ +/* $NetBSD: queue.h,v 1.65 2013/12/25 17:19:34 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef COMPAT_QUEUE_H +#define COMPAT_QUEUE_H + +/* + * Tail queue definitions. + */ +#ifndef TAILQ_END +#define TAILQ_END(head) (NULL) +#endif + +#ifndef TAILQ_HEAD +#define _TAILQ_HEAD(name, type, qual) \ +struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ +} +#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) + +#define TAILQ_HEAD_INITIALIZER(head) \ + { TAILQ_END(head), &(head).tqh_first } + +#define _TAILQ_ENTRY(type, qual) \ +struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */\ +} +#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) +#endif /* !TAILQ_HEAD */ + +/* + * Tail queue access methods. + */ +#ifndef TAILQ_FIRST +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head)) +#endif /* !TAILQ_FIRST */ + +#ifndef TAILQ_FOREACH +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var) != TAILQ_END(head); \ + (var) = ((var)->field.tqe_next)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\ + (var) != TAILQ_END(head); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) +#endif /* !TAILQ_FOREACH */ + +#ifndef TAILQ_INIT +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = TAILQ_END(head); \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = TAILQ_END(head); \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \ + TAILQ_END(head)) \ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != TAILQ_END(head)) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) +#endif /* !TAILQ_INIT */ + +#ifndef TAILQ_REPLACE +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \ + TAILQ_END(head)) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (/*CONSTCOND*/0) +#endif /* !TAILQ_REPLACE */ + +#ifndef TAILQ_FOREACH_SAFE +#define TAILQ_FOREACH_SAFE(var, head, field, next) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && \ + ((next) = TAILQ_NEXT(var, field), 1); (var) = (next)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) != TAILQ_END(head) && \ + ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev)) +#endif /* !TAILQ_FOREACH_SAFE */ + +#ifndef TAILQ_CONCAT +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) +#endif /* !TAILQ_CONCAT */ + +#endif /* !COMAPT_QUEUE_H */ diff --git a/compat/reallocarray.c b/compat/reallocarray.c new file mode 100644 index 00000000..2c77f084 --- /dev/null +++ b/compat/reallocarray.c @@ -0,0 +1,46 @@ +/* + * reallocarray(3) + * Copyright (c) 2016 Roy Marples <roy@marples.name> + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +#include "reallocarray.h" + +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) +void * +reallocarray(void *ptr, size_t n, size_t size) +{ + + if ((n | size) >= SQRT_SIZE_MAX && n > SIZE_MAX / size) { + errno = EOVERFLOW; + return NULL; + } + return realloc(ptr, n * size); +} diff --git a/compat/reallocarray.h b/compat/reallocarray.h new file mode 100644 index 00000000..7d27fe25 --- /dev/null +++ b/compat/reallocarray.h @@ -0,0 +1,33 @@ +/* + * reallocarray(3) + * Copyright (c) 2016 Roy Marples <roy@marples.name> + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef REALLOCARRAY_H +#define REALLOCARRAY_H + +void *reallocarray(void *, size_t, size_t); + +#endif diff --git a/compat/strlcpy.c b/compat/strlcpy.c new file mode 100644 index 00000000..47776a05 --- /dev/null +++ b/compat/strlcpy.c @@ -0,0 +1,52 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include "strlcpy.h" + +size_t +strlcpy(char *dst, const char *src, size_t size) +{ + const char *s = src; + size_t n = size; + + if (n && --n) + do { + if (!(*dst++ = *src++)) + break; + } while (--n); + + if (!n) { + if (size) + *dst = '\0'; + while (*src++); + } + + + return (size_t)(src - s - 1); +} diff --git a/compat/strlcpy.h b/compat/strlcpy.h new file mode 100644 index 00000000..951390a9 --- /dev/null +++ b/compat/strlcpy.h @@ -0,0 +1,34 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef STRLCPY_H +#define STRLCPY_H + +#include <sys/types.h> + +size_t strlcpy(char *, const char *, size_t); +#endif diff --git a/compat/strtoi.c b/compat/strtoi.c new file mode 100644 index 00000000..701d57b3 --- /dev/null +++ b/compat/strtoi.c @@ -0,0 +1,112 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2015 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <inttypes.h> +#include <stdlib.h> + +#include "strtoi.h" + +intmax_t +strtoi(const char * __restrict nptr, char ** __restrict endptr, int base, + intmax_t lo, intmax_t hi, int *rstatus) +{ + int serrno; + intmax_t r; + char *ep; + int rep; + + if (endptr == NULL) + endptr = &ep; + if (rstatus == NULL) + rstatus = &rep; + + serrno = errno; + errno = 0; + r = strtoimax(nptr, endptr, base); + *rstatus = errno; + errno = serrno; + + if (*rstatus == 0) { + if (nptr == *endptr) + *rstatus = ECANCELED; + else if (**endptr != '\0') + *rstatus = ENOTSUP; + } + + if (r < lo) { + if (*rstatus == 0) + *rstatus = ERANGE; + return lo; + } + if (r > hi) { + if (*rstatus == 0) + *rstatus = ERANGE; + return hi; + } + return r; +} + +uintmax_t +strtou(const char * __restrict nptr, char ** __restrict endptr, int base, + uintmax_t lo, uintmax_t hi, int *rstatus) +{ + int serrno; + uintmax_t r; + char *ep; + int rep; + + if (endptr == NULL) + endptr = &ep; + if (rstatus == NULL) + rstatus = &rep; + + serrno = errno; + errno = 0; + r = strtoumax(nptr, endptr, base); + *rstatus = errno; + errno = serrno; + + if (*rstatus == 0) { + if (nptr == *endptr) + *rstatus = ECANCELED; + else if (**endptr != '\0') + *rstatus = ENOTSUP; + } + + if (r < lo) { + if (*rstatus == 0) + *rstatus = ERANGE; + return lo; + } + if (r > hi) { + if (*rstatus == 0) + *rstatus = ERANGE; + return hi; + } + return r; +} diff --git a/compat/strtoi.h b/compat/strtoi.h new file mode 100644 index 00000000..4b0c878c --- /dev/null +++ b/compat/strtoi.h @@ -0,0 +1,37 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2015 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef STRTOI_H +#define STRTOI_H + +#include <inttypes.h> + +intmax_t strtoi(const char * __restrict nptr, char ** __restrict endptr, + int base, intmax_t lo, intmax_t hi, int *rstatus); +uintmax_t strtou(const char * __restrict nptr, char ** __restrict endptr, + int base, uintmax_t lo, uintmax_t hi, int *rstatus); +#endif |
