/* * 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 enum { INVALID = 1, TOOSMALL = 2, TOOLARGE = 3 }; long long cext_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(numstr == ep || *ep != 0) error = INVALID; else if(errno == ERANGE || ll < minval) error = TOOSMALL; else if(errno == ERANGE || ll > maxval) error = TOOLARGE; } if(errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; if(error) ll = 0; return (ll); }