diff --git a/include/client.h b/include/gmni.h

rename from include/client.h

rename to include/gmni.h

index 671de12e7ee53fbbfc03407760723d2a66458c2d..42cfdac95530c9d6a5f4e6e6c3b85635908cc1e6 100644

--- a/include/client.h

+++ b/include/gmni.h

@@ -4,8 +4,49 @@ #include <netdb.h>

#include <openssl/ssl.h>

#include <sys/socket.h>

+enum gemini_result {

+ GEMINI_OK,

+ GEMINI_ERR_OOM,

+ GEMINI_ERR_INVALID_URL,

+ GEMINI_ERR_RESOLVE,

+ GEMINI_ERR_CONNECT,

+ GEMINI_ERR_SSL,

+ 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 {

- int status;

+ enum gemini_status status;

char *meta;

// Response body may be read from here if appropriate:

@@ -35,17 +76,6 @@ // example, to force IPv4/IPv6.

struct addrinfo *hints;

};

-enum gemini_result {

- GEMINI_OK,

- GEMINI_ERR_OOM,

- GEMINI_ERR_INVALID_URL,

- GEMINI_ERR_RESOLVE,

- GEMINI_ERR_CONNECT,

- GEMINI_ERR_SSL,

- GEMINI_ERR_IO,

- GEMINI_ERR_PROTOCOL,

-};

-

// Requests the specified URL via the gemini protocol. If options is non-NULL,

// it may specify some additional configuration to adjust client behavior.

//

@@ -67,5 +97,9 @@

// 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);

#endif

diff --git a/src/client.c b/src/client.c

index 59fa1381ab66496900acb4321f22c6ec3675db5e..86152d6183462636cca4eecbd47824569a688cb1 100644

--- a/src/client.c

+++ b/src/client.c

@@ -9,7 +9,7 @@ #include <string.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <unistd.h>

-#include "client.h"

+#include "gmni.h"

#include "url.h"

static enum gemini_result

@@ -264,3 +264,9 @@ cleanup:

curl_url_cleanup(uri);

return new_url;

}

+

+enum gemini_status_class

+gemini_response_class(enum gemini_status status)

+{

+ return status / 10;

+}

diff --git a/src/gmni.c b/src/gmni.c

index bdaa9baaca75e5f167add9a0ebed73cc60eaa647..b4efdc0235dac0279ce284f2c6b19f680a191647 100644

--- a/src/gmni.c

+++ b/src/gmni.c

@@ -11,7 +11,7 @@ #include <string.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <unistd.h>

-#include "client.h"

+#include "gmni.h"

static void

usage(char *argv_0)

@@ -120,8 +120,8 @@ goto next;

}

char *new_url, *input = NULL;

- switch (resp.status / 10) {

- case 1: // INPUT

+ switch (gemini_response_class(resp.status)) {

+ case GEMINI_STATUS_CLASS_INPUT:

if (input_mode == INPUT_SUPPRESS) {

exit = true;

break;

@@ -149,7 +149,7 @@ free(url);

url = new_url;

assert(url);

goto next;

- case 3: // REDIRECT

+ case GEMINI_STATUS_CLASS_REDIRECT:

free(url);

url = strdup(resp.meta);

if (!follow_redirects) {

@@ -160,10 +160,10 @@ }

exit = true;

}

goto next;

- case 6: // CLIENT CERTIFICATE REQUIRED

+ case GEMINI_STATUS_CLASS_CLIENT_CERTIFICATE_REQUIRED:

assert(0); // TODO

- case 4: // TEMPORARY FAILURE

- case 5: // PERMANENT FAILURE

+ case GEMINI_STATUS_CLASS_TEMPORARY_FAILURE:

+ case GEMINI_STATUS_CLASS_PERMANENT_FAILURE:

if (header_mode == OMIT_HEADERS) {

fprintf(stderr, "%s: %d %s\n",

resp.status / 10 == 4 ?

@@ -172,7 +172,7 @@ resp.status, resp.meta);

}

exit = true;

break;

- case 2: // SUCCESS

+ case GEMINI_STATUS_CLASS_SUCCESS:

exit = true;

break;

}