about summary refs log tree commit diff
path: root/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'compat.c')
-rw-r--r--compat.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/compat.c b/compat.c
new file mode 100644
index 0000000..347536d
--- /dev/null
+++ b/compat.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this Program, or any covered work, by linking or
+ * combining it with LibreSSL (or a modified version of that library),
+ * containing parts covered by the terms of the OpenSSL License and the
+ * original SSLeay license, the licensors of this Program grant you
+ * additional permission to convey the resulting work. Corresponding
+ * Source for a non-source form of such a combination shall include the
+ * source code for the parts of LibreSSL used as well as that of the
+ * covered work.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+char *readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) {
+	if (flags) {
+		if (!fgets(buf, bufsiz, stdin)) return NULL;
+		return strsep(&buf, "\n");
+	}
+	return getpass(prompt);
+}
+
+typedef int Read(void *, char *, int);
+typedef int Write(void *, const char *, int);
+typedef fpos_t Seek(void *, fpos_t, int);
+typedef int Close(void *);
+
+struct Funopen {
+	void *cookie;
+	Read *readfn;
+	Write *writefn;
+	Close *closefn;
+};
+
+static ssize_t cookieRead(void *cookie, char *buf, size_t size) {
+	struct Funopen *funopen = cookie;
+	return funopen->readfn(funopen->cookie, buf, size);
+}
+
+static ssize_t cookieWrite(void *cookie, const char *buf, size_t size) {
+	struct Funopen *funopen = cookie;
+	return funopen->writefn(funopen->cookie, buf, size);
+}
+
+static int cookieClose(void *cookie) {
+	struct Funopen *funopen = cookie;
+	int ret = 0;
+	if (funopen->closefn) ret = funopen->closefn(funopen->cookie);
+	free(cookie);
+	return ret;
+}
+
+FILE *funopen(
+	const void *cookie,
+	Read *readfn, Write *writefn, Seek *seekfn, Close *closefn
+) {
+	struct Funopen *funopen = malloc(sizeof(*funopen));
+	if (!funopen) return NULL;
+	funopen->cookie = (void *)cookie;
+	funopen->readfn = readfn;
+	funopen->writefn = writefn;
+	assert(!seekfn);
+	funopen->closefn = closefn;
+	cookie_io_functions_t fns = {
+		.read = (readfn ? cookieRead : NULL),
+		.write = (writefn ? cookieWrite : NULL),
+		.close = cookieClose,
+	};
+	return fopencookie(funopen, (!readfn ? "w" : !writefn ? "r" : "r+"), fns);
+}