]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Use strtoi(3) and strtou(3) from NetBSD-8 instead of the harder to use
authorRoy Marples <roy@marples.name>
Sat, 31 Jan 2015 01:02:07 +0000 (01:02 +0000)
committerRoy Marples <roy@marples.name>
Sat, 31 Jan 2015 01:02:07 +0000 (01:02 +0000)
strtol(3) calls.
Add shims around strtoimax(3) and strtoumax(3) when these functions
are not available.

compat/strtoi.c [new file with mode: 0644]
compat/strtoi.h [new file with mode: 0644]
configure
dhcp-common.c
if-options.c

diff --git a/compat/strtoi.c b/compat/strtoi.c
new file mode 100644 (file)
index 0000000..701d57b
--- /dev/null
@@ -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 (file)
index 0000000..69eb264
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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
index bac56d7a2392982c64075f4e5c2584f5fb656811..cf91a1711d67fbb38eeba234f183a9edcc712777 100755 (executable)
--- a/configure
+++ b/configure
@@ -636,6 +636,30 @@ if [ "$STRLCPY" = no ]; then
        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
index 3eb1b172085b48b7bf08c25677807be15c2bfd0d..109120f1f2269b1fc3fbcb2bbb5e300f74ccc4c0 100644 (file)
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
@@ -152,9 +153,9 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len,
     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;
 
@@ -169,11 +170,10 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len,
                        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;
@@ -183,11 +183,10 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len,
                                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;
index 86b0a12b6d7d449c401728588ce68a83bc2a09bb..3afd8e9d772df691a3aefd3b9f5d32b6edebe607 100644 (file)
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <getopt.h>
 #include <grp.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <paths.h>
 #include <stdio.h>
@@ -189,26 +190,6 @@ const struct option cf_options[] = {
        {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)
 {
@@ -402,19 +383,15 @@ parse_string_hwaddr(char *sbuf, size_t slen, const char *str, int clid)
 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;
        }
 
@@ -644,7 +621,7 @@ static int
 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;
@@ -734,22 +711,17 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                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;
@@ -806,9 +778,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                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;
@@ -853,8 +825,8 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                }
 
                /* 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;
@@ -895,9 +867,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                }
                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;
@@ -1332,13 +1304,12 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                                        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;
@@ -1382,11 +1353,15 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                                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"
@@ -1394,15 +1369,16 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                                                    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 {
@@ -1505,9 +1481,8 @@ err_sla:
                                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;
                        }
@@ -1525,8 +1500,11 @@ err_sla:
                /* 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;
@@ -1685,9 +1663,8 @@ err_sla:
                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;
                }