diff options
author | Vladimír Čunát <vladimir.cunat@nic.cz> | 2023-06-13 09:09:51 +0200 |
---|---|---|
committer | Vladimír Čunát <vladimir.cunat@nic.cz> | 2023-06-28 09:32:14 +0200 |
commit | 2db9970ae0b3f8e21de79d12cd0fc42f80de09e4 (patch) | |
tree | d37d0d5c35f090542c0a95f65659ed7630998e03 /utils | |
parent | Merge !1417: distro/pkg/deb: make manager package arch specific (diff) | |
download | knot-resolver-2db9970ae0b3f8e21de79d12cd0fc42f80de09e4.tar.xz knot-resolver-2db9970ae0b3f8e21de79d12cd0fc42f80de09e4.zip |
kresc: remove this client
It's never gone beyond experiment/alpha and now we have kresctl
which should be much better. Keeping installed bin/kresc could
confuse users.
Diffstat (limited to 'utils')
-rw-r--r-- | utils/client/kresc.c | 458 | ||||
-rw-r--r-- | utils/client/meson.build | 37 | ||||
-rw-r--r-- | utils/meson.build | 1 |
3 files changed, 0 insertions, 496 deletions
diff --git a/utils/client/kresc.c b/utils/client/kresc.c deleted file mode 100644 index 16782a13..00000000 --- a/utils/client/kresc.c +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) CZ.NIC, z.s.p.o. <knot-resolver@labs.nic.cz> - * SPDX-License-Identifier: GPL-3.0-or-later - */ -#include <arpa/inet.h> -#include <contrib/ccan/asprintf/asprintf.h> -#include <editline/readline.h> -#include <errno.h> -#include <histedit.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/un.h> -#include <unistd.h> - -#define HISTORY_FILE "kresc_history" -#define PROGRAM_NAME "kresc" - -FILE *g_tty = NULL; //!< connection to the daemon - -static char *run_cmd(const char *cmd, size_t * out_len); - -const char *prompt(EditLine * e) -{ - return PROGRAM_NAME "> "; -} - -bool starts_with(const char *a, const char *b) -{ - if (strncmp(a, b, strlen(b)) == 0) - return 1; - return 0; -} - -//! Returns Lua name of type of value, NULL on error. Puts length of type in name_len; -char *get_type_name(const char *value) -{ - if (value == NULL) { - return NULL; - } - - for (int i = 0; value[i]; i++) { - if (value[i] == ')') { - //Return NULL to prevent unexpected function call - return NULL; - } - } - - char *cmd = afmt("type(%s)", value); - if (!cmd) { - perror("While tab-completing."); - return NULL; - } - - size_t name_len; - char *type = run_cmd(cmd, &name_len); - if (!type) { - return NULL; - } - free(cmd); - - if (starts_with(type, "[")) { - //Return "nil" on non-valid name. - free(type); - return strdup("nil"); - } else { - type[strlen(type) - 1] = '\0'; - return type; - } -} - -static void complete_function(EditLine * el) -{ - //Add left parenthesis to function name. - el_insertstr(el, "("); -} - -static void complete_members(EditLine * el, const char *str, - const char *str_type, int str_len, char *dot) -{ - char *table = strdup(str); - if (!table) { - perror("While tab-completing"); - return; - } - //Get only the table name (without partial member name). - if (dot) { - *(table + (dot - str)) = '\0'; - } - //Insert a dot after the table name. - if (!strncmp(str_type, "table", 5)) { - el_insertstr(el, "."); - str_len++; - } - //Check if the substring before dot is a valid table name. - const char *t_type = get_type_name(table); - if (t_type && !strncmp("table", t_type, 5)) { - //Get string of members of the table. - char *cmd = - afmt - ("do local s=\"\"; for i in pairs(%s) do s=s..i..\"\\n\" end return(s) end", - table); - if (!cmd) { - perror("While tab-completing."); - goto complete_members_exit; - } - size_t members_len; - char *members = run_cmd(cmd, &members_len); - free(cmd); - if (!members) { - perror("While communication with daemon"); - goto complete_members_exit; - } - //Split members by newline. - char *members_tok = strdup(members); - free(members); - if (!members_tok) { - goto complete_members_exit; - } - char *token = strtok(members_tok, "\n"); - int matches = 0; - char *lastmatch = NULL; - if (!dot || dot - str + 1 == strlen(str)) { - //Prints all members. - while (token) { - char *member = afmt("%s.%s", table, token); - const char *member_type = get_type_name(member); - if (member && member_type) { - printf("\n%s (%s)", member, member_type); - free(member); - free((void *)member_type); - } else if (member) { - printf("\n%s", member); - free(member); - } - token = strtok(NULL, "\n"); - matches++; - } - } else { - //Print members matching the current line. - while (token) { - if (starts_with(token, dot + 1)) { - const char *member_type = - get_type_name(afmt - ("%s.%s", table, - token)); - if (member_type) { - printf("\n%s.%s (%s)", table, - token, member_type); - free((void *)member_type); - } else { - printf("\n%s.%s", table, token); - } - lastmatch = token; - matches++; - } - token = strtok(NULL, "\n"); - } - - //Complete matching member. - if (matches == 1) { - el_deletestr(el, str_len); - el_insertstr(el, table); - el_insertstr(el, "."); - el_insertstr(el, lastmatch); - } - } - if (matches > 1) { - printf("\n"); - } - free(members_tok); - } - -complete_members_exit: - free(table); - if(t_type) { - free((void*)t_type); - } -} - -static void complete_globals(EditLine * el, const char *str, int str_len) -{ - //Parse Lua globals. - size_t globals_len; - char *globals = run_cmd("_G.__orig_name_list", &globals_len); - if (!globals) { - perror("While tab-completing"); - return; - } - //Show possible globals. - char *globals_tok = strdup(globals); - free(globals); - if (!globals_tok) { - return; - } - char *token = strtok(globals_tok, "\n"); - int matches = 0; - char *lastmatch = NULL; - while (token) { - if (str && starts_with(token, str)) { - char *name = get_type_name(token); - printf("\n%s (%s)", token, name); - free(name); - lastmatch = token; - matches++; - } - token = strtok(NULL, "\n"); - } - if (matches > 1) { - printf("\n"); - } - //Complete matching global. - if (matches == 1) { - el_deletestr(el, str_len); - el_insertstr(el, lastmatch); - } - free(globals_tok); -} - -static unsigned char complete(EditLine * el, int ch) -{ - int argc, pos; - const char **argv; - const LineInfo *li = el_line(el); - Tokenizer *tok = tok_init(NULL); - - //Tokenize current line. - int ret = tok_line(tok, li, &argc, &argv, NULL, &pos); - - if (ret != 0) { - perror("While tab-completing."); - goto complete_exit; - } - //Show help. - if (argc == 0) { - size_t help_len; - char *help = run_cmd("help()", &help_len); - if (help) { - printf("\n%s", help); - free(help); - } else { - perror("While communication with daemon"); - } - goto complete_exit; - } - - if (argc > 1) { - goto complete_exit; - } - //Get name of type of current line. - const char *type = get_type_name(argv[0]); - - if (!type) { - goto complete_exit; - } - //Get position of last dot in current line (useful for parsing table). - char *dot = strrchr(argv[0], '.'); - - if (strncmp(type, "table", 5) != 0 && !dot) { - //Line is not a name of some table and there is no dot in it. - complete_globals(el, argv[0], pos); - } else if ((dot && strncmp(type, "nil", 3) == 0) - || strncmp(type, "table", 5) == 0) { - //Current line (or part of it) is a name of some table. - complete_members(el, argv[0], type, pos, dot); - } else if (strncmp(type, "function", 8) == 0) { - //Current line is a function. - complete_function(el); - } - if (type) { - free((void *)type); - } - -complete_exit: - tok_reset(tok); - tok_end(tok); - return CC_REDISPLAY; -} - -//! Initialize connection to the daemon; return 0 on success. -static int init_tty(const char *path) -{ - int fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) - return 1; - - struct sockaddr_un addr; - addr.sun_family = AF_UNIX; - size_t plen = strlen(path); - if (plen + 1 > sizeof(addr.sun_path)) { - fprintf(stderr, "Path too long\n"); - close(fd); - return 1; - } - memcpy(addr.sun_path, path, plen + 1); - if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr))) { - perror("While connecting to daemon"); - close(fd); - return 1; - } - g_tty = fdopen(fd, "r+"); - if (!g_tty) { - perror("While opening TTY"); - close(fd); - return 1; - } - - // Switch to binary mode and consume the text "> ". - if (fprintf(g_tty, "__binary\n") < 0 || !fread(&addr, 2, 1, g_tty) - || fflush(g_tty)) { - perror("While initializing TTY"); - fclose(g_tty); - g_tty = NULL; - return 1; - } - - return 0; -} - -//! Run a command on the daemon; return the answer or NULL on failure, puts answer length to out_len. -static char *run_cmd(const char *cmd, size_t * out_len) -{ - if (!g_tty || !cmd) - return NULL; - if (fprintf(g_tty, "%s", cmd) < 0 || fflush(g_tty)) - return NULL; - uint32_t len; - if (!fread(&len, sizeof(len), 1, g_tty)) - return NULL; - len = ntohl(len); - if (!len) - return NULL; - char *msg = malloc(1 + (size_t) len); - if (!msg) - return NULL; - if (len && !fread(msg, len, 1, g_tty)) { - free(msg); - return NULL; - } - msg[len] = '\0'; - *out_len = len; - return msg; -} - -static int interact() -{ - EditLine *el; - History *hist; - int count; - const char *line; - HistEvent ev; - el = el_init(PROGRAM_NAME, stdin, stdout, stderr); - el_set(el, EL_PROMPT, prompt); - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_ADDFN, PROGRAM_NAME "-complete", - "Perform " PROGRAM_NAME " completion.", complete); - el_set(el, EL_BIND, "^I", PROGRAM_NAME "-complete", NULL); - - hist = history_init(); - if (hist == 0) { - perror("While initializing command history"); - return 1; - } - history(hist, &ev, H_SETSIZE, 800); - el_set(el, EL_HIST, history, hist); - - char *hist_file = NULL; - - char *data_home = getenv("XDG_DATA_HOME"); - - //Check whether $XDG_DATA_HOME is set. - if (!data_home || *data_home == '\0') { - const char *home = getenv("HOME"); //This should be set on any POSIX compliant OS, even for nobody - - //Create necessary folders. - char *dirs[3] = - { afmt("%s/.local", home), afmt("%s/.local/share", home), - afmt("%s/.local/share/knot-resolver/", home) - }; - bool ok = true; - for (int i = 0; i < 3; i++) { - if (mkdir(dirs[i], 0755) && errno != EEXIST) { - ok = false; - break; - } - } - if (ok) { - hist_file = - afmt("%s/.local/share/knot-resolver/" HISTORY_FILE, home); - } - } else { - if (!mkdir(afmt("%s/knot-resolver/", data_home), 0755) - || errno == EEXIST) { - hist_file = afmt("%s/knot-resolver/" HISTORY_FILE, data_home); - } - } - - //Load history file - if (hist_file) { - history(hist, &ev, H_LOAD, hist_file); - } else { - perror("While opening history file"); - } - - while (1) { - line = el_gets(el, &count); - if (count > 0) { - history(hist, &ev, H_ENTER, line); - size_t msg_len; - char *msg = run_cmd(line, &msg_len); - if (!msg) { - perror("While communication with daemon"); - history_end(hist); - el_end(el); - free(msg); - return 1; - } - printf("%s", msg); - if (msg_len > 0 && msg[msg_len - 1] != '\n') { - printf("\n"); - } - if (hist_file) { - history(hist, &ev, H_SAVE, hist_file); - } - free(msg); - } - } - history_end(hist); - free(hist_file); - el_end(el); - if (feof(stdin)) - return 0; - perror("While reading input"); - return 1; -} - -int main(int argc, char **argv) -{ - fprintf(stderr, "Warning! %s is highly experimental, use at own risk.\n", argv[0]); - fprintf(stderr, "Please tell authors what features you expect from client utility.\n"); - if (argc != 2) { - fprintf(stderr, "Usage: %s tty/xxxxx\n", argv[0]); - return 1; - } - - int res = init_tty(argv[1]); - - if (!res) - res = interact(); - - if (g_tty) - fclose(g_tty); - return res; -} diff --git a/utils/client/meson.build b/utils/client/meson.build deleted file mode 100644 index 761c2cdd..00000000 --- a/utils/client/meson.build +++ /dev/null @@ -1,37 +0,0 @@ -# client -# SPDX-License-Identifier: GPL-3.0-or-later - -kresc_src = files([ - 'kresc.c', -]) -c_src_lint += kresc_src - -build_client = false -if get_option('client') != 'disabled' - message('--- client dependencies ---') - libedit = dependency('libedit', required: false) - if libedit.found() - build_client = true - else # darwin workaround: missing pkgconfig - libedit = meson.get_compiler('c').find_library( - 'edit', required: get_option('client') == 'enabled') - if libedit.found() - build_client = true - endif - endif - message('---------------------------') -endif - - -if build_client - kresc = executable( - 'kresc', - kresc_src, - dependencies: [ - contrib_dep, - libedit, - ], - install: true, - install_dir: get_option('sbindir'), - ) -endif diff --git a/utils/meson.build b/utils/meson.build index 931ef3c5..8bab5f2d 100644 --- a/utils/meson.build +++ b/utils/meson.build @@ -3,5 +3,4 @@ build_utils = get_option('utils') != 'disabled' -subdir('client') subdir('cache_gc') |