cgmnlm

Unnamed repository; edit this file 'description' to name the repository.
git clone git://code.clttr.info/cgmnlm.git
Log | Files | Refs | README | LICENSE

commit 7c453fb45f831ce9178799af9855ecb0bda518ea
parent 95518992983e6531106b48c82edeb0ce825bf351
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 20 Sep 2020 16:41:05 -0400

Implement SENSITIVE INPUT response

Diffstat:
Msrc/client.c | 4++--
Msrc/gmni.c | 57++++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/src/client.c b/src/client.c @@ -175,7 +175,7 @@ gemini_request(const char *url, struct gemini_options *options, } char *endptr; - resp->status = (int)strtol(buf, &endptr, 10); + resp->status = (enum gemini_status)strtol(buf, &endptr, 10); if (*endptr != ' ' || resp->status < 10 || resp->status >= 70) { res = GEMINI_ERR_PROTOCOL; goto cleanup; @@ -268,5 +268,5 @@ cleanup: enum gemini_status_class gemini_response_class(enum gemini_status status) { - return status / 10; + return status / 10 * 10; } diff --git a/src/gmni.c b/src/gmni.c @@ -10,6 +10,7 @@ #include <string.h> #include <sys/socket.h> #include <sys/types.h> +#include <termios.h> #include <unistd.h> #include "gmni.h" @@ -21,6 +22,41 @@ usage(char *argv_0) argv_0); } +static char * +get_input(const struct gemini_response *resp, FILE *source) +{ + int r = 0; + struct termios attrs; + bool tty = fileno(source) != -1 && isatty(fileno(source)); + char *input = NULL; + if (tty) { + fprintf(stderr, "%s: ", resp->meta); + if (resp->status == GEMINI_STATUS_SENSITIVE_INPUT) { + r = tcgetattr(fileno(source), &attrs); + struct termios new_attrs; + r = tcgetattr(fileno(source), &new_attrs); + if (r != -1) { + new_attrs.c_lflag &= ~ECHO; + tcsetattr(fileno(source), TCSANOW, &new_attrs); + } + } + } + size_t s = 0; + ssize_t n = getline(&input, &s, source); + if (n == -1) { + fprintf(stderr, "Error reading input: %s\n", + feof(source) ? "EOF" : + strerror(ferror(source))); + return NULL; + } + input[n - 1] = '\0'; // Drop LF + if (tty && resp->status == GEMINI_STATUS_SENSITIVE_INPUT && r != -1) { + attrs.c_lflag &= ~ECHO; + tcsetattr(fileno(source), TCSANOW, &attrs); + } + return input; +} + int main(int argc, char *argv[]) { @@ -119,7 +155,6 @@ main(int argc, char *argv[]) goto next; } - char *new_url, *input = NULL; switch (gemini_response_class(resp.status)) { case GEMINI_STATUS_CLASS_INPUT: if (input_mode == INPUT_SUPPRESS) { @@ -127,27 +162,19 @@ main(int argc, char *argv[]) break; } - if (fileno(input_source) != -1 && - isatty(fileno(input_source))) { - fprintf(stderr, "%s: ", resp.meta); - } - - size_t s = 0; - ssize_t n = getline(&input, &s, input_source); - if (n == -1) { - fprintf(stderr, "Error reading input: %s\n", - feof(input_source) ? "EOF" : - strerror(ferror(input_source))); + char *input = get_input(&resp, input_source); + if (!input) { r = 1; exit = true; break; } - input[n - 1] = '\0'; // Drop LF - new_url = gemini_input_url(url, input); + char *new_url = gemini_input_url(url, input); + assert(new_url); + + free(input); free(url); url = new_url; - assert(url); goto next; case GEMINI_STATUS_CLASS_REDIRECT: free(url);