diff options
Diffstat (limited to 'compat.c')
-rw-r--r-- | compat.c | 89 |
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); +} |