Implements 'more' feature to birdc.
Also does some code restructuring.
This commit is contained in:
parent
6baef17ecf
commit
f0333f44a5
1 changed files with 105 additions and 46 deletions
139
client/client.c
139
client/client.c
|
@ -17,6 +17,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <curses.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
@ -29,13 +30,19 @@ static int verbose;
|
||||||
|
|
||||||
static char *server_path = PATH_CONTROL_SOCKET;
|
static char *server_path = PATH_CONTROL_SOCKET;
|
||||||
static int server_fd;
|
static int server_fd;
|
||||||
static int server_reply;
|
|
||||||
static byte server_read_buf[4096];
|
static byte server_read_buf[4096];
|
||||||
static byte *server_read_pos = server_read_buf;
|
static byte *server_read_pos = server_read_buf;
|
||||||
|
|
||||||
|
#define STATE_PROMPT 0
|
||||||
|
#define STATE_CMD_SERVER 1
|
||||||
|
#define STATE_CMD_USER 2
|
||||||
|
|
||||||
static int input_initialized;
|
static int input_initialized;
|
||||||
static int input_hidden;
|
|
||||||
static int input_hidden_end;
|
static int input_hidden_end;
|
||||||
|
static int cstate = STATE_CMD_SERVER;
|
||||||
|
static int nstate = STATE_CMD_SERVER;
|
||||||
|
|
||||||
|
static int num_lines, skip_input, interactive;
|
||||||
|
|
||||||
/*** Parsing of arguments ***/
|
/*** Parsing of arguments ***/
|
||||||
|
|
||||||
|
@ -70,7 +77,6 @@ parse_args(int argc, char **argv)
|
||||||
/*** Input ***/
|
/*** Input ***/
|
||||||
|
|
||||||
static void server_send(char *);
|
static void server_send(char *);
|
||||||
static void select_loop(int);
|
|
||||||
|
|
||||||
/* HACK: libreadline internals we need to access */
|
/* HACK: libreadline internals we need to access */
|
||||||
extern int _rl_vis_botlin;
|
extern int _rl_vis_botlin;
|
||||||
|
@ -93,6 +99,15 @@ handle_internal_command(char *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
submit_server_command(char *cmd)
|
||||||
|
{
|
||||||
|
server_send(cmd);
|
||||||
|
nstate = STATE_CMD_SERVER;
|
||||||
|
num_lines = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
got_line(char *cmd_buffer)
|
got_line(char *cmd_buffer)
|
||||||
{
|
{
|
||||||
|
@ -109,13 +124,10 @@ got_line(char *cmd_buffer)
|
||||||
if (cmd)
|
if (cmd)
|
||||||
{
|
{
|
||||||
add_history(cmd);
|
add_history(cmd);
|
||||||
|
|
||||||
if (!handle_internal_command(cmd))
|
if (!handle_internal_command(cmd))
|
||||||
{
|
submit_server_command(cmd);
|
||||||
server_send(cmd);
|
|
||||||
input_hidden = -1;
|
|
||||||
select_loop(0);
|
|
||||||
input_hidden = 0;
|
|
||||||
}
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -218,28 +230,24 @@ input_init(void)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_hide(void)
|
input_hide(void)
|
||||||
{
|
|
||||||
if (input_hidden)
|
|
||||||
return;
|
|
||||||
if (rl_line_buffer)
|
|
||||||
{
|
{
|
||||||
input_hidden_end = rl_end;
|
input_hidden_end = rl_end;
|
||||||
rl_end = 0;
|
rl_end = 0;
|
||||||
rl_expand_prompt("");
|
rl_expand_prompt("");
|
||||||
rl_redisplay();
|
rl_redisplay();
|
||||||
input_hidden = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_reveal(void)
|
input_reveal(void)
|
||||||
{
|
{
|
||||||
if (input_hidden <= 0)
|
/* need this, otherwise some lib seems to eat pending output when
|
||||||
return;
|
the prompt is displayed */
|
||||||
|
fflush(stdout);
|
||||||
|
tcdrain(fileno(stdout));
|
||||||
|
|
||||||
rl_end = input_hidden_end;
|
rl_end = input_hidden_end;
|
||||||
rl_expand_prompt("bird> ");
|
rl_expand_prompt("bird> ");
|
||||||
rl_forced_update_display();
|
rl_forced_update_display();
|
||||||
input_hidden = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -253,6 +261,51 @@ cleanup(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
update_state(void)
|
||||||
|
{
|
||||||
|
if (nstate == cstate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (nstate == STATE_PROMPT)
|
||||||
|
if (input_initialized)
|
||||||
|
input_reveal();
|
||||||
|
else
|
||||||
|
input_init();
|
||||||
|
|
||||||
|
if (nstate != STATE_PROMPT)
|
||||||
|
input_hide();
|
||||||
|
|
||||||
|
cstate = nstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
more(void)
|
||||||
|
{
|
||||||
|
printf("--More--\015");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
redo:
|
||||||
|
switch (getchar())
|
||||||
|
{
|
||||||
|
case 32:
|
||||||
|
num_lines = 2;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
num_lines--;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
skip_input = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto redo;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" \015");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** Communication with server ***/
|
/*** Communication with server ***/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -281,26 +334,32 @@ server_got_reply(char *x)
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
|
|
||||||
input_hide();
|
|
||||||
if (*x == '+') /* Async reply */
|
if (*x == '+') /* Async reply */
|
||||||
printf(">>> %s\n", x+1);
|
skip_input || printf(">>> %s\n", x+1);
|
||||||
else if (x[0] == ' ') /* Continuation */
|
else if (x[0] == ' ') /* Continuation */
|
||||||
printf("%s%s\n", verbose ? " " : "", x+1);
|
skip_input || printf("%s%s\n", verbose ? " " : "", x+1);
|
||||||
else if (strlen(x) > 4 &&
|
else if (strlen(x) > 4 &&
|
||||||
sscanf(x, "%d", &code) == 1 && code >= 0 && code < 10000 &&
|
sscanf(x, "%d", &code) == 1 && code >= 0 && code < 10000 &&
|
||||||
(x[4] == ' ' || x[4] == '-'))
|
(x[4] == ' ' || x[4] == '-'))
|
||||||
{
|
{
|
||||||
if (code)
|
if (code)
|
||||||
printf("%s\n", verbose ? x : x+5);
|
skip_input || printf("%s\n", verbose ? x : x+5);
|
||||||
if (x[4] == ' ')
|
if (x[4] == ' ')
|
||||||
server_reply = code;
|
{
|
||||||
|
nstate = STATE_PROMPT;
|
||||||
|
skip_input = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("??? <%s>\n", x);
|
skip_input || printf("??? <%s>\n", x);
|
||||||
/* need this, otherwise some lib seems to eat pending output when
|
|
||||||
the prompt is displayed */
|
if (skip_input)
|
||||||
fflush(stdout);
|
return;
|
||||||
tcdrain(fileno(stdout));
|
|
||||||
|
num_lines++;
|
||||||
|
if (interactive && input_initialized && (num_lines >= LINES) && (cstate == STATE_CMD_SERVER))
|
||||||
|
more();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -347,15 +406,16 @@ server_read(void)
|
||||||
static fd_set select_fds;
|
static fd_set select_fds;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
select_loop(int mode)
|
select_loop(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
server_reply = -1;
|
while (1)
|
||||||
while (mode || server_reply < 0)
|
|
||||||
{
|
{
|
||||||
FD_ZERO(&select_fds);
|
FD_ZERO(&select_fds);
|
||||||
|
|
||||||
|
if (cstate != STATE_CMD_USER)
|
||||||
FD_SET(server_fd, &select_fds);
|
FD_SET(server_fd, &select_fds);
|
||||||
if (mode)
|
if (cstate != STATE_CMD_SERVER)
|
||||||
FD_SET(0, &select_fds);
|
FD_SET(0, &select_fds);
|
||||||
|
|
||||||
rv = select(server_fd+1, &select_fds, NULL, NULL, NULL);
|
rv = select(server_fd+1, &select_fds, NULL, NULL, NULL);
|
||||||
|
@ -370,13 +430,15 @@ select_loop(int mode)
|
||||||
if (FD_ISSET(server_fd, &select_fds))
|
if (FD_ISSET(server_fd, &select_fds))
|
||||||
{
|
{
|
||||||
server_read();
|
server_read();
|
||||||
if (mode)
|
update_state();
|
||||||
input_reveal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(0, &select_fds))
|
if (FD_ISSET(0, &select_fds))
|
||||||
|
{
|
||||||
rl_callback_read_char();
|
rl_callback_read_char();
|
||||||
|
update_state();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
input_reveal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -440,13 +502,10 @@ main(int argc, char **argv)
|
||||||
dmalloc_debug(0x2f03d00);
|
dmalloc_debug(0x2f03d00);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
interactive = isatty(0);
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
cmd_build_tree();
|
cmd_build_tree();
|
||||||
server_connect();
|
server_connect();
|
||||||
select_loop(0);
|
select_loop();
|
||||||
|
|
||||||
input_init();
|
|
||||||
|
|
||||||
select_loop(1);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue