pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
output.c
Go to the documentation of this file.
1/*
2 * Copyright 2019-2021 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <crm/common/util.h>
13#include <crm/common/xml.h>
14#include <libxml/tree.h>
15
16static GHashTable *formatters = NULL;
17
18void
20 out->free_priv(out);
21
22 if (out->messages != NULL) {
23 g_hash_table_destroy(out->messages);
24 }
25
26 g_free(out->request);
27 free(out);
28}
29
30int
31pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename,
32 char **argv) {
33 pcmk__output_factory_t create = NULL;;
34
35 if (formatters == NULL) {
36 return EINVAL;
37 }
38
39 /* If no name was given, just try "text". It's up to each tool to register
40 * what it supports so this also may not be valid.
41 */
42 if (fmt_name == NULL) {
43 create = g_hash_table_lookup(formatters, "text");
44 } else {
45 create = g_hash_table_lookup(formatters, fmt_name);
46 }
47
48 if (create == NULL) {
50 }
51
52 *out = create(argv);
53 if (*out == NULL) {
54 return ENOMEM;
55 }
56
57 if (pcmk__str_eq(filename, "-", pcmk__str_null_matches)) {
58 (*out)->dest = stdout;
59 } else {
60 (*out)->dest = fopen(filename, "w");
61 if ((*out)->dest == NULL) {
62 return errno;
63 }
64 }
65
66 (*out)->quiet = false;
67 (*out)->messages = pcmk__strkey_table(free, NULL);
68
69 if ((*out)->init(*out) == false) {
71 return ENOMEM;
72 }
73
74 setenv("OCF_OUTPUT_FORMAT", (*out)->fmt_name, 1);
75
76 return pcmk_rc_ok;
77}
78
79int
80pcmk__register_format(GOptionGroup *group, const char *name,
81 pcmk__output_factory_t create, GOptionEntry *options) {
82 if (create == NULL) {
83 return -EINVAL;
84 }
85
86 if (formatters == NULL) {
87 formatters = pcmk__strkey_table(free, NULL);
88 }
89
90 if (options != NULL && group != NULL) {
91 g_option_group_add_entries(group, options);
92 }
93
94 g_hash_table_insert(formatters, strdup(name), create);
95 return 0;
96}
97
98void
99pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *formats) {
100 pcmk__supported_format_t *entry = NULL;
101
102 if (formats == NULL) {
103 return;
104 }
105
106 for (entry = formats; entry->name != NULL; entry++) {
107 pcmk__register_format(group, entry->name, entry->create, entry->options);
108 }
109}
110
111void
113 if (formatters != NULL) {
114 g_hash_table_destroy(formatters);
115 }
116}
117
118int
119pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) {
120 va_list args;
121 int rc = pcmk_rc_ok;
123
124 fn = g_hash_table_lookup(out->messages, message_id);
125 if (fn == NULL) {
126 crm_debug("Called unknown output message '%s' for format '%s'",
127 message_id, out->fmt_name);
128 return EINVAL;
129 }
130
131 va_start(args, message_id);
132 rc = fn(out, args);
133 va_end(args);
134
135 return rc;
136}
137
138void
139pcmk__register_message(pcmk__output_t *out, const char *message_id,
141 g_hash_table_replace(out->messages, strdup(message_id), fn);
142}
143
144void
147
148 for (entry = table; entry->message_id != NULL; entry++) {
149 if (pcmk__strcase_any_of(entry->fmt_name, "default", out->fmt_name, NULL)) {
150 pcmk__register_message(out, entry->message_id, entry->fn);
151 }
152 }
153}
154
155void
157{
158 if (error == NULL) {
159 return;
160 }
161
162 if (out != NULL) {
163 out->err(out, "%s: %s", g_get_prgname(), error->message);
164 } else {
165 fprintf(stderr, "%s: %s\n", g_get_prgname(), error->message);
166 }
167
168 g_clear_error(&error);
169}
Utility functions.
#define crm_debug(fmt, args...)
Definition logging.h:355
int pcmk__register_format(GOptionGroup *group, const char *name, pcmk__output_factory_t create, GOptionEntry *options)
Definition output.c:80
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition output.c:145
void pcmk__output_free(pcmk__output_t *out)
Definition output.c:19
void pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *formats)
Definition output.c:99
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition output.c:31
int pcmk__call_message(pcmk__output_t *out, const char *message_id,...)
Definition output.c:119
void pcmk__register_message(pcmk__output_t *out, const char *message_id, pcmk__message_fn_t fn)
Definition output.c:139
void pcmk__output_and_clear_error(GError *error, pcmk__output_t *out)
Definition output.c:156
void pcmk__unregister_formats()
Definition output.c:112
int(* pcmk__message_fn_t)(pcmk__output_t *out, va_list args)
pcmk__output_t *(* pcmk__output_factory_t)(char **argv)
char * name
Definition pcmk_fence.c:31
int rc
Definition pcmk_fence.c:35
int setenv(const char *name, const char *value, int why)
@ pcmk_rc_ok
Definition results.h:142
@ pcmk_rc_unknown_format
Definition results.h:136
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:610
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:955
@ pcmk__str_null_matches
pcmk__message_fn_t fn
The function to be called for message_id given a match on fmt_name. See comments on pcmk__message_fn_...
const char * fmt_name
The format type this handler is for.
const char * message_id
The message to be handled.
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
GHashTable * messages
Custom messages that are currently registered on this formatter.
const char * fmt_name
The name of this output formatter.
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void(* free_priv)(pcmk__output_t *out)
gchar * request
A copy of the request that generated this output.
GOptionEntry * options
Format-specific command line options. This can be NULL if no command line options should be supported...
pcmk__output_factory_t create
A function that creates a pcmk__output_t.
const char * name
The name of this output formatter, which should match the fmt_name parameter in some pcmk__output_t s...
Wrappers for and extensions to libxml2.