Created
July 17, 2015 14:18
-
-
Save nonakap/243f0e87050a53b1cbf6 to your computer and use it in GitHub Desktop.
doas(1): porting OpenBSD doas(1) command to NetBSD.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment