Skip to content
Browse files

Support a paging function on command line interface.

  • Loading branch information...
1 parent e00d766 commit ec03f3bacbac5d18854fd1fece82d8ae2163a744 t-momose committed
Showing with 112 additions and 17 deletions.
  1. +112 −17 kame/kame/shisad/command.c
View
129 kame/kame/shisad/command.c
@@ -1,4 +1,4 @@
-/* $KAME: command.c,v 1.5 2006/04/10 15:30:52 t-momose Exp $ */
+/* $KAME: command.c,v 1.6 2006/07/03 09:21:07 t-momose Exp $ */
/*
* Copyright (C) 2004 WIDE Project.
@@ -48,13 +48,32 @@
static struct sockaddr_in6 sin6_ci;
char *prompt = "> ";
+#define MAX_SCREENLINES 24
+
+struct line_buffer {
+ TAILQ_ENTRY(line_buffer) lb_entry;
+ char line[0];
+};
+
+struct connection_context {
+ LIST_ENTRY(connection_context) cc_entry;
+ int socket;
+ int remained_lines;
+ int wait_nextpage;
+ TAILQ_HEAD(lb_head, line_buffer) lb_head;
+};
+LIST_HEAD(connect_ctx_head, connection_context) connect_ctx_head =
+LIST_HEAD_INITIALIZER(connect_ctx_head);
+
+
void command_help(int, char *);
-void got_interrupt(int, char *);
+static void got_interrupt(int, char *);
void quit_ui(int, char *);
int command_in(int);
int new_connection(int);
-#define disp_prompt(s) write((s), prompt, strlen(prompt))
+static void disp_prompt(int);
static void dispatch_command(int, char *, struct command_table *);
+static struct connection_context *find_connection_context_by_socket(int);
struct command_table basic_command_table[] = {
{"help", command_help, "Show help"},
@@ -130,13 +149,22 @@ new_connection(s)
int ss;
struct sockaddr_in6 sin6;
socklen_t sin6len;
+ struct connection_context *connect_ctx;
sin6len = sizeof(struct sockaddr_in6);
if ((ss = accept(s, (struct sockaddr *)&sin6, &sin6len)) < 0) {
perror("command: accept");
return -1;
}
-
+
+ if ((connect_ctx = malloc(sizeof(*connect_ctx))) == NULL) {
+ return (-1);
+ }
+ memset(connect_ctx, '\0', sizeof(*connect_ctx));
+ connect_ctx->socket = ss;
+ connect_ctx->remained_lines = MAX_SCREENLINES;
+ TAILQ_INIT(&connect_ctx->lb_head);
+ LIST_INSERT_HEAD(&connect_ctx_head, connect_ctx, cc_entry);
new_fd_list(ss, POLLIN, command_in);
disp_prompt(ss);
return (0);
@@ -148,23 +176,38 @@ command_in(s)
{
int bytes;
char buffer[2048];
+ struct connection_context *cc;
+
+ cc = find_connection_context_by_socket(s);
bytes = read(s, buffer, 2048);
/* XXX quick hack for an interrupt, <IAC IP IAC DO TM> */
if (memcmp(buffer, "\xff\xf4\xff\xfd\x06", 5) == 0) {
got_interrupt(s, buffer);
- disp_prompt(s);
- return (0);
+ } else if (cc && cc->wait_nextpage) {
+ /* dump the buffer */
+ int i = MAX_SCREENLINES;
+ struct line_buffer *lb;
+
+ while ((lb = TAILQ_FIRST(&cc->lb_head)) && --i > 0) {
+ write(s, lb->line, strlen(lb->line));
+ TAILQ_REMOVE(&cc->lb_head, lb, lb_entry);
+ free(lb);
+ }
+ if (lb)
+ return (0);
+ cc->wait_nextpage = 0;
+ } else {
+ buffer[bytes] = '\0';
+ while (strlen(buffer) && isspace(buffer[strlen(buffer) - 1]))
+ buffer[strlen(buffer) - 1] = '\0';
+ if (strlen(buffer) > 0)
+ dispatch_command(s, buffer, commands);
}
- buffer[bytes] = '\0';
- while (strlen(buffer) && isspace(buffer[strlen(buffer) - 1]))
- buffer[strlen(buffer) - 1] = '\0';
- if (strlen(buffer) > 0)
- dispatch_command(s, buffer, commands);
-
- disp_prompt(s);
+ if (cc && cc->wait_nextpage == 0)
+ disp_prompt(s);
return (0);
}
@@ -178,7 +221,7 @@ dispatch_command(s, command_line, command_table)
char *arg;
struct command_table *ctbl;
char *errmsg = "??? unknown command\n";
-
+
if ((strncmp(command_line, "help", 4) == 0) ||
(strncmp(command_line, "?", 1) == 0)) {
command_help(s, (char *)command_table);
@@ -214,11 +257,32 @@ command_printf(int s, const char *fmt, ...)
{
va_list ap;
char buffer[512];
-
+ struct connection_context *cc;
+ char *msg_more = "-- MORE -- (push Enter key)";
+
va_start(ap, fmt);
vsnprintf(buffer, 512, fmt, ap);
va_end(ap);
- write(s, buffer, strlen(buffer));
+
+ cc = find_connection_context_by_socket(s);
+ if (cc && cc->remained_lines-- <= 0) {
+ struct line_buffer *lb;
+
+ lb = malloc(sizeof(struct line_buffer) + strlen(buffer) + 1);
+ if (!lb) {
+ syslog(LOG_ERR, "memory allocation for line buffers was failed");
+ write(s, buffer, strlen(buffer));
+ } else {
+ strcpy(lb->line, buffer);
+ TAILQ_INSERT_TAIL(&cc->lb_head, lb, lb_entry);
+ }
+ } else {
+ write(s, buffer, strlen(buffer));
+ if (cc && cc->remained_lines <= 0) {
+ write(s, msg_more, strlen(msg_more));
+ cc->wait_nextpage = 1;
+ }
+ }
}
void
@@ -236,17 +300,37 @@ command_help(s, line)
}
}
+static struct connection_context *
+find_connection_context_by_socket(s)
+ int s;
+{
+ struct connection_context *cc;
+
+ LIST_FOREACH(cc, &connect_ctx_head, cc_entry) {
+ if (cc->socket == s)
+ return (cc);
+ }
+
+ return (cc);
+}
+
void
quit_ui(s, line)
int s;
char *line;
{
+ struct connection_context *cc;
+
+ cc = find_connection_context_by_socket(s);
command_printf(s, "bye bye\n");
+ LIST_REMOVE(cc, cc_entry);
+ free(cc);
delete_fd_list_entry(s);
close(s);
}
-void got_interrupt(s, line)
+static void
+got_interrupt(s, line)
int s;
char *line;
{
@@ -255,3 +339,14 @@ void got_interrupt(s, line)
write(s, buffer, 6);
}
+void
+disp_prompt(s)
+ int s;
+{
+ struct connection_context *cc;
+
+ cc = find_connection_context_by_socket(s);
+ if (cc)
+ cc->remained_lines = MAX_SCREENLINES;
+ write((s), prompt, strlen(prompt));
+}

0 comments on commit ec03f3b

Please sign in to comment.
Something went wrong with that request. Please try again.