strtol(3) calls.
Add shims around strtoimax(3) and strtoumax(3) when these functions
are not available.
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
+
+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
echo "#include \"compat/strlcpy.h\"" >>$CONFIG_H
fi
+if [ -z "$STRTOI" ]; then
+ printf "Testing for strtoi ... "
+ cat <<EOF >_strtoi.c
+#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
+int main(void) {
+ int e;
+ return strtoi("1234", NULL, 0, 0, INT32_MAX, &e);
+}
+EOF
+ if $XCC _strtoi.c -o _strtoi 2>&3; then
+ STRTOI=yes
+ else
+ STRTOI=no
+ fi
+ echo "$STRTOI"
+ rm -f _strtoi.c _strtoi
+fi
+if [ "$STRTOI" = no ]; then
+ echo "COMPAT_SRCS+= compat/strtoi.c" >>$CONFIG_MK
+ echo "#include \"compat/strtoi.h\"" >>$CONFIG_H
+fi
+
if [ -z "$DPRINTF" ]; then
printf "Testing for dprintf ... "
cat <<EOF >_dprintf.c
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
const struct dhcp_opt *odopts, size_t odopts_len,
uint8_t *mask, const char *opts, int add)
{
- char *token, *o, *p, *t;
+ char *token, *o, *p;
const struct dhcp_opt *opt;
- int match;
+ int match, e;
unsigned int n;
size_t i;
if (strcmp(opt->var, token) == 0)
match = 1;
else {
- errno = 0;
- n = (unsigned int)strtol(token, &t, 0);
- if (errno == 0 && !*t)
- if (opt->option == n)
- match = 1;
+ n = (unsigned int)strtou(token, NULL, 0,
+ 0, UINT_MAX, &e);
+ if (e == 0 && opt->option == n)
+ match = 1;
}
if (match)
break;
if (strcmp(opt->var, token) == 0)
match = 1;
else {
- errno = 0;
- n = (unsigned int)strtol(token, &t, 0);
- if (errno == 0 && !*t)
- if (opt->option == n)
- match = 1;
+ n = (unsigned int)strtou(token, NULL, 0,
+ 0, UINT_MAX, &e);
+ if (e == 0 && opt->option == n)
+ match = 1;
}
if (match)
break;
#include <errno.h>
#include <getopt.h>
#include <grp.h>
+#include <inttypes.h>
#include <limits.h>
#include <paths.h>
#include <stdio.h>
{NULL, 0, NULL, '\0'}
};
-static int
-atoint(const char *s)
-{
- char *t;
- long n;
-
- errno = 0;
- n = strtol(s, &t, 0);
- if ((errno != 0 && n == 0) || s == t ||
- (errno == ERANGE && (n == LONG_MAX || n == LONG_MIN)))
- {
- if (errno == 0)
- errno = EINVAL;
- syslog(LOG_ERR, "`%s' out of range", s);
- return -1;
- }
-
- return (int)n;
-}
-
static char *
add_environ(struct if_options *ifo, const char *value, int uniq)
{
static int
parse_iaid1(uint8_t *iaid, const char *arg, size_t len, int n)
{
- unsigned long l;
+ int e;
+ uint32_t narg;
ssize_t s;
- uint32_t u32;
- char *np;
- errno = 0;
- l = strtoul(arg, &np, 0);
- if (l <= (unsigned long)UINT32_MAX && errno == 0 && *np == '\0') {
+ narg = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
+ if (e == 0) {
if (n)
- u32 = htonl((uint32_t)l);
- else
- u32 = (uint32_t)l;
- memcpy(iaid, &u32, sizeof(u32));
+ narg = htonl(narg);
+ memcpy(iaid, &narg, sizeof(narg));
return 0;
}
parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
int opt, const char *arg, struct dhcp_opt **ldop, struct dhcp_opt **edop)
{
- int i, t;
+ int e, i, t;
long l;
unsigned long u;
char *p = NULL, *fp, *np, **nconf;
ifo->options |= DHCPCD_RELEASE;
break;
case 'l':
- if (*arg == '-') {
- syslog(LOG_ERR,
- "leasetime must be a positive value");
- return -1;
- }
- errno = 0;
- ifo->leasetime = (uint32_t)strtoul(arg, NULL, 0);
- if (errno == EINVAL || errno == ERANGE) {
- syslog(LOG_ERR, "`%s' out of range", arg);
+ ifo->leasetime = (uint32_t)strtou(arg, NULL,
+ 0, 0, UINT32_MAX, &e);
+ if (e) {
+ syslog(LOG_ERR, "failed to convert leasetime %s", arg);
return -1;
}
break;
case 'm':
- ifo->metric = atoint(arg);
- if (ifo->metric < 0) {
- syslog(LOG_ERR, "metric must be a positive value");
+ ifo->metric = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
+ if (e) {
+ syslog(LOG_ERR, "failed to convert metric %s", arg);
return -1;
}
break;
ifo->options &= ~(DHCPCD_ARP | DHCPCD_STATIC);
break;
case 't':
- ifo->timeout = atoint(arg);
- if (ifo->timeout < 0) {
- syslog(LOG_ERR, "timeout must be a positive value");
+ ifo->timeout = (time_t)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
+ if (e) {
+ syslog(LOG_ERR, "failed to convert timeout");
return -1;
}
break;
}
/* No need to strip the comma */
- i = atoint(arg);
- if (i < 1 || i > 254) {
+ i = (int)strtoi(arg, NULL, 0, 1, 254, &e);
+ if (e) {
syslog(LOG_ERR, "vendor option should be between"
" 1 and 254 inclusive");
return -1;
}
break;
case 'y':
- ifo->reboot = atoint(arg);
- if (ifo->reboot < 0) {
- syslog(LOG_ERR, "reboot must be a positive value");
+ ifo->reboot = (time_t)strtoi(arg, NULL, 0, 0, UINT32_MAX, &e);
+ if (e) {
+ syslog(LOG_ERR, "failed to convert reboot %s", arg);
return -1;
}
break;
memset(&ia->addr, 0, sizeof(ia->addr));
}
if (p && ia->ia_type == D6_OPTION_IA_PD) {
- i = atoint(p);
- if (i != -1 && (i < 8 || i > 120)) {
- errno = EINVAL;
- i = -1;
- }
- if (i == -1) {
- syslog(LOG_ERR, "%s: %m", p);
+ i = (int)strtoi(p, NULL, 0, 8, 120, &e);
+ if (e) {
+ syslog(LOG_ERR,
+ "%s: failed to convert"
+ " prefix len",
+ p);
ia->prefix_len = 0;
} else
ia->prefix_len = (uint8_t)i;
if (*p == '\0')
sla->sla_set = 0;
else {
- errno = 0;
- i = atoint(p);
- if (i == -1)
+ sla->sla = (uint32_t)strtou(p, NULL,
+ 0, 0, UINT32_MAX, &e);
+ sla->sla_set = 1;
+ if (e) {
+ syslog(LOG_ERR,
+ "%s: failed to convert sla",
+ ifname);
goto err_sla;
- sla->sla = (uint32_t)i;
+ }
if (sla->sla == 0 && ia->sla_len > 1) {
syslog(LOG_ERR, "%s: cannot"
" assign multiple prefixes"
ifname);
goto err_sla;
}
- sla->sla_set = 1;
- if (errno)
- goto err_sla;
}
if (np) {
- i = atoint(np);
- if (i < 0 || i > 128)
+ sla->prefix_len = (uint8_t)strtoi(np,
+ NULL, 0, 0, 128, &e);
+ if (e) {
+ syslog(LOG_ERR, "%s: failed to "
+ "convert prefix len",
+ ifname);
goto err_sla;
- sla->prefix_len = (uint8_t)i;
+ }
} else
sla->prefix_len = 0;
} else {
return -1;
}
*fp++ = '\0';
- errno = 0;
- u = strtoul(arg, &np, 0);
- if (u > UINT32_MAX || errno != 0 || *np != '\0') {
+ u = strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
+ if (e) {
syslog(LOG_ERR, "invalid code: %s", arg);
return -1;
}
/* length */
if (np) {
*np++ = '\0';
- if ((l = atoint(np)) == -1)
+ l = (long)strtou(np, NULL, 0, 0, LONG_MAX, &e);
+ if (e) {
+ syslog(LOG_ERR, "failed to convert length");
return -1;
+ }
} else
l = 0;
t = 0;
fp = strwhite(arg);
if (fp)
*fp++ = '\0';
- errno = 0;
- u = strtoul(arg, &np, 0);
- if (u > UINT32_MAX || errno != 0 || *np != '\0') {
+ u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
+ if (e) {
syslog(LOG_ERR, "invalid code: %s", arg);
return -1;
}