mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
utils: xtgettcap: new utility, to send XTGETTCAP queries
This commit is contained in:
parent
f359a8d6bc
commit
9937d92c85
3 changed files with 177 additions and 0 deletions
1
utils/meson.build
Normal file
1
utils/meson.build
Normal file
|
|
@ -0,0 +1 @@
|
|||
executable('xtgettcap', 'xtgettcap.c')
|
||||
175
utils/xtgettcap.c
Normal file
175
utils/xtgettcap.c
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
static struct termios orig_termios;
|
||||
|
||||
static void
|
||||
disable_raw_mode(void)
|
||||
{
|
||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0)
|
||||
exit(__LINE__);
|
||||
}
|
||||
|
||||
static void
|
||||
enable_raw_mode(void)
|
||||
{
|
||||
if (tcgetattr(STDIN_FILENO, &orig_termios) < 0)
|
||||
exit(__LINE__);
|
||||
|
||||
atexit(disable_raw_mode);
|
||||
|
||||
struct termios raw = orig_termios;
|
||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
raw.c_oflag &= ~(OPOST);
|
||||
raw.c_cflag |= (CS8);
|
||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||
raw.c_cc[VMIN] = 0;
|
||||
raw.c_cc[VTIME] = 1;
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0)
|
||||
exit(__LINE__);
|
||||
}
|
||||
|
||||
static const char *
|
||||
hexlify(const char *s)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
const size_t len = strlen(s);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
sprintf(&buf[i * 2], "%02x", s[i]);
|
||||
buf[len * 2 + 1] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static size_t
|
||||
unhexlify(char *dst, const char *src)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (const char *p = src; *p != '\0'; p += 2, dst++, count++)
|
||||
sscanf(p, "%02hhx", (unsigned char *)dst);
|
||||
|
||||
*dst = '\0';
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char *const *argv)
|
||||
{
|
||||
enable_raw_mode();
|
||||
|
||||
const size_t query_count = argc - 1;
|
||||
|
||||
printf("\x1bP+q");
|
||||
for (int i = 1; i < argc; i++)
|
||||
printf("%s%s", i > 1 ? ";" : "", hexlify(argv[i]));
|
||||
printf("\033\\");
|
||||
|
||||
fflush(NULL);
|
||||
|
||||
size_t replies = 0;
|
||||
while (replies < query_count) {
|
||||
struct pollfd fds[] = {{.fd = STDIN_FILENO, .events = POLLIN}};
|
||||
int r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
|
||||
if (r < 0)
|
||||
exit(__LINE__);
|
||||
|
||||
char buf[1024] = {0};
|
||||
ssize_t count = read(STDIN_FILENO, buf, sizeof(buf));
|
||||
|
||||
if (count < 0)
|
||||
exit(__LINE__);
|
||||
|
||||
if (count == 1 && buf[0] == 'q')
|
||||
break;
|
||||
|
||||
printf("reply: (%zd chars): ", count);
|
||||
|
||||
for (size_t i = 0; i < (size_t)count; i++) {
|
||||
if (isprint(buf[i]))
|
||||
printf("%c", buf[i]);
|
||||
else if (buf[i] == '\033')
|
||||
printf("\033[1;31m\\E\033[m");
|
||||
else
|
||||
printf("%02x", (uint8_t)buf[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
const char *p = buf;
|
||||
const char *end = buf + count;
|
||||
|
||||
while (p < end) {
|
||||
|
||||
const char *ST = strstr(p, "\033\\");
|
||||
if (ST == NULL)
|
||||
break;
|
||||
|
||||
if (count < 5 ||
|
||||
(strncmp(p, "\033P1+r", 5) != 00 &&
|
||||
strncmp(p, "\033P0+r", 5) != 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const bool success = p[2] == '1';
|
||||
|
||||
char decoded[1024];
|
||||
char copy[ST - &p[5] + 1];
|
||||
strncpy(copy, &p[5], ST - &p[5]);
|
||||
copy[ST - &p[5]] = '\0';
|
||||
|
||||
char *saveptr = NULL;
|
||||
for (char *key_value = strtok_r(copy, "; ", &saveptr);
|
||||
key_value != NULL;
|
||||
key_value = strtok_r(NULL, "; ", &saveptr))
|
||||
{
|
||||
// printf("key-value=%s\n", key_value);
|
||||
const char *key = strtok(key_value, "=");
|
||||
const char *value = strtok(NULL, "=");
|
||||
|
||||
#if 0
|
||||
assert((success && value != NULL) ||
|
||||
(!success && value == NULL));
|
||||
#endif
|
||||
|
||||
//printf("key=%s, value=%s\n", key, value);
|
||||
size_t len = unhexlify(decoded, key);
|
||||
|
||||
if (value != NULL) {
|
||||
decoded[len++] = '=';
|
||||
len += unhexlify(&decoded[len], value);
|
||||
}
|
||||
|
||||
const int color = success ? 39 : 31;
|
||||
|
||||
printf(" \033[%dm", color);
|
||||
for (size_t i = 0 ; i < len; i++) {
|
||||
if (isprint(decoded[i]))
|
||||
printf("%c", decoded[i]);
|
||||
else if (decoded[i] == '\033')
|
||||
printf("\033[1;31m\\E\033[22;%dm", color);
|
||||
else
|
||||
printf("\033[1m%02x\033[22m", (uint8_t)decoded[i]);
|
||||
}
|
||||
printf("\033[m\r\n");
|
||||
replies++;
|
||||
}
|
||||
|
||||
p = ST + 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue