[rtems-libbsd commit] Makefile: Conditionalize IPV6 files and build some commands as .rel

Joel Sherrill joel at rtems.org
Tue Oct 23 18:32:57 UTC 2012


Module:    rtems-libbsd
Branch:    master
Commit:    68e094811145d779189aaa1cf8ee13ce9ca4d0c5
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=68e094811145d779189aaa1cf8ee13ce9ca4d0c5

Author:    Joel Sherrill <joel.sherrill at oarcorp.com>
Date:      Tue Oct 23 13:31:30 2012 -0500

Makefile: Conditionalize IPV6 files and build some commands as .rel

At least ifconfig has "static" global C constructors and you have
to force the objects in.

---

 freebsd-userspace/Makefile                     |  105 +++++++++++------
 freebsd-userspace/lib/libc/net/gethostbydns.c  |    6 +
 freebsd-userspace/lib/libc/net/gethostbyht.c   |   13 ++
 freebsd-userspace/lib/libc/net/gethostnamadr.c |    4 +
 freebsd-userspace/lib/libc/stdlib/strtonum.3   |  155 ++++++++++++++++++++++++
 freebsd-userspace/lib/libc/stdlib/strtonum.c   |   68 +++++++++++
 6 files changed, 314 insertions(+), 37 deletions(-)

diff --git a/freebsd-userspace/Makefile b/freebsd-userspace/Makefile
index c763bc8..554ca64 100644
--- a/freebsd-userspace/Makefile
+++ b/freebsd-userspace/Makefile
@@ -82,7 +82,10 @@ C_FILES += lib/libc/net/if_indextoname.c
 C_FILES += lib/libc/net/if_nameindex.c
 C_FILES += lib/libc/net/if_nametoindex.c
 C_FILES += lib/libc/net/linkaddr.c
+ifneq ($(DISABLE_IPV6),yes)
 C_FILES += lib/libc/net/map_v4v6.c
+endif
+# This file is not IPV6 specific
 C_FILES += lib/libc/net/name6.c
 C_FILES += lib/libc/net/rcmd.c
 C_FILES += lib/libc/net/recv.c
@@ -102,6 +105,7 @@ C_FILES += lib/libc/resolv/res_state.c
 C_FILES += lib/libc/resolv/res_update.c
 C_FILES += lib/libc/resolv/mtctxres.c
 C_FILES += lib/libc/string/strsep.c
+C_FILES += lib/libc/stdlib/strtonum.c
 
 C_FILES += lib/libc/isc/ev_streams.c
 C_FILES += lib/libc/isc/ev_timers.c
@@ -168,7 +172,9 @@ C_FILES += rtems/rtems-shell.c
 
 # ping command sources
 C_FILES += commands/sbin/ping/ping.c
+ifneq ($(DISABLE_IPV6),yes)
 C_FILES += commands/sbin/ping6/ping6.c
+endif
 
 # route command sources
 C_FILES += commands/sbin/route/route.c
@@ -192,24 +198,26 @@ C_FILES += commands/sbin/dhclient/tables.c
 C_FILES += commands/sbin/dhclient/tree.c
 
 # ifconfig command sources
-C_FILES += commands/sbin/ifconfig/af_atalk.c
-C_FILES += commands/sbin/ifconfig/af_inet.c
-C_FILES += commands/sbin/ifconfig/af_link.c
-C_FILES += commands/sbin/ifconfig/ifbridge.c
-C_FILES += commands/sbin/ifconfig/ifclone.c
-C_FILES += commands/sbin/ifconfig/ifgif.c
-C_FILES += commands/sbin/ifconfig/ifgroup.c
-C_FILES += commands/sbin/ifconfig/iflagg.c
-C_FILES += commands/sbin/ifconfig/ifmedia.c
-C_FILES += commands/sbin/ifconfig/ifvlan.c
-C_FILES += commands/sbin/ifconfig/af_inet6.c
-C_FILES += commands/sbin/ifconfig/af_nd6.c
-C_FILES += commands/sbin/ifconfig/ifcarp.c
-C_FILES += commands/sbin/ifconfig/ifconfig.c
-C_FILES += commands/sbin/ifconfig/ifgre.c
-C_FILES += commands/sbin/ifconfig/ifieee80211.c
-C_FILES += commands/sbin/ifconfig/ifmac.c
-C_FILES += commands/sbin/ifconfig/ifpfsync.c
+# UNUSED IFCONFIG_C_FILES += commands/sbin/ifconfig/af_atalk.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/af_inet.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/af_link.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifbridge.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifclone.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifgif.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifgroup.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/iflagg.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifmedia.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifvlan.c
+ifneq ($(DISABLE_IPV6),yes)
+IFCONFIG_C_FILES += commands/sbin/ifconfig/af_inet6.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/af_nd6.c
+endif
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifcarp.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifconfig.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifgre.c
+# UNUSED IFCONFIG_C_FILES += commands/sbin/ifconfig/ifieee80211.c
+# UNUSED IFCONFIG_C_FILES += commands/sbin/ifconfig/ifmac.c
+IFCONFIG_C_FILES += commands/sbin/ifconfig/ifpfsync.c
 
 # The following two files were left out to avoid
 # porting issues.  regdomain uses an xml parser
@@ -222,31 +230,46 @@ C_FILES += commands/sbin/ifconfig/ifpfsync.c
 
 # netstat command sources
 # no need to support AppleTalk yet
-# C_FILES += commands/usr.bin/netstat/atalk.c
-C_FILES += commands/usr.bin/netstat/bpf.c
-C_FILES += commands/usr.bin/netstat/if.c
-C_FILES += commands/usr.bin/netstat/inet6.c
-C_FILES += commands/usr.bin/netstat/inet.c
-C_FILES += commands/usr.bin/netstat/ipsec.c
+# NETSTAT_C_FILES += commands/usr.bin/netstat/atalk.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/bpf.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/if.c
+ifneq ($(DISABLE_IPV6),yes)
+NETSTAT_C_FILES += commands/usr.bin/netstat/inet6.c
+endif
+NETSTAT_C_FILES += commands/usr.bin/netstat/inet.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/ipsec.c
 # no need to support IPX yet
-# C_FILES += commands/usr.bin/netstat/ipx.c
-C_FILES += commands/usr.bin/netstat/main.c
+# NETSTAT_C_FILES += commands/usr.bin/netstat/ipx.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/main.c
 # XXX does not compile yet
-C_FILES += commands/usr.bin/netstat/mbuf.c
-C_FILES += commands/usr.bin/netstat/mroute6.c
-C_FILES += commands/usr.bin/netstat/mroute.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/mbuf.c
+ifneq ($(DISABLE_IPV6),yes)
+NETSTAT_C_FILES += commands/usr.bin/netstat/mroute6.c
+endif
+NETSTAT_C_FILES += commands/usr.bin/netstat/mroute.c
 # Disable netgraph support - this is a long thread to pull
-# C_FILES += commands/usr.bin/netstat/netgraph.c
-C_FILES += commands/usr.bin/netstat/pfkey.c
+# NETSTAT_C_FILES += commands/usr.bin/netstat/netgraph.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/pfkey.c
 # Actually just route.c in FreeBSD
-C_FILES += commands/usr.bin/netstat/netstat_route.c
-C_FILES += commands/usr.bin/netstat/sctp.c
-C_FILES += commands/usr.bin/netstat/unix.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/netstat_route.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/sctp.c
+NETSTAT_C_FILES += commands/usr.bin/netstat/unix.c
 
 C_O_FILES = $(C_FILES:%.c=%.o)
 C_D_FILES = $(C_FILES:%.c=%.d)
 
+IFCONFIG_C_O_FILES = $(IFCONFIG_C_FILES:%.c=%.o)
+IFCONFIG_C_D_FILES = $(IFCONFIG_C_FILES:%.c=%.d)
+
+NETSTAT_C_O_FILES = $(NETSTAT_C_FILES:%.c=%.o)
+NETSTAT_C_D_FILES = $(NETSTAT_C_FILES:%.c=%.d)
+
 LIB = libbsdc.a
+IFCONFIG = commands/sbin/ifconfig/ifconfig.rel
+NETSTAT = commands/usr.bin/netstat/netstat.rel
+
+COMMAND_RELS = $(NETSTAT) $(IFCONFIG)
+
 GEN_FILES = include/rpc/rpcb_prot.h
 GEN_FILES += commands/sbin/route/keywords.h
 # lib/libc/net
@@ -261,11 +284,17 @@ GEN_FILES += lib/libipsec/policy_parse.c
 EXTRA_CLEAN += lib/libipsec/policy_parse.i
 EXTRA_CLEAN += lib/libipsec/y.tab.h
 
-all: $(LIB)
+all: $(LIB) 
 
-$(LIB): $(GEN_FILES) $(C_O_FILES)
+$(LIB): $(GEN_FILES) $(C_O_FILES) $(COMMAND_RELS)
 	$(AR) rcu $@ $^
 
+$(IFCONFIG): $(IFCONFIG_C_O_FILES)
+	$(LD) -r -o $@ $^
+
+$(NETSTAT): $(NETSTAT_C_O_FILES)
+	$(LD) -r -o $@ $^
+
 include/rpc/rpcb_prot.h: include/rpc/rpcb_prot.x
 	rm -f include/rpc/rpcb_prot.h
 	rpcgen -h -o include/rpc/rpcb_prot.h include/rpc/rpcb_prot.x
@@ -307,7 +336,9 @@ install: $(LIB)
 	install -c -m 644 $(LIB) $(INSTALL_BASE)
 
 clean:
-	rm -f $(LIB) $(C_O_FILES) $(C_D_FILES) $(GEN_FILES) $(CLEAN_FILES)
+	rm -f $(LIB) $(GEN_FILES) $(CLEAN_FILES)
+	rm -f $(C_O_FILES) $(IFCONFIG_C_O_FILES) $(NETSTAT_C_O_FILES)
+	rm -f $(C_D_FILES) $(IFCONFIG_C_D_FILES) $(NETSTAT_C_D_FILES)
 
 -include $(C_D_FILES)
 
diff --git a/freebsd-userspace/lib/libc/net/gethostbydns.c b/freebsd-userspace/lib/libc/net/gethostbydns.c
index fa22fed..2993a67 100644
--- a/freebsd-userspace/lib/libc/net/gethostbydns.c
+++ b/freebsd-userspace/lib/libc/net/gethostbydns.c
@@ -340,6 +340,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
 			break;
 #else
 			he->h_name = bp;
+#ifdef INET6
 			if (statp->options & RES_USE_INET6) {
 				n = strlen(bp) + 1;	/* for the \0 */
 				if (n >= MAXHOSTNAMELEN) {
@@ -349,6 +350,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
 				bp += n;
 				_map_v4v6_hostent(he, &bp, ep);
 			}
+#endif
 			RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
 			return (0);
 #endif
@@ -424,8 +426,10 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
 			he->h_name = bp;
 			bp += n;
 		}
+#ifdef INET6
 		if (statp->options & RES_USE_INET6)
 			_map_v4v6_hostent(he, &bp, ep);
+#endif
 		RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
 		return (0);
 	}
@@ -699,11 +703,13 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
 	memcpy(hed->host_addr, uaddr, len);
 	hed->h_addr_ptrs[0] = (char *)hed->host_addr;
 	hed->h_addr_ptrs[1] = NULL;
+#ifdef INET6
 	if (af == AF_INET && (statp->options & RES_USE_INET6)) {
 		_map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr);
 		he.h_addrtype = AF_INET6;
 		he.h_length = NS_IN6ADDRSZ;
 	}
+#endif
 	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
 		*errnop = errno;
 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
diff --git a/freebsd-userspace/lib/libc/net/gethostbyht.c b/freebsd-userspace/lib/libc/net/gethostbyht.c
index cb88cf9..eb995b9 100644
--- a/freebsd-userspace/lib/libc/net/gethostbyht.c
+++ b/freebsd-userspace/lib/libc/net/gethostbyht.c
@@ -115,6 +115,7 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped,
 	if (!(cp = strpbrk(p, " \t")))
 		goto again;
 	*cp++ = '\0';
+#ifdef INET6
 	if (inet_pton(AF_INET6, p, hed->host_addr) > 0) {
 		af = AF_INET6;
 		len = IN6ADDRSZ;
@@ -131,6 +132,12 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped,
 	} else {
 		goto again;
 	}
+#else
+	if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
+		af = AF_INET;
+		len = INADDRSZ;
+	}
+#endif
 	hed->h_addr_ptrs[0] = (char *)hed->host_addr;
 	hed->h_addr_ptrs[1] = NULL;
 	he->h_addr_list = hed->h_addr_ptrs;
@@ -193,8 +200,10 @@ gethostent_r(struct hostent *hptr, char *buffer, size_t buflen,
 		*h_errnop = statp->res_h_errno;
 		return (-1);
 	}
+#ifdef INET6
 	if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0)
 		return (-1);
+#endif
 	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
 		*h_errnop = statp->res_h_errno;
@@ -254,12 +263,14 @@ _ht_gethostbyname(void *rval, void *cb_data, va_list ap)
 	while ((error = gethostent_p(&he, hed, 0, statp)) == 0) {
 		if (he.h_addrtype != af)
 			continue;
+#ifdef INET6
 		if (he.h_addrtype == AF_INET &&
 		    statp->options & RES_USE_INET6) {
 			_map_v4v6_address(he.h_addr, he.h_addr);
 			he.h_length = IN6ADDRSZ;
 			he.h_addrtype = AF_INET6;
 		}
+#endif
 		if (strcasecmp(he.h_name, name) == 0)
 			break;
 		for (cp = he.h_aliases; *cp != 0; cp++)
@@ -317,6 +328,7 @@ _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
 
 	_sethosthtent(0, hed);
 	while ((error = gethostent_p(&he, hed, 0, statp)) == 0)
+#ifdef INET6
 		if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) {
 			if (he.h_addrtype == AF_INET &&
 			    statp->options & RES_USE_INET6) {
@@ -326,6 +338,7 @@ _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
 			}
 			break;
 		}
+#endif
 	_endhosthtent(hed);
 
 	if (error != 0)
diff --git a/freebsd-userspace/lib/libc/net/gethostnamadr.c b/freebsd-userspace/lib/libc/net/gethostnamadr.c
index d5aaa38..d663e28 100644
--- a/freebsd-userspace/lib/libc/net/gethostnamadr.c
+++ b/freebsd-userspace/lib/libc/net/gethostnamadr.c
@@ -458,19 +458,23 @@ fakeaddr(const char *name, int af, struct hostent *hp, char *buf,
 	}
 	strncpy(hed->hostbuf, name, MAXDNAME);
 	hed->hostbuf[MAXDNAME] = '\0';
+#ifdef INET6
 	if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) {
 		_map_v4v6_address((char *)hed->host_addr,
 		    (char *)hed->host_addr);
 		af = AF_INET6;
 	}
+#endif
 	he.h_addrtype = af;
 	switch(af) {
 	case AF_INET:
 		he.h_length = NS_INADDRSZ;
 		break;
+#ifdef INET6
 	case AF_INET6:
 		he.h_length = NS_IN6ADDRSZ;
 		break;
+#endif
 	default:
 		errno = EAFNOSUPPORT;
 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
diff --git a/freebsd-userspace/lib/libc/stdlib/strtonum.3 b/freebsd-userspace/lib/libc/stdlib/strtonum.3
new file mode 100644
index 0000000..b83aadd
--- /dev/null
+++ b/freebsd-userspace/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,155 @@
+.\" Copyright (c) 2004 Ted Unangst
+.\"
+.\" 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.
+.\"
+.\" $OpenBSD: strtonum.3,v 1.13 2006/04/25 05:15:42 tedu Exp $
+.\" $FreeBSD$
+.\"
+.Dd April 29, 2004
+.Dt STRTONUM 3
+.Os
+.Sh NAME
+.Nm strtonum
+.Nd "reliably convert string value to an integer"
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft long long
+.Fo strtonum
+.Fa "const char *nptr"
+.Fa "long long minval"
+.Fa "long long maxval"
+.Fa "const char **errstr"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn strtonum
+function converts the string in
+.Fa nptr
+to a
+.Vt "long long"
+value.
+The
+.Fn strtonum
+function was designed to facilitate safe, robust programming
+and overcome the shortcomings of the
+.Xr atoi 3
+and
+.Xr strtol 3
+family of interfaces.
+.Pp
+The string may begin with an arbitrary amount of whitespace
+(as determined by
+.Xr isspace 3 )
+followed by a single optional
+.Ql +
+or
+.Ql -
+sign.
+.Pp
+The remainder of the string is converted to a
+.Vt "long long"
+value according to base 10.
+.Pp
+The value obtained is then checked against the provided
+.Fa minval
+and
+.Fa maxval
+bounds.
+If
+.Fa errstr
+is non-null,
+.Fn strtonum
+stores an error string in
+.Fa *errstr
+indicating the failure.
+.Sh RETURN VALUES
+The
+.Fn strtonum
+function returns the result of the conversion,
+unless the value would exceed the provided bounds or is invalid.
+On error, 0 is returned,
+.Va errno
+is set, and
+.Fa errstr
+will point to an error message.
+On success,
+.Fa *errstr
+will be set to
+.Dv NULL ;
+this fact can be used to differentiate
+a successful return of 0 from an error.
+.Sh EXAMPLES
+Using
+.Fn strtonum
+correctly is meant to be simpler than the alternative functions.
+.Bd -literal -offset indent
+int iterations;
+const char *errstr;
+
+iterations = strtonum(optarg, 1, 64, &errstr);
+if (errstr)
+	errx(1, "number of iterations is %s: %s", errstr, optarg);
+.Ed
+.Pp
+The above example will guarantee that the value of iterations is between
+1 and 64 (inclusive).
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ERANGE
+The given string was out of range.
+.It Bq Er EINVAL
+The given string did not consist solely of digit characters.
+.It Bq Er EINVAL
+The supplied
+.Fa minval
+was larger than
+.Fa maxval .
+.El
+.Pp
+If an error occurs,
+.Fa errstr
+will be set to one of the following strings:
+.Pp
+.Bl -tag -width ".Li too large" -compact
+.It Li "too large"
+The result was larger than the provided maximum value.
+.It Li "too small"
+The result was smaller than the provided minimum value.
+.It Li invalid
+The string did not consist solely of digit characters.
+.El
+.Sh SEE ALSO
+.Xr atof 3 ,
+.Xr atoi 3 ,
+.Xr atol 3 ,
+.Xr atoll 3 ,
+.Xr sscanf 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3
+.Sh STANDARDS
+The
+.Fn strtonum
+function is a
+.Bx
+extension.
+The existing alternatives, such as
+.Xr atoi 3
+and
+.Xr strtol 3 ,
+are either impossible or difficult to use safely.
+.Sh HISTORY
+The
+.Fn strtonum
+function first appeared in
+.Ox 3.6 .
diff --git a/freebsd-userspace/lib/libc/stdlib/strtonum.c b/freebsd-userspace/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000..6dccd97
--- /dev/null
+++ b/freebsd-userspace/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * 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.
+ *
+ *	$OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define INVALID 	1
+#define TOOSMALL 	2
+#define TOOLARGE 	3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+    const char **errstrp)
+{
+	long long ll = 0;
+	char *ep;
+	int error = 0;
+	struct errval {
+		const char *errstr;
+		int err;
+	} ev[4] = {
+		{ NULL,		0 },
+		{ "invalid",	EINVAL },
+		{ "too small",	ERANGE },
+		{ "too large",	ERANGE },
+	};
+
+	ev[0].err = errno;
+	errno = 0;
+	if (minval > maxval)
+		error = INVALID;
+	else {
+		ll = strtoll(numstr, &ep, 10);
+		if (errno == EINVAL || numstr == ep || *ep != '\0')
+			error = INVALID;
+		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+			error = TOOSMALL;
+		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+			error = TOOLARGE;
+	}
+	if (errstrp != NULL)
+		*errstrp = ev[error].errstr;
+	errno = ev[error].err;
+	if (error)
+		ll = 0;
+
+	return (ll);
+}




More information about the vc mailing list