commit 7c453fb45f831ce9178799af9855ecb0bda518ea
parent 95518992983e6531106b48c82edeb0ce825bf351
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 20 Sep 2020 16:41:05 -0400
Implement SENSITIVE INPUT response
Diffstat:
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);