summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/strtonum.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib/strtonum.c')
-rw-r--r--src/lib/libc/stdlib/strtonum.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/lib/libc/stdlib/strtonum.c b/src/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000000..9ac0d34ee0
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,74 @@
1/* $OpenBSD: strtonum.c,v 1.1 2004/05/03 17:09:24 tedu Exp $ */
2/*
3 * Copyright (c) 2004 Ted Unangst and Todd Miller
4 * All rights reserved.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <errno.h>
20#include <limits.h>
21#include <stdlib.h>
22
23#define INVALID 1
24#define TOOSMALL 2
25#define TOOLARGE 3
26
27unsigned long long
28strtonum(const char *numstr, long long minval, unsigned long long maxval,
29 const char **errstrp)
30{
31 unsigned long long ull;
32 char *ep;
33 int error;
34 struct errval {
35 const char *errstr;
36 int errno;
37 } ev[4] = {
38 { NULL, 0 },
39 { "invalid", EINVAL },
40 { "too small", ERANGE },
41 { "too large", ERANGE },
42 };
43
44 ev[0].errno = errno;
45 errno = 0;
46 error = 0;
47 ull = 0;
48 if (minval > maxval || maxval < minval ||
49 (minval < 0 && maxval > LLONG_MAX))
50 error = INVALID;
51 else if (minval >= 0) {
52 ull = strtoull(numstr, &ep, 10);
53 if (numstr == ep || *ep != '\0')
54 error = INVALID;
55 else if ((ull == ULLONG_MAX && errno == ERANGE) || ull > maxval)
56 error = TOOLARGE;
57 } else {
58 long long ll = strtoll(numstr, &ep, 10);
59 if (numstr == ep || *ep != '\0')
60 error = INVALID;
61 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
62 error = TOOSMALL;
63 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
64 error = TOOLARGE;
65 ull = (unsigned long long)ll;
66 }
67 if (errstrp != NULL)
68 *errstrp = ev[error].errstr;
69 errno = ev[error].errno;
70 if (error)
71 ull = 0;
72
73 return (ull);
74}