Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/usr.bin/doas/Makefile b/usr.bin/doas/Makefile
- index 809fe0b..6610edb 100644
- --- a/usr.bin/doas/Makefile
- +++ b/usr.bin/doas/Makefile
- @@ -1,14 +1,31 @@
- +# $NetBSD$
- # $OpenBSD: Makefile,v 1.1 2015/07/16 20:44:21 tedu Exp $
- -SRCS= parse.y doas.c
- +.include <bsd.own.mk>
- +
- +USE_FORT?=yes
- +WARN= 4
- PROG= doas
- +SRCS= parse.y doas.c
- MAN= doas.1 doas.conf.5
- -BINOWN= root
- +BINOWN= root
- BINMODE=4555
- -CFLAGS+= -I${.CURDIR}
- -COPTS+= -Wall
- +CPPFLAGS+=-I${.CURDIR}
- +CPPFLAGS+=-DHAVE_LOGIN_CAP_H
- +CPPFLAGS+=-DHAVE_INTTYPES_H
- +CPPFLAGS+=-DHAVE_REALLOCARR
- +CPPFLAGS+=-DHAVE_STRTOI
- +
- +DPADD+= ${LIBUTIL}
- +LDADD+= -lutil
- +
- +.if ${MKPAM} != "no"
- +CPPFLAGS+= -DUSE_PAM
- +LDADD+= -lpam ${PAM_STATIC_LDADD}
- +DPADD+= ${LIBPAM} ${PAM_STATIC_DPADD}
- +.endif
- .include <bsd.prog.mk>
- diff --git a/usr.bin/doas/doas.1 b/usr.bin/doas/doas.1
- index b9bf0d3..2e33b54 100644
- --- a/usr.bin/doas/doas.1
- +++ b/usr.bin/doas/doas.1
- @@ -1,3 +1,4 @@
- +.\" $NetBSD$
- .\" $OpenBSD: doas.1,v 1.1 2015/07/16 20:44:21 tedu Exp $
- .\"
- .\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
- diff --git a/usr.bin/doas/doas.c b/usr.bin/doas/doas.c
- index 3570cca..7ef2d64 100644
- --- a/usr.bin/doas/doas.c
- +++ b/usr.bin/doas/doas.c
- @@ -1,3 +1,4 @@
- +/* $NetBSD$ */
- /* $OpenBSD: doas.c,v 1.6 2015/07/16 23:22:08 nicm Exp $ */
- /*
- * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
- @@ -18,9 +19,10 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- +#if defined(HAVE_INTTYPES_H)
- +#include <inttypes.h>
- +#endif
- #include <limits.h>
- -#include <login_cap.h>
- -#include <bsd_auth.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- @@ -30,6 +32,21 @@
- #include <grp.h>
- #include <syslog.h>
- +#if defined(HAVE_LOGIN_CAP_H)
- +#include <login_cap.h>
- +#endif
- +
- +#if defined(USE_BSD_AUTH)
- +#include <bsd_auth.h>
- +#endif
- +
- +#if defined(USE_PAM)
- +#include <security/pam_appl.h>
- +#include <security/openpam.h>
- +
- +static struct pam_conv pamc = { openpam_ttyconv, NULL };
- +#endif
- +
- #include "doas.h"
- static void __dead
- @@ -40,7 +57,7 @@ usage(void)
- }
- size_t
- -arraylen(const char **arr)
- +arraylen(const char * const *arr)
- {
- size_t cnt = 0;
- while (*arr) {
- @@ -54,15 +71,25 @@ static int
- parseuid(const char *s, uid_t *uid)
- {
- struct passwd *pw;
- +#if defined(HAVE_STRTONUM)
- const char *errstr;
- +#else
- + int error;
- +#endif
- if ((pw = getpwnam(s)) != NULL) {
- *uid = pw->pw_uid;
- return 0;
- }
- +#if defined(HAVE_STRTONUM)
- *uid = strtonum(s, 0, UID_MAX, &errstr);
- if (errstr)
- return -1;
- +#else
- + *uid = strtoi(s, NULL, 10, 0, UID_MAX, &error);
- + if (error)
- + return -1;
- +#endif
- return 0;
- }
- @@ -82,14 +109,24 @@ static gid_t
- strtogid(const char *s)
- {
- struct group *gr;
- - const char *errstr;
- gid_t gid;
- +#if defined(HAVE_STRTONUM)
- + const char *errstr;
- +#else
- + int error;
- +#endif
- if ((gr = getgrnam(s)) != NULL)
- return gr->gr_gid;
- +#if defined(HAVE_STRTONUM)
- gid = strtonum(s, 0, GID_MAX, &errstr);
- if (errstr)
- return -1;
- +#else
- + gid = strtoi(s, NULL, 10, 0, GID_MAX, &error);
- + if (error)
- + return -1;
- +#endif
- return gid;
- }
- @@ -101,7 +138,7 @@ match(uid_t uid, gid_t *groups, int ngroups, uid_t target, const char *cmd,
- if (r->ident[0] == ':') {
- gid_t rgid = strtogid(r->ident + 1);
- - if (rgid == -1)
- + if (rgid == (gid_t)-1)
- return 0;
- for (i = 0; i < ngroups; i++) {
- if (rgid == groups[i])
- @@ -161,12 +198,12 @@ parseconfig(const char *filename)
- }
- static int
- -copyenvhelper(const char **oldenvp, const char **safeset, int nsafe,
- +copyenvhelper(const char * const *oldenvp, const char **safeset, int nsafe,
- char **envp, int ei)
- {
- int i;
- for (i = 0; i < nsafe; i++) {
- - const char **oe = oldenvp;
- + const char * const *oe = oldenvp;
- while (*oe) {
- size_t len = strlen(safeset[i]);
- if (strncmp(*oe, safeset[i], len) == 0 &&
- @@ -182,9 +219,9 @@ copyenvhelper(const char **oldenvp, const char **safeset, int nsafe,
- }
- static char **
- -copyenv(const char **oldenvp, struct rule *rule)
- +copyenv(const char * const *oldenvp, struct rule *rule)
- {
- - const char *safeset[] = {
- + static const char *safeset[] = {
- "DISPLAY", "HOME", "LOGNAME", "MAIL", "SHELL",
- "PATH", "TERM", "USER", "USERNAME",
- NULL,
- @@ -195,12 +232,18 @@ copyenv(const char **oldenvp, struct rule *rule)
- const char **extra;
- int ei;
- int i, j;
- -
- +
- if ((rule->options & KEEPENV) && !rule->envlist) {
- j = arraylen(oldenvp);
- +#if defined(HAVE_REALLOCARRAY)
- envp = reallocarray(NULL, j + 1, sizeof(char *));
- if (!envp)
- err(1, "reallocarray");
- +#else
- + envp = NULL;
- + if (reallocarr(&envp, j + 1, sizeof(char *)))
- + err(1, "reallocarr");
- +#endif
- for (i = 0; i < j; i++) {
- if (!(envp[i] = strdup(oldenvp[i])))
- err(1, "strdup");
- @@ -222,9 +265,15 @@ copyenv(const char **oldenvp, struct rule *rule)
- }
- }
- +#if defined(HAVE_REALLOCARRAY)
- envp = reallocarray(NULL, nsafe + nextras + 1, sizeof(char *));
- if (!envp)
- err(1, "can't allocate new environment");
- +#else
- + envp = NULL;
- + if (reallocarr(&envp, nsafe + nextras + 1, sizeof(char *)))
- + err(1, "can't allocate new environment");
- +#endif
- ei = 0;
- ei = copyenvhelper(oldenvp, safeset, nsafe, envp, ei);
- @@ -244,6 +293,8 @@ fail(void)
- int
- main(int argc, char **argv, char **envp)
- {
- + static const char *safepath = "/bin:/sbin:/usr/bin:/usr/sbin:"
- + "/usr/local/bin:/usr/local/sbin";
- char cmdline[1024];
- char myname[32];
- uid_t uid, target = 0;
- @@ -253,8 +304,11 @@ main(int argc, char **argv, char **envp)
- struct rule *rule;
- const char *cmd;
- int i, ch;
- - const char *safepath = "/bin:/sbin:/usr/bin:/usr/sbin:"
- - "/usr/local/bin:/usr/local/sbin";
- +#if defined(USE_PAM)
- + pam_handle_t *pamh = NULL;
- + int pam_err;
- + int pam_silent = PAM_SILENT;
- +#endif
- parseconfig("/etc/doas.conf");
- @@ -299,22 +353,84 @@ main(int argc, char **argv, char **envp)
- }
- if (!(rule->options & NOPASS)) {
- +#if defined(USE_BSD_AUTH)
- if (!auth_userokay(myname, NULL, NULL, NULL)) {
- syslog(LOG_AUTHPRIV | LOG_NOTICE,
- "failed password for %s", myname);
- fail();
- }
- +#elif defined(USE_PAM)
- +#define PAM_END(msg) do { \
- + syslog(LOG_ERR, "%s: %s", msg, pam_strerror(pamh, pam_err)); \
- + warnx("%s: %s", msg, pam_strerror(pamh, pam_err)); \
- + pam_end(pamh, pam_err); \
- + exit(EXIT_FAILURE); \
- +} while (/*CONSTCOND*/0)
- +
- + pam_err = pam_start("doas", myname, &pamc, &pamh);
- + if (pam_err != PAM_SUCCESS) {
- + if (pamh != NULL)
- + PAM_END("pam_start");
- + syslog(LOG_ERR, "pam_start failed: %s",
- + pam_strerror(pamh, pam_err));
- + errx(EXIT_FAILURE, "pam_start failed");
- + }
- +
- + switch (pam_err = pam_authenticate(pamh, pam_silent)) {
- + case PAM_SUCCESS:
- + switch (pam_err = pam_acct_mgmt(pamh, pam_silent)) {
- + case PAM_SUCCESS:
- + break;
- +
- + case PAM_NEW_AUTHTOK_REQD:
- + pam_err = pam_chauthtok(pamh,
- + pam_silent|PAM_CHANGE_EXPIRED_AUTHTOK);
- + if (pam_err != PAM_SUCCESS)
- + PAM_END("pam_chauthtok");
- + break;
- +
- + case PAM_AUTH_ERR:
- + case PAM_USER_UNKNOWN:
- + case PAM_MAXTRIES:
- + syslog(LOG_AUTHPRIV | LOG_NOTICE,
- + "failed auth for %s", myname);
- + fail();
- + break;
- +
- + default:
- + PAM_END("pam_acct_mgmt");
- + break;
- + }
- + break;
- +
- + case PAM_AUTH_ERR:
- + case PAM_USER_UNKNOWN:
- + case PAM_MAXTRIES:
- + syslog(LOG_AUTHPRIV | LOG_NOTICE,
- + "failed auth for %s", myname);
- + fail();
- + break;
- +
- + default:
- + PAM_END("pam_authenticate");
- + break;
- + }
- + pam_end(pamh, pam_err);
- +#else
- +#error No auth module!
- +#endif
- }
- - envp = copyenv((const char **)envp, rule);
- + envp = copyenv((const char * const *)envp, rule);
- pw = getpwuid(target);
- if (!pw)
- errx(1, "no passwd entry for target");
- +#if defined(HAVE_LOGIN_CAP_H)
- if (setusercontext(NULL, pw, target, LOGIN_SETGROUP |
- LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
- LOGIN_SETUSER) != 0)
- errx(1, "failed to set user context for target");
- -
- +#endif
- syslog(LOG_AUTHPRIV | LOG_INFO, "%s ran command as %s: %s",
- myname, pw->pw_name, cmdline);
- setenv("PATH", safepath, 1);
- diff --git a/usr.bin/doas/doas.conf.5 b/usr.bin/doas/doas.conf.5
- index ddfdfd6..4fd85e2 100644
- --- a/usr.bin/doas/doas.conf.5
- +++ b/usr.bin/doas/doas.conf.5
- @@ -1,3 +1,4 @@
- +.\" $NetBSD$
- .\" $OpenBSD: doas.conf.5,v 1.2 2015/07/16 21:24:07 nicm Exp $
- .\"
- .\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
- diff --git a/usr.bin/doas/doas.h b/usr.bin/doas/doas.h
- index b6d0275..4af3fd2 100644
- --- a/usr.bin/doas/doas.h
- +++ b/usr.bin/doas/doas.h
- @@ -1,3 +1,4 @@
- +/* $NetBSD$ */
- struct rule {
- int action;
- @@ -11,10 +12,30 @@ struct rule {
- extern struct rule **rules;
- extern int nrules, maxrules;
- -size_t arraylen(const char **);
- +size_t arraylen(const char * const *);
- #define PERMIT 1
- #define DENY 2
- #define NOPASS 0x1
- #define KEEPENV 0x2
- +
- +#if !defined(HAVE_REALLOCARRAY) && !defined(HAVE_REALLOCARR)
- +int reallocarr(void *ptr, size_t num, size_t size);
- +#endif /* !HAVE_REALLOCARRAY && !HAVE_REALLOCARR */
- +
- +#if !defined(HAVE_STRTOI) && !defined(HAVE_STRTONUM)
- +#if defined(HAVE_INTTYPES_H)
- +#include <stdint.h>
- +#elif defined(HAVE_LONG_LONG_INT)
- +typedef long long intmax_t;
- +#else /* !HAVE_INTTYPES_H && !HAVE_LONG_LONG_INT */
- +typedef long intmax_t;
- +#endif /* HAVE_LONG_LONG_INT */
- +intmax_t strtoi(const char *nptr, char **endptr, int base, intmax_t lo,
- + intmax_t hi, int *rstatus);
- +#endif /* !HAVE_STRTOI && !HAVE_STRTONUM */
- +
- +#if !defined(HAVE_EXECVPE)
- +int execvpe(const char *file, char * const *argv, char * const *envp);
- +#endif /* !HAVE_EXECVPE */
- diff --git a/usr.bin/doas/execvpe.c b/usr.bin/doas/execvpe.c
- new file mode 100644
- index 0000000..4a74d4b
- --- /dev/null
- +++ b/usr.bin/doas/execvpe.c
- @@ -0,0 +1,48 @@
- +/* $NetBSD$ */
- +
- +/*-
- + * Copyright (C) 2015 NONAKA Kimihiro <nonakap@gmail.com>
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- + */
- +
- +#include <unistd.h>
- +
- +#include "doas.h"
- +
- +#if !defined(HAVE_EXECVPE)
- +
- +extern char **environ;
- +
- +int
- +execvpe(const char *file, char * const *argv, char * const *envp)
- +{
- + char **oldenvp = environ;
- + int error;
- +
- + environ = (char **)(long)envp; /* XXX */
- + error = execvp(file, argv);
- + environ = oldenvp;
- + return error;
- +}
- +
- +#endif /* !HAVE_EXECVPE */
- diff --git a/usr.bin/doas/parse.y b/usr.bin/doas/parse.y
- index 089dc4f..9b084c2 100644
- --- a/usr.bin/doas/parse.y
- +++ b/usr.bin/doas/parse.y
- @@ -1,3 +1,4 @@
- +/* $NetBSD$ */
- /* $OpenBSD: parse.y,v 1.4 2015/07/16 23:02:56 nicm Exp $ */
- /*
- * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
- @@ -23,6 +24,7 @@
- #include <stdarg.h>
- #include <stdio.h>
- #include <string.h>
- +#include <stdlib.h>
- #include <err.h>
- #include "doas.h"
- @@ -77,8 +79,13 @@ rule: action ident target cmd {
- maxrules = 63;
- else
- maxrules *= 2;
- +#if defined(HAVE_REALLOCARRAY)
- if (!(rules = reallocarray(rules, maxrules, sizeof(*rules))))
- errx(1, "can't allocate rules");
- +#else
- + if (reallocarr(&rules, maxrules, sizeof(*rules)))
- + errx(1, "can't allocate rules");
- +#endif
- }
- rules[nrules++] = r;
- } ;
- @@ -116,8 +123,14 @@ envlist: /* empty */ {
- errx(1, "can't allocate envlist");
- } | envlist TSTRING {
- int nenv = arraylen($1.envlist);
- +#if defined(HAVE_REALLOCARRAY)
- if (!($$.envlist = reallocarray($1.envlist, nenv + 2, sizeof(char *))))
- errx(1, "can't allocate envlist");
- +#else
- + $$.envlist = $1.envlist;
- + if (reallocarr(&$$.envlist, nenv + 2, sizeof(char *)))
- + errx(1, "can't allocate envlist");
- +#endif
- $$.envlist[nenv] = $2.str;
- $$.envlist[nenv + 1] = NULL;
- }
- @@ -150,7 +163,7 @@ yyerror(const char *fmt, ...)
- verrx(1, fmt, va);
- }
- -struct keyword {
- +static const struct keyword {
- const char *word;
- int token;
- } keywords[] = {
- @@ -206,7 +219,7 @@ eow:
- *p = 0;
- if (c != EOF)
- ungetc(c, yyfp);
- - for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
- + for (i = 0; i < (int)(sizeof(keywords) / sizeof(keywords[0])); i++) {
- if (strcmp(buf, keywords[i].word) == 0)
- return keywords[i].token;
- }
- diff --git a/usr.bin/doas/reallocarr.c b/usr.bin/doas/reallocarr.c
- new file mode 100644
- index 0000000..342bba2
- --- /dev/null
- +++ b/usr.bin/doas/reallocarr.c
- @@ -0,0 +1,73 @@
- +/* $NetBSD$ */
- +/* NetBSD: reallocarr.c,v 1.2 2015/07/16 00:03:59 kamil Exp */
- +
- +/*-
- + * Copyright (c) 2015 Joerg Sonnenberger <joerg@NetBSD.org>.
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + *
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in
- + * the documentation and/or other materials provided with the
- + * distribution.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
- + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +
- +#include <errno.h>
- +/* Old POSIX has SIZE_MAX in limits.h */
- +#include <limits.h>
- +#include <stdint.h>
- +#include <stdlib.h>
- +#include <string.h>
- +
- +#include "doas.h"
- +
- +#if !defined(HAVE_REALLOCARR) && !defined(HAVE_REALLOCARRAY)
- +
- +int
- +reallocarr(void *ptr, size_t num, size_t size)
- +{
- + int saved_errno, result;
- + void *optr;
- + void *nptr;
- +
- + saved_errno = errno;
- + memcpy(&optr, ptr, sizeof(ptr));
- + if (num == 0 || size == 0) {
- + free(optr);
- + nptr = NULL;
- + memcpy(ptr, &nptr, sizeof(ptr));
- + errno = saved_errno;
- + return 0;
- + }
- + if ((num >= 65535 || size >= 65535) && num > SIZE_MAX / size)
- + return EOVERFLOW;
- + nptr = realloc(optr, num * size);
- + if (nptr == NULL) {
- + result = errno;
- + } else {
- + result = 0;
- + memcpy(ptr, &nptr, sizeof(ptr));
- + }
- + errno = saved_errno;
- + return result;
- +}
- +
- +#endif /* !HAVE_REALLOCARR && !HAVE_REALLOCARRAY */
- diff --git a/usr.bin/doas/strtoi.c b/usr.bin/doas/strtoi.c
- new file mode 100644
- index 0000000..ec6481f
- --- /dev/null
- +++ b/usr.bin/doas/strtoi.c
- @@ -0,0 +1,102 @@
- +/* $NetBSD$ */
- +/* NetBSD: _strtoi.h,v 1.2 2015/01/18 17:55:22 christos Exp */
- +
- +/*-
- + * Copyright (c) 1990, 1993
- + * The Regents of the University of California. All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. Neither the name of the University nor the names of its contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + *
- + * Original version ID:
- + * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp
- + *
- + * Created by Kamil Rytarowski, based on ID:
- + * NetBSD: src/common/lib/libc/stdlib/_strtoul.h,v 1.7 2013/05/17 12:55:56 joerg Exp
- + */
- +
- +#if defined(HAVE_INTTYPES_H)
- +#include <inttypes.h>
- +#endif
- +#include <stdlib.h>
- +#include <errno.h>
- +
- +#include "doas.h"
- +
- +#if !defined(HAVE_STRTOI) && !defined(HAVE_STRTONUM)
- +
- +#if defined(HAVE_STRTOIMAX)
- +#define STRTOIMAX strtoimax
- +#elif defined(HAVE_STRTOLL)
- +#define STRTOIMAX strtoll
- +#else
- +#define STRTOIMAX strtol
- +#endif
- +
- +intmax_t
- +strtoi(const char *nptr, char **endptr, int base, intmax_t lo, intmax_t hi,
- + int *rstatus)
- +{
- + int serrno;
- + intmax_t im;
- + char *ep;
- + int rep;
- +
- + if (endptr == NULL)
- + endptr = &ep;
- + if (rstatus == NULL)
- + rstatus = &rep;
- +
- + serrno = errno;
- + errno = 0;
- +
- + im = STRTOIMAX(nptr, endptr, base);
- +
- + *rstatus = errno;
- + errno = serrno;
- +
- + if (*rstatus == 0) {
- + /* No digits were found */
- + if (nptr == *endptr)
- + *rstatus = ECANCELED;
- + /* There are further characters after number */
- + else if (**endptr != '\0')
- + *rstatus = ENOTSUP;
- + }
- +
- + if (im < lo) {
- + if (*rstatus == 0)
- + *rstatus = ERANGE;
- + return lo;
- + }
- + if (im > hi) {
- + if (*rstatus == 0)
- + *rstatus = ERANGE;
- + return hi;
- + }
- +
- + return im;
- +}
- +
- +#endif /* !HAVE_STRTOI && !HAVE_STRTONUM */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement