/* $OpenBSD: strtonum.c,v 1.5 2004/07/16 18:36:05 otto Exp $ */ /* $DragonFly: src/lib/libc/stdlib/strtonum.c,v 1.1 2004/08/15 16:01:11 joerg Exp $ */ /* * 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. */ #include #include #include #define INVALID 1 #define TOOSMALL 2 #define TOOLARGE 3 static struct errval { const char *errstr; int err; } ev[4] = { { NULL, 0 }, { "invalid", EINVAL }, { "too small", ERANGE }, { "too large", ERANGE }, }; unsigned long long strtonum(const char *numstr, long long minval, unsigned long long umaxval, const char **errstrp) { long long ll, maxval = (long long)umaxval; unsigned long long ull = 0; char *ep; int error = 0; ev[0].err = errno; errno = 0; if (umaxval > LLONG_MAX ) { if (minval < 0) { error = INVALID; goto done; } ull = strtoull(numstr, &ep, 10); if (numstr == ep || *ep != '\0') error = INVALID; else if ((ull == ULLONG_MAX && errno == ERANGE) || ull > umaxval) error = TOOLARGE; else if (ull < minval) error = TOOSMALL; } else { if (minval > maxval || maxval < minval) { error = INVALID; goto done; } ll = strtoll(numstr, &ep, 10); if (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; ull = (unsigned long long)ll; } done: if (errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; if (error) ull = 0; return(ull); }