.Dd Jun 20, 2020 .Dt LIBGEMINICLIENT 3 .Os .Sh NAME .Nm gemini_create , gemini_init , gemini_connect , .Nm gemini_connect_query , gemini_read , gemini_reset , gemini_fini , .Nm gemini_destroy .Sh SYNOPSIS .In libgeminiclient.h .Ft struct gemini * .Fn gemini_create void .Ft void .Fn gemini_init "struct gemini *ctx" .Ft void .Fn gemini_envinit "struct gemini *ctx" .Ft int .Fn gemini_connect "struct gemini *ctx" "const char *url" .Ft int .Fn gemini_connect_query "struct gemini *ctx" "const char *url" \ "const char *query" .Ft ssize_t .Fn gemini_read "struct gemini *ctx" "void *buffer" "size_t size" .Ft void .Fn gemini_reset "struct gemini *ctx" .Ft void .Fn gemini_fini "struct gemini *ctx" .Ft void .Fn gemini_destroy "struct gemini *ctx" .Sh DESCRIPTION .Fn gemini_create allocates a .Vt gemini structure and calls .Fn gemini_init on it. .Pp .Fn gemini_init Initializes the provided .Vt gemini structure. .Pp .Fn gemini_envinit Initializes the provided .Vt gemini structure, using the following environment variables, if they are provided: .Pp .Bl -tag -width Ds -compact .It Ev GEMINI_KEYFILE Initializes the .Fa keyfile field. .It Ev GEMINI_CERTFILE Initializes the .Fa certfile field. .It Ev GEMINI_TOFUFILE Initializes the .Fa tofufile field. .It Ev GEMINI_PROXY Initializes the .Fa proxy field. .It Ev GEMINI_MAX_REDIRECTS Initializes the .Fa maxredirects field. .It Ev GEMINI_PORT Initializes the .Fa port field. .El .Pp .Fn gemini_connect opens a connection to the provided .Fa url , and sets up the .Vt gemini structure for reading. .Pp .Fn gemini_connect_query calls .Fn gemini_connect with the escaped .Fa query appended to .Fa url separated by a question-mark. .Pp .Fn gemini_read attempts to read using the .Vt gemini structure previously set up by .Fn gemini_connect , sending the request and parsing the response as needed. After a successful return the .Fa meta , .Fa metalen , and .Fa status are set to that received by the response. .Fa meta will always be NUL terminated, but it may contain NUL characters itself. .Pp Categories of .Fa status values are as follows: .Bl -tag -width Ds -compact .It Li 1X Request for user-input. META contains the prompt. .It Li 2X Success. META contains the MIME-type. .It Li 3X Redirect. META contains the new URL. .It Li 4X Temporary failure. META contains the error string. .It Li 5X Permanent failure. META contains the error string. .It Li 6X Certificate required. META contains additional information. .El .Pp .Fn gemini_reset prepares the provided .Vt gemini structure to be reused for .Fn gemini_connect while keeping reusable data. This prevents user-configurable information from being reset, and prevents .Fa certfile , .Fa keyfile , and .Fa tofufile from being reopened. .Pp .Fn gemini_close Closes and reinitializes the provided .Vt gemini structure. .Pp .Fn gemini_destroy calls .Fn gemini_close on the provided .Vt gemini structure and frees it. .Pp The useful members of the .Vt gemini structure are as follows: .Bd -literal -offset indent -compact struct gemini { const char *certfile; /* Certificate file */ const char *keyfile; /* Key file */ const char *tofufile; /* Known-hosts file */ const char *proxy; /* Proxy host */ char *meta; /* Response META */ size_t metalen; /* Length of `meta' */ int flags; /* Configuration flags */ int maxredirects; /* Default 5 */ int socketfd; /* The socket to use */ short status; /* Response STATUS */ short port; /* Default port */ }; .Ed .Pp Possible .Fa flags are as follows: .Bl -tag -width Ds -compact .It Dv GEMINI_TOFU_WRITE Write any new certificate information to .Fa tofufile on .Dn gemini_close . .El .Pp All knows .Fa status values are as follows: .Bl -tag -width Ds .It Li 10 The server requested user-input. META contains the suggested prompt to show the user. .It Li 20 The request was successful, and the requested data will follow the response. META contains the MIME-type of the data. .It Li 21 The request was successful, the requested data will follow the response, and the user-defined certificate can retired. META contains the MIME-type of the data. .It Li 30 The requested resource currently exists at a different location. META contains the new URL. .It Li 31 The requested resource can be assumed to exist at a different location. META contains the new URL. .It Li 40 The request failed in a temporary manner. META may contain additional information. .It Li 41 The server is currently unavailable. META may contain additional information. .It Li 42 There was a CGI error. META may contain additional information. .It Li 43 The requested host does not match the server, and the proxied request failed. the request. META may contain additional information. .It Li 44 The request was rejected due to rate-limiting. META contains an estimated amount of seconds before a retry may be successful. .It Li 50 The request failed in a permanent manner. META may contain additional information. .It Li 51 The requested resource was not found by the server. META may contain additional information. .It Li 52 The requested resource no longer exists at that URL. META may contain additional information. .It Li 53 The requested host does not match the server, and it refused to proxy the request. META may contain additional information. .It Li 59 The server says that the client's request was invalid. META may contain additional information. .It Li 60 An user-defined certificate is required. META may contain additional information. .It Li 61 A transient user-defined certificate is required. META may contain additional information. .It Li 62 An authorized user-defined certificate is required. META may contain additional information. .It Li 63 The user-defined certificate was rejected because was not considered valid by the server. META may contain additional information. .It Li 64 The user-defined certificate was rejected because it is not yet valid. META may contain additional information. .It Li 65 The user-defined certificate was rejected because it is expired. META may contain additional information. .El .Sh RETURN VALUES .Fn gemini_create returns a pointer to a newly initialized .Vt gemini structure, or a NULL on a failure. .Pp .Fn gemini_connect and .Fn gemini_connect_query returns a 0 on success and a -1 on an error. They can also return .Dv TLS_WANT_POLLIN and .Dv TLS_WANT_POLLOUT if .Fa socketfd is set to a non-blocking file-descriptor, even if they do it is safe to call .Fn gemini_read at this point. .Pp .Fn gemini_read returns a -1 on an error, otherwise it returns the amount of data read into the buffer, with 0 only being returned when there is nothing left to read after successfully reading the response header. It can also return .Dv TLS_WANT_POLLIN and .Dv TLS_WANT_POLLOUT if .Fa socketfd is set to a non-blocking file-descriptor. .Sh EXAMPLES The following example shows how you initialize various values: .Bd -literal -offset indent -compact gemini = gemini_create(); gemini->keyfile = keyfile; gemini->certfile = certfile; gemini->tofufile = tofufile; gemini->flags |= GEMINI_TOFU_WRITE; gemini->port = port; while ((url = get_url()) != NULL) if (gemini_connect(gemini) != 0) continue; ... gemini_reset(gemini); } gemini_destroy(gemini); .Ed .Pp The following example shows how to handle redirects and other status codes yourself: .Bd -literal -offset indent -compact gemini->maxredirects = 0; while ((url = get_url()) != NULL) { if (gemini_connect(gemini, url) != 0) { warn("Could not open: %s", url); continue; } while ((r = gemini_read(gemini, buf, bufsize)) > 0) { ... } if (r < 0) { warn("Error while reading"); gemini_reset(gemini); continue; } switch (gemini->status / 10) { ... case 3: if (yesno("Redirected to \\"%s\\" [Y/n]?", gemini->meta)) prepend_url(gemini->meta); break; ... default: warn("Bad status %02hd: %s", gemini->status, gemini->meta); break; } gemini_reset(gemini); } .Ed .Sh SEE ALSO .Xr tls_read 3