|
rpm-build |
3ee90c |
/*
|
|
rpm-build |
3ee90c |
* Copyright 2019 the Pacemaker project contributors
|
|
rpm-build |
3ee90c |
*
|
|
rpm-build |
3ee90c |
* The version control history for this file may have further details.
|
|
rpm-build |
3ee90c |
*
|
|
rpm-build |
3ee90c |
* This source code is licensed under the GNU Lesser General Public License
|
|
rpm-build |
3ee90c |
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
|
|
rpm-build |
3ee90c |
*/
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include <stdarg.h>
|
|
rpm-build |
3ee90c |
#include <stdlib.h>
|
|
rpm-build |
3ee90c |
#include <crm/crm.h>
|
|
rpm-build |
3ee90c |
#include <crm/common/curses_internal.h>
|
|
rpm-build |
3ee90c |
#include <crm/common/output.h>
|
|
rpm-build |
3ee90c |
#include <glib.h>
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#include "crm_mon.h"
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#if CURSES_ENABLED
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
GOptionEntry crm_mon_curses_output_entries[] = {
|
|
rpm-build |
3ee90c |
{ NULL }
|
|
rpm-build |
3ee90c |
};
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
typedef struct curses_list_data_s {
|
|
rpm-build |
3ee90c |
unsigned int len;
|
|
rpm-build |
3ee90c |
char *singular_noun;
|
|
rpm-build |
3ee90c |
char *plural_noun;
|
|
rpm-build |
3ee90c |
} curses_list_data_t;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
typedef struct private_data_s {
|
|
rpm-build |
3ee90c |
GQueue *parent_q;
|
|
rpm-build |
3ee90c |
} private_data_t;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_free_priv(pcmk__output_t *out) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (priv == NULL) {
|
|
rpm-build |
3ee90c |
return;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
g_queue_free(priv->parent_q);
|
|
rpm-build |
3ee90c |
free(priv);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static bool
|
|
rpm-build |
3ee90c |
curses_init(pcmk__output_t *out) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = NULL;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
/* If curses_init was previously called on this output struct, just return. */
|
|
rpm-build |
3ee90c |
if (out->priv != NULL) {
|
|
rpm-build |
3ee90c |
return true;
|
|
rpm-build |
3ee90c |
} else {
|
|
rpm-build |
3ee90c |
out->priv = calloc(1, sizeof(private_data_t));
|
|
rpm-build |
3ee90c |
if (out->priv == NULL) {
|
|
rpm-build |
3ee90c |
return false;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
priv = out->priv;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
priv->parent_q = g_queue_new();
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
initscr();
|
|
rpm-build |
3ee90c |
cbreak();
|
|
rpm-build |
3ee90c |
noecho();
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
return true;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_reset(pcmk__output_t *out) {
|
|
rpm-build |
3ee90c |
CRM_ASSERT(out->priv != NULL);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
curses_free_priv(out);
|
|
rpm-build |
3ee90c |
curses_init(out);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_subprocess_output(pcmk__output_t *out, int exit_status,
|
|
rpm-build |
3ee90c |
const char *proc_stdout, const char *proc_stderr) {
|
|
rpm-build |
3ee90c |
if (proc_stdout != NULL) {
|
|
rpm-build |
3ee90c |
printw("%s\n", proc_stdout);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (proc_stderr != NULL) {
|
|
rpm-build |
3ee90c |
printw("%s\n", proc_stderr);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
clrtoeol();
|
|
rpm-build |
3ee90c |
refresh();
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
/* curses_version is defined in curses.h, so we can't use that name here.
|
|
rpm-build |
3ee90c |
* Note that this function prints out via text, not with curses.
|
|
rpm-build |
3ee90c |
*/
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_ver(pcmk__output_t *out, bool extended) {
|
|
rpm-build |
3ee90c |
if (extended) {
|
|
rpm-build |
3ee90c |
printf("Pacemaker %s (Build: %s): %s\n", PACEMAKER_VERSION, BUILD_VERSION, CRM_FEATURES);
|
|
rpm-build |
3ee90c |
} else {
|
|
rpm-build |
3ee90c |
printf("Pacemaker %s\n", PACEMAKER_VERSION);
|
|
rpm-build |
3ee90c |
printf("Written by Andrew Beekhof\n");
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(2, 3)
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_err_info(pcmk__output_t *out, const char *format, ...) {
|
|
rpm-build |
3ee90c |
va_list ap;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
/* Informational output does not get indented, to separate it from other
|
|
rpm-build |
3ee90c |
* potentially indented list output.
|
|
rpm-build |
3ee90c |
*/
|
|
rpm-build |
3ee90c |
va_start(ap, format);
|
|
rpm-build |
3ee90c |
vw_printw(stdscr, format, ap);
|
|
rpm-build |
3ee90c |
va_end(ap);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
/* Add a newline. */
|
|
rpm-build |
3ee90c |
addch('\n');
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
clrtoeol();
|
|
rpm-build |
3ee90c |
refresh();
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_output_xml(pcmk__output_t *out, const char *name, const char *buf) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_ASSERT(priv != NULL);
|
|
rpm-build |
3ee90c |
curses_indented_printf(out, "%s", buf);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(4, 5)
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_begin_list(pcmk__output_t *out, const char *singular_noun, const char *plural_noun,
|
|
rpm-build |
3ee90c |
const char *format, ...) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
curses_list_data_t *new_list = NULL;
|
|
rpm-build |
3ee90c |
va_list ap;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_ASSERT(priv != NULL);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
va_start(ap, format);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
curses_indented_vprintf(out, format, ap);
|
|
rpm-build |
3ee90c |
printw(":\n");
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
va_end(ap);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
new_list = calloc(1, sizeof(curses_list_data_t));
|
|
rpm-build |
3ee90c |
new_list->len = 0;
|
|
rpm-build |
3ee90c |
new_list->singular_noun = singular_noun == NULL ? NULL : strdup(singular_noun);
|
|
rpm-build |
3ee90c |
new_list->plural_noun = plural_noun == NULL ? NULL : strdup(plural_noun);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
g_queue_push_tail(priv->parent_q, new_list);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(3, 4)
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_list_item(pcmk__output_t *out, const char *id, const char *format, ...) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
va_list ap;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_ASSERT(priv != NULL);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
va_start(ap, format);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (id != NULL) {
|
|
rpm-build |
3ee90c |
curses_indented_printf(out, "%s: ", id);
|
|
rpm-build |
3ee90c |
vw_printw(stdscr, format, ap);
|
|
rpm-build |
3ee90c |
} else {
|
|
rpm-build |
3ee90c |
curses_indented_vprintf(out, format, ap);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
addch('\n');
|
|
rpm-build |
3ee90c |
va_end(ap);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
out->increment_list(out);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_increment_list(pcmk__output_t *out) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
gpointer tail;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_ASSERT(priv != NULL);
|
|
rpm-build |
3ee90c |
tail = g_queue_peek_tail(priv->parent_q);
|
|
rpm-build |
3ee90c |
CRM_ASSERT(tail != NULL);
|
|
rpm-build |
3ee90c |
((curses_list_data_t *) tail)->len++;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
static void
|
|
rpm-build |
3ee90c |
curses_end_list(pcmk__output_t *out) {
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
curses_list_data_t *node = NULL;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_ASSERT(priv != NULL);
|
|
rpm-build |
3ee90c |
node = g_queue_pop_tail(priv->parent_q);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (node->singular_noun != NULL && node->plural_noun != NULL) {
|
|
rpm-build |
3ee90c |
if (node->len == 1) {
|
|
rpm-build |
3ee90c |
curses_indented_printf(out, "%d %s found\n", node->len, node->singular_noun);
|
|
rpm-build |
3ee90c |
} else {
|
|
rpm-build |
3ee90c |
curses_indented_printf(out, "%d %s found\n", node->len, node->plural_noun);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
free(node);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
pcmk__output_t *
|
|
rpm-build |
3ee90c |
crm_mon_mk_curses_output(char **argv) {
|
|
rpm-build |
3ee90c |
pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (retval == NULL) {
|
|
rpm-build |
3ee90c |
return NULL;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
retval->fmt_name = "console";
|
|
rpm-build |
3ee90c |
retval->request = g_strjoinv(" ", argv);
|
|
rpm-build |
3ee90c |
retval->supports_quiet = true;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
retval->init = curses_init;
|
|
rpm-build |
3ee90c |
retval->free_priv = curses_free_priv;
|
|
rpm-build |
3ee90c |
retval->finish = curses_finish;
|
|
rpm-build |
3ee90c |
retval->reset = curses_reset;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
retval->register_message = pcmk__register_message;
|
|
rpm-build |
3ee90c |
retval->message = pcmk__call_message;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
retval->subprocess_output = curses_subprocess_output;
|
|
rpm-build |
3ee90c |
retval->version = curses_ver;
|
|
rpm-build |
3ee90c |
retval->err = curses_err_info;
|
|
rpm-build |
3ee90c |
retval->info = curses_err_info;
|
|
rpm-build |
3ee90c |
retval->output_xml = curses_output_xml;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
retval->begin_list = curses_begin_list;
|
|
rpm-build |
3ee90c |
retval->list_item = curses_list_item;
|
|
rpm-build |
3ee90c |
retval->increment_list = curses_increment_list;
|
|
rpm-build |
3ee90c |
retval->end_list = curses_end_list;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
return retval;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(2, 0)
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
curses_indented_vprintf(pcmk__output_t *out, const char *format, va_list args) {
|
|
rpm-build |
3ee90c |
int level = 0;
|
|
rpm-build |
3ee90c |
private_data_t *priv = out->priv;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
CRM_ASSERT(priv != NULL);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
level = g_queue_get_length(priv->parent_q);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
for (int i = 0; i < level; i++) {
|
|
rpm-build |
3ee90c |
printw(" ");
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
if (level > 0) {
|
|
rpm-build |
3ee90c |
printw("* ");
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
vw_printw(stdscr, format, args);
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
clrtoeol();
|
|
rpm-build |
3ee90c |
refresh();
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(2, 3)
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
curses_indented_printf(pcmk__output_t *out, const char *format, ...) {
|
|
rpm-build |
3ee90c |
va_list ap;
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
va_start(ap, format);
|
|
rpm-build |
3ee90c |
curses_indented_vprintf(out, format, ap);
|
|
rpm-build |
3ee90c |
va_end(ap);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
#else
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
pcmk__output_t *
|
|
rpm-build |
3ee90c |
crm_mon_mk_curses_output(char **argv) {
|
|
rpm-build |
3ee90c |
/* curses was disabled in the build, so fall back to text. */
|
|
rpm-build |
3ee90c |
return pcmk__mk_text_output(argv);
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(2, 0)
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
curses_indented_vprintf(pcmk__output_t *out, const char *format, va_list args) {
|
|
rpm-build |
3ee90c |
return;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
G_GNUC_PRINTF(2, 3)
|
|
rpm-build |
3ee90c |
void
|
|
rpm-build |
3ee90c |
curses_indented_printf(pcmk__output_t *out, const char *format, va_list args) {
|
|
rpm-build |
3ee90c |
return;
|
|
rpm-build |
3ee90c |
}
|
|
rpm-build |
3ee90c |
|
|
rpm-build |
3ee90c |
#endif
|