[PATCH] Client: add "show hostname" command, and add client prompt hostname display
Molly Miller
bird at m-squa.red
Thu Feb 11 22:14:23 CET 2021
Hi all,
The recent patch on the list from Vincent Bernat which added support for the
draft BGP hostname capability [1] reminded me of a thread from last year, in
which there was a feature request for the ability to display the system
hostname in the Bird client prompt [2].
This feature doesn't appear to have been implemented since then, and now
that a hostname is tracked internally by Bird, I've written a
proof-of-concept patch (appended inline) which displays the daemon hostname
in the client prompt.
This patch adds a "show hostname" command to the daemon for convenience, and
modifies the client to automatically issue this command when starting in
interactive mode. The client then intercepts the response (which will either
contain the daemon hostname, or be a syntax error if the daemon does not
understand the command), and then sets the received hostname in the prompt
if the response is a success code.
(The rationale for not simply calling uname(2) in the client is that the
resulting nodename may not match the hostname configured in the daemon, in
the case where the daemon configuration contains a hostname "<foo>"
directive. It's also possible to connect to the daemon over a Unix socket
forwarded over SSH, in which case the client would be running on a separate
system with a different hostname regardless of the daemon configuration --
thanks to Tim Stallard for pointing this out.)
I don't know how willing the Bird maintainers would be to commit this patch,
however I thought I'd post it to the list in case anyone else is interested.
Cheers,
--mm.
[1]: https://bird.network.cz/pipermail/bird-users/2021-February/015187.html,
merged as 71423871
[2]: https://bird.network.cz/pipermail/bird-users/2020-July/014678.html
-- >8 --
Subject: [PATCH] Client: add "show hostname" command, and client prompt
hostname display.
This patch adds a "show hostname" command to the daemon, which returns the
server's currently configured hostname, and extends the command line client
to issue this command upon connecting to the daemon, in order to retrieve a
hostname to display in the client's prompt. A '-p' option has also been added
to suppress this behaviour.
molly on flywheel ~> birdc
BIRD v2.0.7 ready.
bird (flywheel)> show hostname
Hostname: flywheel
bird (flywheel)> exit
molly on flywheel ~> birdc -p
BIRD v2.0.7 ready.
bird> show hostname
Hostname: flywheel
bird> quit
Additionally, the error message generated by older versions of the daemon when
running the "show hostname" command is caught, in order to remain interoperable
with versions which do not have this patch.
The client program does not, however, have any means of detecting whether the
hostname changes as part of an online configuration update, so changes in the
daemon's hostname will not be propagated to a client which is persistent across
the configuration change.
---
client/birdc.c | 11 +++++++++--
client/birdcl.c | 8 +++++++-
client/client.c | 48 ++++++++++++++++++++++++++++++++++++++++++------
client/client.h | 2 ++
doc/reply_codes | 1 +
nest/cmds.c | 7 +++++++
nest/cmds.h | 1 +
nest/config.Y | 3 +++
8 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/client/birdc.c b/client/birdc.c
index f1aea2fe..b1b9b218 100644
--- a/client/birdc.c
+++ b/client/birdc.c
@@ -162,7 +162,7 @@ input_init(void)
rl_readline_name = "birdc";
rl_add_defun("bird-complete", input_complete, '\t');
rl_add_defun("bird-help", input_help, '?');
- rl_callback_handler_install("bird> ", input_got_line);
+ rl_callback_handler_install(prompt_string, input_got_line);
// rl_get_screen_size();
term_lns = LINES;
@@ -184,7 +184,7 @@ input_reveal(void)
tcdrain(STDOUT_FILENO);
rl_end = input_hidden_end;
- rl_expand_prompt("bird> ");
+ rl_expand_prompt(prompt_string);
rl_forced_update_display();
prompt_active = 1;
@@ -201,6 +201,13 @@ input_hide(void)
prompt_active = 0;
}
+void
+input_reload(void)
+{
+ input_hide();
+ input_reveal();
+}
+
void
input_notify(int prompt)
{
diff --git a/client/birdcl.c b/client/birdcl.c
index 4508185c..d36914c9 100644
--- a/client/birdcl.c
+++ b/client/birdcl.c
@@ -38,6 +38,12 @@ input_stop_list(void)
/* Empty in non-ncurses version. */
}
+void
+input_reload(void)
+{
+ /* Empty in non-ncurses version. */
+}
+
void
input_notify(int prompt)
{
@@ -45,7 +51,7 @@ input_notify(int prompt)
if (!prompt)
return;
- printf("bird> ");
+ printf(prompt_string);
fflush(stdout);
}
diff --git a/client/client.c b/client/client.c
index 97cf6639..0de7aaaf 100644
--- a/client/client.c
+++ b/client/client.c
@@ -37,8 +37,11 @@
#include "sysdep/unix/unix.h"
#define SERVER_READ_BUF_LEN 4096
+#define SERVER_PROMPT_LEN 64
+#define SERVER_PROMPT_DEFAULT "bird> "
+#define SERVER_HOSTNAME_PREFIX "Hostname: "
-static char *opt_list = "s:vrl";
+static char *opt_list = "s:vrlp";
static int verbose, restricted, once;
static char *init_cmd;
@@ -47,12 +50,15 @@ static int server_fd;
static byte server_read_buf[SERVER_READ_BUF_LEN];
static byte *server_read_pos = server_read_buf;
-int init = 1; /* During intial sequence */
-int busy = 1; /* Executing BIRD command */
-int interactive; /* Whether stdin is terminal */
+int init = 1; /* During intial sequence */
+int busy = 1; /* Executing BIRD command */
+int hostprompt = 1; /* Whether to show hostname in prompt */
+int interactive; /* Whether stdin is terminal */
+char prompt_string[SERVER_PROMPT_LEN]; /* Prompt string */
static int num_lines, skip_input;
int term_lns, term_cls;
+static int hostname_read = 0;
/*** Parsing of arguments ***/
@@ -60,7 +66,7 @@ int term_lns, term_cls;
static void
usage(char *name)
{
- fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l]\n", name);
+ fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l] [-p]\n", name);
exit(1);
}
@@ -87,6 +93,9 @@ parse_args(int argc, char **argv)
if (!server_changed)
server_path = xbasename(server_path);
break;
+ case 'p':
+ hostprompt = 0;
+ break;
default:
usage(argv[0]);
}
@@ -199,6 +208,12 @@ init_commands(void)
exit(0);
}
+ /* Set up local prompt, and attempt to retrieve daemon hostname */
+ memset(prompt_string, 0, sizeof(prompt_string));
+ strcpy(prompt_string, SERVER_PROMPT_DEFAULT);
+ if (hostprompt)
+ submit_server_command("show hostname");
+
input_init();
term_lns = (term_lns > 0) ? term_lns : 25;
@@ -239,6 +254,16 @@ more(void)
more_end();
}
+static void
+update_prompt(char *x)
+{
+ if (strncmp(x, SERVER_HOSTNAME_PREFIX, sizeof(SERVER_HOSTNAME_PREFIX)-1) != 0)
+ return;
+
+ memset(prompt_string, 0, sizeof(prompt_string));
+ snprintf(prompt_string, sizeof(prompt_string), "bird (%s)> ", x+sizeof(SERVER_HOSTNAME_PREFIX)-1);
+}
+
/*** Communication with server ***/
@@ -281,7 +306,18 @@ server_got_reply(char *x)
(x[4] == ' ' || x[4] == '-'))
{
if (code)
- PRINTF(len, "%s\n", verbose ? x : x+5);
+ {
+ if ((code == 1026 || code == 9001) && !hostname_read && hostprompt)
+ {
+ hostname_read = 1;
+ if (code == 1026) {
+ update_prompt(x+5);
+ input_reload();
+ }
+ }
+ else
+ PRINTF(len, "%s\n", verbose ? x : x+5);
+ }
if (x[4] == ' ')
{
diff --git a/client/client.h b/client/client.h
index f9693def..8de7b38c 100644
--- a/client/client.h
+++ b/client/client.h
@@ -9,6 +9,7 @@
extern int init, busy, interactive;
extern int term_lns, term_cls;
+extern char prompt_string[];
/* birdc.c / birdcl.c */
@@ -16,6 +17,7 @@ void input_start_list(void);
void input_stop_list(void);
void input_init(void);
+void input_reload(void);
void input_notify(int prompt);
void input_read(void);
diff --git a/doc/reply_codes b/doc/reply_codes
index 02f4e656..47f9d3e8 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -61,6 +61,7 @@ Reply codes of BIRD command-line interface
1023 Show Babel interfaces
1024 Show Babel neighbors
1025 Show Babel entries
+1026 Show hostname
8000 Reply too long
8001 Route not found
diff --git a/nest/cmds.c b/nest/cmds.c
index 18f39eb5..a412faf3 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -95,6 +95,13 @@ cmd_show_memory(void)
cli_msg(0, "");
}
+void
+cmd_show_hostname(void)
+{
+ cli_msg(-1026, "Hostname: %s", config->hostname);
+ cli_msg(0, "");
+}
+
void
cmd_eval(const struct f_line *expr)
{
diff --git a/nest/cmds.h b/nest/cmds.h
index 194a9d7f..14c7293d 100644
--- a/nest/cmds.h
+++ b/nest/cmds.h
@@ -16,6 +16,7 @@ struct f_inst;
void cmd_show_status(void);
void cmd_show_symbols(struct sym_show_data *sym);
void cmd_show_memory(void);
+void cmd_show_hostname(void);
struct f_line;
void cmd_eval(const struct f_line *expr);
diff --git a/nest/config.Y b/nest/config.Y
index 39bf6149..72ea0726 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -564,6 +564,9 @@ CF_CLI(SHOW STATUS,,, [[Show router status]])
CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
{ cmd_show_memory(); } ;
+CF_CLI(SHOW HOSTNAME,,, [[Show current hostname]])
+{ cmd_show_hostname(); } ;
+
CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
--
2.20.1
More information about the Bird-users
mailing list