03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Copyright (c) 2004 Ted Unangst and Todd Miller
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * All rights reserved.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk *
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Permission to use, copy, modify, and distribute this software for any
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * purpose with or without fee is hereby granted, provided that the above
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * copyright notice and this permission notice appear in all copies.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk *
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#pragma ident "%Z%%M% %I% %E% SMI"
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <errno.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <limits.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <stdlib.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define INVALID 1
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define TOOSMALL 2
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define TOOLARGE 3
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkunsigned int
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkstrtonum(const char *numstr, unsigned int minval, unsigned int maxval,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk const char **errstrp)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk long long ll = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk char *ep;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int error = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct errval {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk const char *errstr;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int err;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } ev[4] = {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk { NULL, 0 },
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk { "invalid", EINVAL },
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk { "too small", ERANGE },
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk { "too large", ERANGE },
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk };
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ev[0].err = errno;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errno = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (minval > maxval)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk error = INVALID;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ll = strtoll(numstr, &ep, 10);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (numstr == ep || *ep != '\0')
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk error = INVALID;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk error = TOOSMALL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk error = TOOLARGE;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (errstrp != NULL)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk *errstrp = ev[error].errstr;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errno = ev[error].err;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (error)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ll = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * we have already checked boundaries above so we can safely
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * convert return type here
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return ((unsigned int)ll);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}