From: Elias Fleckenstein Date: Thu, 30 Sep 2021 14:15:44 +0000 (+0200) Subject: Add code X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=a6c5dd9faf12ac38b1868c7ad742947a7dbeb905;p=asprintf.git Add code --- diff --git a/README.md b/README.md new file mode 100644 index 0000000..763e1a6 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Dragonport + +Dragonport is a small C library to provide portable implementations of some GNU or Linux only methods that [dragonblocks_alpha](https://github.com/dragonblocks/dragonblocks_alpha) depends on. +It also includes methods that are technically in the POSIX standard, but are not implemented on some target platforms (or the target platforms only conform with an older standard, like Plan 9 APE). +Where possible, dragonblocks will use an already existing library, this library is just a collection of code that is part of a bigger project that dragonblocks should not depend on or that is not compatible with dragonblocks without modifications. +This library is only capable of what dragonblocks needs, and it does not intend to be general purpose. + +## Implementations +* `asprintf.c`: Taken from [libressl-portable](https://github.com/libressl-portable/portable/blob/master/crypto/compat/bsd-asprintf.c). diff --git a/asprintf.c b/asprintf.c new file mode 100644 index 0000000..98a84e9 --- /dev/null +++ b/asprintf.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Elias Fleckenstein + * + * Based on libressl-portable: + * Copyright (c) 2004 Darren Tucker. + * + * Based originally on asprintf.c from OpenBSD: + * Copyright (c) 1997 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include /* for INT_MAX */ +#include +#include /* for vsnprintf */ +#include + +#define INIT_SZ 128 + +int +vasprintf(char **str, const char *fmt, va_list ap) +{ + int ret; + va_list ap2; + char *string, *newstr; + size_t len; + + if ((string = malloc(INIT_SZ)) == NULL) + goto fail; + + va_copy(ap2, ap); + ret = vsnprintf(string, INIT_SZ, fmt, ap2); + va_end(ap2); + if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ + *str = string; + } else if (ret == INT_MAX || ret < 0) { /* Bad length */ + free(string); + goto fail; + } else { /* bigger than initial, realloc allowing for nul */ + len = (size_t)ret + 1; + if ((newstr = realloc(string, len)) == NULL) { + free(string); + goto fail; + } + va_copy(ap2, ap); + ret = vsnprintf(newstr, len, fmt, ap2); + va_end(ap2); + if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */ + free(newstr); + goto fail; + } + *str = newstr; + } + return (ret); + +fail: + *str = NULL; + errno = ENOMEM; + return (-1); +} + +int asprintf(char **str, const char *fmt, ...) +{ + va_list ap; + int ret; + + *str = NULL; + va_start(ap, fmt); + ret = vasprintf(str, fmt, ap); + va_end(ap); + + return ret; +} diff --git a/asprintf.h b/asprintf.h new file mode 100644 index 0000000..eef66c5 --- /dev/null +++ b/asprintf.h @@ -0,0 +1,9 @@ +#ifndef _DRAGONPORT_ASPINTF_H_ +#define _DRAGONPORT_ASPINTF_H_ + +#include + +int vasprintf(char **str, const char *fmt, va_list ap); +int asprintf(char **str, const char *fmt, ...); + +#endif _DRAGONPORT_ASPINTF_H_