~sircmpwn/public-inbox

gmni: Add static library for gmni v7 PROPOSED

Martijn Braam: 1
 Add static library for gmni

 14 files changed, 57 insertions(+), 332 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/public-inbox/patches/14496/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH gmni v7] Add static library for gmni Export this patch

---
 .gitignore     |   2 +
 Makefile       |  27 +++++++-
 config.sh      |   3 +-
 configure      |  17 ++++-
 include/gmni.h | 164 -------------------------------------------------
 include/tofu.h |  49 ---------------
 include/url.h  | 103 -------------------------------
 src/client.c   |   4 +-
 src/gmni.c     |   4 +-
 src/gmnlm.c    |   6 +-
 src/parser.c   |   2 +-
 src/tofu.c     |   4 +-
 src/url.c      |   2 +-
 src/util.c     |   2 +-
 14 files changed, 57 insertions(+), 332 deletions(-)
 delete mode 100644 include/gmni.h
 delete mode 100644 include/tofu.h
 delete mode 100644 include/url.h

diff --git a/.gitignore b/.gitignore
index 6ec8d51..4a40b62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ gmni
gmnlm
*.1
*.o
*.a
*.pc
diff --git a/Makefile b/Makefile
index 5ac44db..22fed5d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
.POSIX:
.SUFFIXES:
OUTDIR=.build
VERSION=0.0.0
include $(OUTDIR)/config.mk
include $(OUTDIR)/cppcache

@@ -12,9 +13,26 @@ gmnlm: $(gmnlm_objects)
	@printf 'CCLD\t$@\n'
	@$(CC) $(LDFLAGS) -o $@ $(gmnlm_objects) $(LIBS)

libgmni.a: $(libgmni.a_objects)
	@printf 'AR\t$@\n'
	@$(AR) -rcs $@ $(libgmni.a_objects)

doc/gmni.1: doc/gmni.scd
doc/gmnlm.1: doc/gmnlm.scd

libgmni.pc:
	@printf 'GEN\t$@\n'
	@printf 'prefix=%s\n' "$(PREFIX)" > $@
	@printf 'exec_prefix=$${prefix}\n' >> $@
	@printf 'includedir=$${prefix}/include\n' >> $@
	@printf 'libdir=$${prefix}/lib\n' >> $@
	@printf 'Name: libgmni\n' >> $@
	@printf 'Version: %s\n' "$(VERSION)" >> $@
	@printf 'Description: The gmni client library\n' >> $@
	@printf 'Requires: libssl libcrypto\n' >> $@
	@printf 'Cflags: -I$${includedir}/gmni\n' >> $@
	@printf 'Libs: -L$${libdir} -lgmni\n' >> $@

.SUFFIXES: .c .o .scd .1

.c.o:
@@ -22,7 +40,7 @@ doc/gmnlm.1: doc/gmnlm.scd
	@touch $(OUTDIR)/cppcache
	@grep $< $(OUTDIR)/cppcache >/dev/null || \
		$(CPP) $(CFLAGS) -MM -MT $@ $< >> $(OUTDIR)/cppcache
	@$(CC) -c $(CFLAGS) -o $@ $<
	@$(CC) -c -fPIC $(CFLAGS) -o $@ $<

.scd.1:
	@printf 'SCDOC\t$@\n'
@@ -31,7 +49,7 @@ doc/gmnlm.1: doc/gmnlm.scd
docs: doc/gmni.1 doc/gmnlm.1

clean:
	@rm -f gmni gmnlm doc/gmni.1 doc/gmnlm.1 $(gmnlm_objects) $(gmni_objects)
	@rm -f gmni gmnlm libgmni.a libgmni.pc doc/gmni.1 doc/gmnlm.1 $(gmnlm_objects) $(gmni_objects)

distclean: clean
	@rm -rf "$(OUTDIR)"
@@ -41,6 +59,11 @@ install: all
	mkdir -p $(MANDIR)/man1
	install -Dm755 gmni $(BINDIR)/gmni
	install -Dm755 gmnlm $(BINDIR)/gmnlm
	install -Dm755 libgmni.a $(LIBDIR)/libgmni.a
	install -Dm644 include/gmni/gmni.h $(INCLUDEDIR)/gmni/gmni.h
	install -Dm644 include/gmni/tofu.h $(INCLUDEDIR)/gmni/tofu.h
	install -Dm644 include/gmni/url.h $(INCLUDEDIR)/gmni/url.h
	install -Dm644 libgmni.pc $(LIBDIR)/pkgconfig
	install -Dm644 doc/gmni.1 $(MANDIR)/man1/gmni.1
	install -Dm644 doc/gmnlm.1 $(MANDIR)/man1/gmnlm.1

diff --git a/config.sh b/config.sh
index b03dfff..a696362 100644
--- a/config.sh
+++ b/config.sh
@@ -134,6 +134,7 @@ run_configure() {
	_INSTDIR=\$(DESTDIR)\$(PREFIX)
	BINDIR?=${BINDIR:-\$(_INSTDIR)/bin}
	LIBDIR?=${LIBDIR:-\$(_INSTDIR)/lib}
	INCLUDEDIR?=${INCLUDEDIR:-\$(_INSTDIR)/include}
	MANDIR?=${MANDIR:-\$(_INSTDIR)/share/man}
	CACHE=\$(OUTDIR)/cache
	CFLAGS=${CFLAGS}
@@ -146,7 +147,7 @@ run_configure() {
	
	for target in $all
	do
		$target >>"$outdir"/config.mk
		${target//./_} >>"$outdir"/config.mk
	done
	echo done

diff --git a/configure b/configure
index 44db11c..e82a0e2 100755
--- a/configure
+++ b/configure
@@ -23,6 +23,21 @@ gmnlm() {
		src/util.c
}

all="gmni gmnlm"
libgmni_a() {
	genrules libgmni.a \
		src/client.c \
		src/escape.c \
		src/tofu.c \
		src/url.c \
		src/util.c \
		src/parser.c
}

libgmni_pc() {
	:
}

all="gmni gmnlm libgmni.a libgmni.pc"


run_configure
diff --git a/include/gmni.h b/include/gmni.h
deleted file mode 100644
index 7e27b48..0000000
--- a/include/gmni.h
@@ -1,164 +0,0 @@
#ifndef GEMINI_CLIENT_H
#define GEMINI_CLIENT_H
#include <netdb.h>
#include <openssl/ssl.h>
#include <stdbool.h>
#include <sys/socket.h>

enum gemini_result {
	GEMINI_OK,
	GEMINI_ERR_OOM,
	GEMINI_ERR_INVALID_URL,
	GEMINI_ERR_NOT_GEMINI,
	GEMINI_ERR_RESOLVE,
	GEMINI_ERR_CONNECT,
	GEMINI_ERR_SSL,
	GEMINI_ERR_SSL_VERIFY,
	GEMINI_ERR_IO,
	GEMINI_ERR_PROTOCOL,
};

enum gemini_status {
	GEMINI_STATUS_INPUT = 10,
	GEMINI_STATUS_SENSITIVE_INPUT = 11,
	GEMINI_STATUS_SUCCESS = 20,
	GEMINI_STATUS_REDIRECT_TEMPORARY = 30,
	GEMINI_STATUS_REDIRECT_PERMANENT = 31,
	GEMINI_STATUS_TEMPORARY_FAILURE = 40,
	GEMINI_STATUS_SERVER_UNAVAILABLE = 41,
	GEMINI_STATUS_CGI_ERROR = 42,
	GEMINI_STATUS_PROXY_ERROR = 43,
	GEMINI_STATUS_SLOW_DOWN = 44,
	GEMINI_STATUS_PERMANENT_FAILURE = 50,
	GEMINI_STATUS_NOT_FOUND = 51,
	GEMINI_STATUS_GONE = 52,
	GEMINI_STATUS_PROXY_REQUEST_REFUSED = 53,
	GEMINI_STATUS_BAD_REQUEST = 59,
	GEMINI_STATUS_CLIENT_CERTIFICATE_REQUIRED = 60,
	GEMINI_STATUS_CERTIFICATE_NOT_AUTHORIZED = 61,
	GEMINI_STATUS_CERTIFICATE_NOT_VALID = 62,
};

enum gemini_status_class {
	GEMINI_STATUS_CLASS_INPUT = 10,
	GEMINI_STATUS_CLASS_SUCCESS = 20,
	GEMINI_STATUS_CLASS_REDIRECT = 30,
	GEMINI_STATUS_CLASS_TEMPORARY_FAILURE = 40,
	GEMINI_STATUS_CLASS_PERMANENT_FAILURE = 50,
	GEMINI_STATUS_CLASS_CLIENT_CERTIFICATE_REQUIRED = 60,
};

struct gemini_response {
	enum gemini_status status;
	char *meta;

	// Response body may be read from here if appropriate:
	BIO *bio;

	// Connection state
	SSL_CTX *ssl_ctx;
	SSL *ssl;
	int fd;
};

struct gemini_options {
	// If NULL, an SSL context will be created. If unset, the ssl field
	// must also be NULL.
	SSL_CTX *ssl_ctx;

	// If ai_family != AF_UNSPEC (the default value on most systems), the
	// client will connect to this address and skip name resolution.
	struct addrinfo *addr;

	// If non-NULL, these hints are provided to getaddrinfo. Useful, for
	// example, to force IPv4/IPv6.
	struct addrinfo *hints;
};

// Requests the specified URL via the gemini protocol. If options is non-NULL,
// it may specify some additional configuration to adjust client behavior.
//
// Returns a value indicating the success of the request.
//
// Caller must call gemini_response_finish afterwards to clean up resources
// before exiting or re-using it for another request.
enum gemini_result gemini_request(const char *url,
		struct gemini_options *options,
		struct gemini_response *resp);

// Must be called after gemini_request in order to free up the resources
// allocated during the request.
void gemini_response_finish(struct gemini_response *resp);

// Returns a user-friendly string describing an error.
const char *gemini_strerr(enum gemini_result r, struct gemini_response *resp);

// Returns the given URL with the input response set to the specified value.
// The caller must free the string.
char *gemini_input_url(const char *url, const char *input);

// Returns the general response class (i.e. with the second digit set to zero)
// of the given Gemini status code.
enum gemini_status_class gemini_response_class(enum gemini_status status);

enum gemini_tok {
	GEMINI_TEXT,
	GEMINI_LINK,
	GEMINI_PREFORMATTED_BEGIN,
	GEMINI_PREFORMATTED_END,
	GEMINI_PREFORMATTED_TEXT,
	GEMINI_HEADING,
	GEMINI_LIST_ITEM,
	GEMINI_QUOTE,
};

struct gemini_token {
	enum gemini_tok token;

	// The token field determines which of the union members is valid.
	union {
		char *text;

		struct {
			char *text;
			char *url; // May be NULL
		} link;

		char *preformatted;

		struct {
			char *title;
			int level; // 1, 2, or 3
		} heading;

		char *list_item;
		char *quote_text;
	};
};

struct gemini_parser {
	BIO *f;
	char *buf;
	size_t bufsz;
	size_t bufln;
	bool preformatted;
};

// Initializes a text/gemini parser which reads from the specified BIO.
void gemini_parser_init(struct gemini_parser *p, BIO *f);

// Finishes this text/gemini parser and frees up its resources.
void gemini_parser_finish(struct gemini_parser *p);

// Reads the next token from a text/gemini file.
// 
// Returns 0 on success, 1 on EOF, and -1 on failure.
//
// Caller must call gemini_token_finish before exiting or re-using the token
// parameter.
int gemini_parser_next(struct gemini_parser *p, struct gemini_token *token);

// Must be called after gemini_next to free up resources for the next token.
void gemini_token_finish(struct gemini_token *token);

#endif
diff --git a/include/tofu.h b/include/tofu.h
deleted file mode 100644
index a88167b..0000000
--- a/include/tofu.h
@@ -1,49 +0,0 @@
#ifndef GEMINI_TOFU_H
#define GEMINI_TOFU_H
#include <limits.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <time.h>

enum tofu_error {
	TOFU_VALID,
	// Expired, wrong CN, etc.
	TOFU_INVALID_CERT,
	// Cert is valid but we haven't seen it before
	TOFU_UNTRUSTED_CERT,
	// Cert is valid but we already trust another cert for this host
	TOFU_FINGERPRINT_MISMATCH,
};

enum tofu_action {
	TOFU_ASK,
	TOFU_FAIL,
	TOFU_TRUST_ONCE,
	TOFU_TRUST_ALWAYS,
};

struct known_host {
	char *host, *fingerprint;
	time_t expires;
	int lineno;
	struct known_host *next;
};

// Called when the user needs to be prompted to agree to trust an unknown
// certificate. Return true to trust this certificate.
typedef enum tofu_action (tofu_callback_t)(enum tofu_error error,
	const char *fingerprint, struct known_host *host, void *data);

struct gemini_tofu {
	char known_hosts_path[PATH_MAX+1];
	struct known_host *known_hosts;
	int lineno;
	tofu_callback_t *callback;
	void *cb_data;
};

void gemini_tofu_init(struct gemini_tofu *tofu,
		SSL_CTX *ssl_ctx, tofu_callback_t *cb, void *data);
void gemini_tofu_finish(struct gemini_tofu *tofu);

#endif
diff --git a/include/url.h b/include/url.h
deleted file mode 100644
index 155fd55..0000000
--- a/include/url.h
@@ -1,103 +0,0 @@
#ifndef URLAPI_H
#define URLAPI_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at https://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/

/* the error codes for the URL API */
typedef enum {
  CURLUE_OK,
  CURLUE_BAD_HANDLE,          /* 1 */
  CURLUE_BAD_PARTPOINTER,     /* 2 */
  CURLUE_MALFORMED_INPUT,     /* 3 */
  CURLUE_BAD_PORT_NUMBER,     /* 4 */
  CURLUE_UNSUPPORTED_SCHEME,  /* 5 */
  CURLUE_URLDECODE,           /* 6 */
  CURLUE_OUT_OF_MEMORY,       /* 7 */
  CURLUE_USER_NOT_ALLOWED,    /* 8 */
  CURLUE_UNKNOWN_PART,        /* 9 */
  CURLUE_NO_SCHEME,           /* 10 */
  CURLUE_NO_USER,             /* 11 */
  CURLUE_NO_PASSWORD,         /* 12 */
  CURLUE_NO_OPTIONS,          /* 13 */
  CURLUE_NO_HOST,             /* 14 */
  CURLUE_NO_PORT,             /* 15 */
  CURLUE_NO_QUERY,            /* 16 */
  CURLUE_NO_FRAGMENT          /* 17 */
} CURLUcode;

typedef enum {
  CURLUPART_URL,
  CURLUPART_SCHEME,
  CURLUPART_USER,
  CURLUPART_PASSWORD,
  CURLUPART_OPTIONS,
  CURLUPART_HOST,
  CURLUPART_PORT,
  CURLUPART_PATH,
  CURLUPART_QUERY,
  CURLUPART_FRAGMENT
} CURLUPart;

#define CURLU_PATH_AS_IS (1<<4)         /* leave dot sequences */
#define CURLU_DISALLOW_USER (1<<5)      /* no user+password allowed */
#define CURLU_URLDECODE (1<<6)          /* URL decode on get */
#define CURLU_URLENCODE (1<<7)          /* URL encode on set */
#define CURLU_APPENDQUERY (1<<8)        /* append a form style part */

typedef struct Curl_URL CURLU;

/*
 * curl_url() creates a new CURLU handle and returns a pointer to it.
 * Must be freed with curl_url_cleanup().
 */
struct Curl_URL *curl_url(void);

/*
 * curl_url_cleanup() frees the CURLU handle and related resources used for
 * the URL parsing. It will not free strings previously returned with the URL
 * API.
 */
void curl_url_cleanup(struct Curl_URL *handle);

/*
 * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
 * handle must also be freed with curl_url_cleanup().
 */
struct Curl_URL *curl_url_dup(struct Curl_URL *in);

/*
 * curl_url_get() extracts a specific part of the URL from a CURLU
 * handle. Returns error code. The returned pointer MUST be freed with
 * free() afterwards.
 */
CURLUcode curl_url_get(struct Curl_URL *handle, CURLUPart what,
	char **part, unsigned int flags);

/*
 * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
 * error code. The passed in string will be copied. Passing a NULL instead of
 * a part string, clears that part.
 */
CURLUcode curl_url_set(struct Curl_URL *handle, CURLUPart what,
	const char *part, unsigned int flags);

#endif
diff --git a/src/client.c b/src/client.c
index 398e133..8b6b9e7 100644
--- a/src/client.c
+++ b/src/client.c
@@ -9,8 +9,8 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "gmni.h"
#include "url.h"
#include <gmni/gmni.h>
#include <gmni/url.h>

static enum gemini_result
gemini_get_addrinfo(struct Curl_URL *uri, struct gemini_options *options, 
diff --git a/src/gmni.c b/src/gmni.c
index 000a565..8299a60 100644
--- a/src/gmni.c
+++ b/src/gmni.c
@@ -12,8 +12,8 @@
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include "gmni.h"
#include "tofu.h"
#include <gmni/gmni.h>
#include <gmni/tofu.h>
#include "util.h"

static void
diff --git a/src/gmnlm.c b/src/gmnlm.c
index 245ec85..2fba84e 100644
--- a/src/gmnlm.c
+++ b/src/gmnlm.c
@@ -14,9 +14,9 @@
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include "gmni.h"
#include "tofu.h"
#include "url.h"
#include <gmni/gmni.h>
#include <gmni/tofu.h>
#include <gmni/url.h>
#include "util.h"

struct link {
diff --git a/src/parser.c b/src/parser.c
index 5794151..ad2c0e6 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -5,7 +5,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "gmni.h"
#include <gmni/gmni.h>

void
gemini_parser_init(struct gemini_parser *p, BIO *f)
diff --git a/src/tofu.c b/src/tofu.c
index 48a627f..863efc6 100644
--- a/src/tofu.c
+++ b/src/tofu.c
@@ -10,8 +10,8 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "gmni.h"
#include "tofu.h"
#include <gmni/gmni.h>
#include <gmni/tofu.h>
#include "util.h"

static int
diff --git a/src/url.c b/src/url.c
index dabf45f..47741e4 100644
--- a/src/url.c
+++ b/src/url.c
@@ -31,7 +31,7 @@
#include <string.h>
#include <strings.h>
#include "escape.h"
#include "url.h"
#include <gmni/url.h>

/* Provided by gmni */
static char *
diff --git a/src/util.c b/src/util.c
index 360c99a..0a479af 100644
--- a/src/util.c
+++ b/src/util.c
@@ -7,7 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "gmni.h"
#include <gmni/gmni.h>
#include "util.h"

static void
-- 
2.29.0
Thanks!

To git@git.sr.ht:~sircmpwn/gmni
   122fb0a..49c0c52  master -> master