summary refs log tree commit diff
path: root/compat.h
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-12-23 16:26:43 -0500
committerJune McEnroe <june@causal.agency>2019-12-23 16:26:43 -0500
commit405f502a07ed696c13a720e5e6af4071be839a21 (patch)
tree3e5ee277b2a29e5f96f73f0e7490fdd79513b904 /compat.h
parentHandle folded From headers (diff)
downloadimbox-405f502a07ed696c13a720e5e6af4071be839a21.tar.gz
imbox-405f502a07ed696c13a720e5e6af4071be839a21.zip
Add (GNU/)Linux compatibility
Implements a dumb version of readpassphrase that calls getpass and
implements funopen in terms of fopencookie.
Diffstat (limited to 'compat.h')
-rw-r--r--compat.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/compat.h b/compat.h
new file mode 100644
index 0000000..55dda53
--- /dev/null
+++ b/compat.h
@@ -0,0 +1,90 @@
+/* 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/>.
+ */
+
+#ifdef __linux__
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NO_READPASSPHRASE_H
+#define RPP_STDIN 1
+static inline 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 _readfn(void *, char *, int);
+typedef int _writefn(void *, const char *, int);
+typedef fpos_t _seekfn(void *, fpos_t, int);
+typedef int _closefn(void *);
+
+struct _funopen {
+	void *cookie;
+	_readfn *readfn;
+	_writefn *writefn;
+	_closefn *closefn;
+};
+
+static inline ssize_t
+_cookie_read(void *cookie, char *buf, size_t size) {
+	struct _funopen *funopen = cookie;
+	assert((size_t)(int)size == size);
+	return funopen->readfn(funopen->cookie, buf, size);
+}
+
+static inline ssize_t
+_cookie_write(void *cookie, const char *buf, size_t size) {
+	struct _funopen *funopen = cookie;
+	assert((size_t)(int)size == size);
+	return funopen->writefn(funopen->cookie, buf, size);
+}
+
+static inline int
+_cookie_close(void *cookie) {
+	struct _funopen *funopen = cookie;
+	int ret = funopen->closefn(funopen->cookie);
+	free(cookie);
+	return ret;
+}
+
+static const cookie_io_functions_t _cookie_fns = {
+	.read = _cookie_read,
+	.write = _cookie_write,
+	.close = _cookie_close,
+};
+
+static inline FILE *
+funopen(
+	const void *cookie,
+	_readfn *readfn, _writefn *writefn, _seekfn *seekfn, _closefn *closefn
+) {
+	struct _funopen *funopen = malloc(sizeof(*funopen));
+	if (!funopen) return NULL;
+	assert(!seekfn);
+	*funopen = (struct _funopen) { (void *)cookie, readfn, writefn, closefn };
+	return fopencookie(funopen, "r+", _cookie_fns);
+}
+
+#endif /* __linux__ */