1*03100a63Svk199839 /* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */ 2*03100a63Svk199839 3*03100a63Svk199839 /* 4*03100a63Svk199839 * Copyright (c) 2004 Ted Unangst and Todd Miller 5*03100a63Svk199839 * All rights reserved. 6*03100a63Svk199839 * 7*03100a63Svk199839 * Permission to use, copy, modify, and distribute this software for any 8*03100a63Svk199839 * purpose with or without fee is hereby granted, provided that the above 9*03100a63Svk199839 * copyright notice and this permission notice appear in all copies. 10*03100a63Svk199839 * 11*03100a63Svk199839 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12*03100a63Svk199839 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13*03100a63Svk199839 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14*03100a63Svk199839 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15*03100a63Svk199839 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16*03100a63Svk199839 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17*03100a63Svk199839 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18*03100a63Svk199839 */ 19*03100a63Svk199839 20*03100a63Svk199839 #pragma ident "%Z%%M% %I% %E% SMI" 21*03100a63Svk199839 22*03100a63Svk199839 #include <errno.h> 23*03100a63Svk199839 #include <limits.h> 24*03100a63Svk199839 #include <stdlib.h> 25*03100a63Svk199839 26*03100a63Svk199839 #define INVALID 1 27*03100a63Svk199839 #define TOOSMALL 2 28*03100a63Svk199839 #define TOOLARGE 3 29*03100a63Svk199839 30*03100a63Svk199839 unsigned int 31*03100a63Svk199839 strtonum(const char *numstr, unsigned int minval, unsigned int maxval, 32*03100a63Svk199839 const char **errstrp) 33*03100a63Svk199839 { 34*03100a63Svk199839 long long ll = 0; 35*03100a63Svk199839 char *ep; 36*03100a63Svk199839 int error = 0; 37*03100a63Svk199839 struct errval { 38*03100a63Svk199839 const char *errstr; 39*03100a63Svk199839 int err; 40*03100a63Svk199839 } ev[4] = { 41*03100a63Svk199839 { NULL, 0 }, 42*03100a63Svk199839 { "invalid", EINVAL }, 43*03100a63Svk199839 { "too small", ERANGE }, 44*03100a63Svk199839 { "too large", ERANGE }, 45*03100a63Svk199839 }; 46*03100a63Svk199839 47*03100a63Svk199839 ev[0].err = errno; 48*03100a63Svk199839 errno = 0; 49*03100a63Svk199839 if (minval > maxval) 50*03100a63Svk199839 error = INVALID; 51*03100a63Svk199839 else { 52*03100a63Svk199839 ll = strtoll(numstr, &ep, 10); 53*03100a63Svk199839 if (numstr == ep || *ep != '\0') 54*03100a63Svk199839 error = INVALID; 55*03100a63Svk199839 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) 56*03100a63Svk199839 error = TOOSMALL; 57*03100a63Svk199839 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) 58*03100a63Svk199839 error = TOOLARGE; 59*03100a63Svk199839 } 60*03100a63Svk199839 if (errstrp != NULL) 61*03100a63Svk199839 *errstrp = ev[error].errstr; 62*03100a63Svk199839 errno = ev[error].err; 63*03100a63Svk199839 if (error) 64*03100a63Svk199839 ll = 0; 65*03100a63Svk199839 66*03100a63Svk199839 /* 67*03100a63Svk199839 * we have already checked boundaries above so we can safely 68*03100a63Svk199839 * convert return type here 69*03100a63Svk199839 */ 70*03100a63Svk199839 return ((unsigned int)ll); 71*03100a63Svk199839 } 72