Skip to content

Commit

Permalink
pager: Working pager on client side
Browse files Browse the repository at this point in the history
  • Loading branch information
pkun committed Oct 20, 2022
1 parent d0eaf0e commit 6c79c93
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 10 deletions.
51 changes: 45 additions & 6 deletions bin/klish/interactive.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>

#include <faux/faux.h>
#include <faux/str.h>
Expand All @@ -21,6 +23,8 @@ typedef struct ctx_s {
tinyrl_t *tinyrl;
struct options *opts;
char *hotkeys[VT100_HOTKEY_MAP_LEN];
tri_t pager_working;
FILE *pager_pipe;
} ctx_t;


Expand Down Expand Up @@ -75,9 +79,8 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
ctx.tinyrl = tinyrl;
ctx.opts = opts;
faux_bzero(ctx.hotkeys, sizeof(ctx.hotkeys));

// Replace common stdout callback by interactive-specific one.
ktp_session_set_cb(ktp, KTP_SESSION_CB_STDOUT, interactive_stdout_cb, &ctx);
ctx.pager_working = TRI_UNDEFINED;
ctx.pager_pipe = NULL;

// Now AUTH command is used only for starting hand-shake and getting
// prompt from the server. Generally it must be necessary for
Expand All @@ -88,6 +91,10 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
if (auth_rc < 0)
goto cleanup;

// Replace common stdout callback by interactive-specific one.
// Place it after auth to make auth use standard stdout callback.
ktp_session_set_cb(ktp, KTP_SESSION_CB_STDOUT, interactive_stdout_cb, &ctx);

// Don't stop interactive loop on each answer
ktp_session_set_stop_on_answer(ktp, BOOL_FALSE);

Expand Down Expand Up @@ -240,6 +247,13 @@ bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
}
faux_error_free(error);

// Wait for pager
if (ctx->pager_working == TRI_TRUE) {
pclose(ctx->pager_pipe);
ctx->pager_working = TRI_UNDEFINED;
ctx->pager_pipe = NULL;
}

tinyrl_set_busy(ctx->tinyrl, BOOL_FALSE);
if (!ktp_session_done(ktp))
tinyrl_redisplay(ctx->tinyrl);
Expand Down Expand Up @@ -572,10 +586,35 @@ static bool_t interactive_stdout_cb(ktp_session_t *ktp, const char *line, size_t
{
ctx_t *ctx = (ctx_t *)udata;

if (write(STDOUT_FILENO, line, len) < 0)
return BOOL_FALSE;
assert(ctx);

ktp = ktp; // Happy compiler
// Start pager if necessary
if (
ctx->opts->pager_enabled && // Pager enabled within config file
(ctx->pager_working == TRI_UNDEFINED) && // Pager is not working
!(ktp_session_cmd_features(ktp) & KTP_STATUS_INTERACTIVE) // Non interactive command
) {

ctx->pager_pipe = popen(ctx->opts->pager, "we");
if (!ctx->pager_pipe)
ctx->pager_working = BOOL_FALSE; // Indicates can't start
else
ctx->pager_working = BOOL_TRUE;
}

// Write to pager's pipe if pager is really working
if (ctx->pager_working == TRI_TRUE) {
if (fwrite(line, 1, len, ctx->pager_pipe) == 0) {
// If we can't write to pager pipe then try stdout.
if (write(STDOUT_FILENO, line, len) < 0)
return BOOL_FALSE;
return BOOL_TRUE; // Don't break the loop
}
fflush(ctx->pager_pipe);
} else {
if (write(STDOUT_FILENO, line, len) < 0)
return BOOL_FALSE;
}

return BOOL_TRUE;
}
2 changes: 1 addition & 1 deletion bin/klish/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#endif

#define DEFAULT_CFGFILE "/etc/klish/klish.conf"
#define DEFAULT_PAGER "/usr/bin/less -I -F -e -X -K -d"
#define DEFAULT_PAGER "/usr/bin/less -I -F -e -X -K -d -r"

/** @brief Command line and config file options
*/
Expand Down
6 changes: 3 additions & 3 deletions klish.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#UnixSocketPath=/tmp/klish-unix-socket

# The klish can use external pager for non-interactive commands. By default it
# will execute "/usr/bin/less -I -F -e -X -K -d" process as a pager.
#Pager=/usr/bin/less -I -F -e -X -K -d
# will execute "/usr/bin/less -I -F -e -X -K -d -r" process as a pager.
Pager=/usr/bin/less -I -F -e -X -K -d -r

# External pager is enabled by default. But user can explicitly enable or
# disable it. Use "y" or "n" values.
# UsePager=y
#UsePager=y
1 change: 1 addition & 0 deletions klish/ktp_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ bool_t ktp_session_completion(ktp_session_t *ktp, const char *line,
bool_t dry_run);
bool_t ktp_session_help(ktp_session_t *ktp, const char *line);
bool_t ktp_session_retcode(ktp_session_t *ktp, int *retcode);
ktp_status_e ktp_session_cmd_features(const ktp_session_t *ktp);


// Server KTP session
Expand Down

0 comments on commit 6c79c93

Please sign in to comment.