This source file includes following definitions.
- pcmk__output_formatters
- pcmk__output_free
- pcmk__bare_output_new
- pcmk__output_new
- pcmk__register_format
- pcmk__register_formats
- pcmk__unregister_formats
- pcmk__call_message
- pcmk__register_message
- pcmk__register_messages
- pcmk__output_and_clear_error
- pcmk__xml_output_new
- pcmk__xml_output_finish
- pcmk__log_output_new
- pcmk__text_output_new
1
2
3
4
5
6
7
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
16 #include "crmcommon_private.h"
17
18 static GHashTable *formatters = NULL;
19
20 #if defined(PCMK__UNIT_TESTING)
21
22 GHashTable *
23 pcmk__output_formatters(void) {
24 return formatters;
25 }
26
27 #endif
28
29 void
30 pcmk__output_free(pcmk__output_t *out) {
31 if (out == NULL) {
32 return;
33 }
34
35 out->free_priv(out);
36
37 if (out->messages != NULL) {
38 g_hash_table_destroy(out->messages);
39 }
40
41 g_free(out->request);
42 free(out);
43 }
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 int
63 pcmk__bare_output_new(pcmk__output_t **out, const char *fmt_name,
64 const char *filename, char **argv)
65 {
66 pcmk__output_factory_t create = NULL;
67
68 pcmk__assert((formatters != NULL) && (out != NULL));
69
70
71
72
73 if (fmt_name == NULL) {
74 create = g_hash_table_lookup(formatters, "text");
75 } else {
76 create = g_hash_table_lookup(formatters, fmt_name);
77 }
78
79 if (create == NULL) {
80 return pcmk_rc_unknown_format;
81 }
82
83 *out = create(argv);
84 if (*out == NULL) {
85 return ENOMEM;
86 }
87
88 if (pcmk__str_eq(filename, "-", pcmk__str_null_matches)) {
89 (*out)->dest = stdout;
90 } else {
91 (*out)->dest = fopen(filename, "w");
92 if ((*out)->dest == NULL) {
93 pcmk__output_free(*out);
94 *out = NULL;
95 return errno;
96 }
97 }
98
99 (*out)->quiet = false;
100 (*out)->messages = pcmk__strkey_table(free, NULL);
101
102 if ((*out)->init(*out) == false) {
103 pcmk__output_free(*out);
104 return ENOMEM;
105 }
106
107 setenv("OCF_OUTPUT_FORMAT", (*out)->fmt_name, 1);
108
109 return pcmk_rc_ok;
110 }
111
112 int
113 pcmk__output_new(pcmk__output_t **out, const char *fmt_name,
114 const char *filename, char **argv)
115 {
116 int rc = pcmk__bare_output_new(out, fmt_name, filename, argv);
117
118 if (rc == pcmk_rc_ok) {
119
120 pcmk__register_option_messages(*out);
121 pcmk__register_patchset_messages(*out);
122 }
123 return rc;
124 }
125
126 int
127 pcmk__register_format(GOptionGroup *group, const char *name,
128 pcmk__output_factory_t create,
129 const GOptionEntry *options)
130 {
131 char *name_copy = NULL;
132
133 pcmk__assert((create != NULL) && !pcmk__str_empty(name));
134
135
136
137 name_copy = strdup(name);
138 if (name_copy == NULL) {
139 return ENOMEM;
140 }
141
142 if (formatters == NULL) {
143 formatters = pcmk__strkey_table(free, NULL);
144 }
145
146 if (options != NULL && group != NULL) {
147 g_option_group_add_entries(group, options);
148 }
149
150 g_hash_table_insert(formatters, name_copy, create);
151 return pcmk_rc_ok;
152 }
153
154 void
155 pcmk__register_formats(GOptionGroup *group,
156 const pcmk__supported_format_t *formats)
157 {
158 if (formats == NULL) {
159 return;
160 }
161 for (const pcmk__supported_format_t *entry = formats; entry->name != NULL;
162 entry++) {
163 pcmk__register_format(group, entry->name, entry->create, entry->options);
164 }
165 }
166
167 void
168 pcmk__unregister_formats(void) {
169 if (formatters != NULL) {
170 g_hash_table_destroy(formatters);
171 formatters = NULL;
172 }
173 }
174
175 int
176 pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) {
177 va_list args;
178 int rc = pcmk_rc_ok;
179 pcmk__message_fn_t fn;
180
181 pcmk__assert((out != NULL) && !pcmk__str_empty(message_id));
182
183 fn = g_hash_table_lookup(out->messages, message_id);
184 if (fn == NULL) {
185 crm_debug("Called unknown output message '%s' for format '%s'",
186 message_id, out->fmt_name);
187 return EINVAL;
188 }
189
190 va_start(args, message_id);
191 rc = fn(out, args);
192 va_end(args);
193
194 return rc;
195 }
196
197 void
198 pcmk__register_message(pcmk__output_t *out, const char *message_id,
199 pcmk__message_fn_t fn)
200 {
201 pcmk__assert((out != NULL) && !pcmk__str_empty(message_id) && (fn != NULL));
202 g_hash_table_replace(out->messages, pcmk__str_copy(message_id), fn);
203 }
204
205 void
206 pcmk__register_messages(pcmk__output_t *out, const pcmk__message_entry_t *table)
207 {
208 for (const pcmk__message_entry_t *entry = table; entry->message_id != NULL;
209 entry++) {
210 if (pcmk__strcase_any_of(entry->fmt_name, "default", out->fmt_name, NULL)) {
211 pcmk__register_message(out, entry->message_id, entry->fn);
212 }
213 }
214 }
215
216 void
217 pcmk__output_and_clear_error(GError **error, pcmk__output_t *out)
218 {
219 if (error == NULL || *error == NULL) {
220 return;
221 }
222
223 if (out != NULL) {
224 out->err(out, "%s: %s", g_get_prgname(), (*error)->message);
225 } else {
226 fprintf(stderr, "%s: %s\n", g_get_prgname(), (*error)->message);
227 }
228
229 g_clear_error(error);
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 int
246 pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml) {
247 pcmk__supported_format_t xml_format[] = {
248 PCMK__SUPPORTED_FORMAT_XML,
249 { NULL, NULL, NULL }
250 };
251
252 if (xml == NULL) {
253 return EINVAL;
254 }
255
256 if (*xml != NULL) {
257 pcmk__xml_free(*xml);
258 *xml = NULL;
259 }
260 pcmk__register_formats(NULL, xml_format);
261 return pcmk__output_new(out, "xml", NULL, NULL);
262 }
263
264
265
266
267
268
269
270
271
272 void
273 pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status,
274 xmlNodePtr *xml)
275 {
276 if (out == NULL) {
277 return;
278 }
279
280 out->finish(out, exit_status, FALSE, (void **) xml);
281 pcmk__output_free(out);
282 }
283
284
285
286
287
288
289
290
291
292 int
293 pcmk__log_output_new(pcmk__output_t **out)
294 {
295 int rc = pcmk_rc_ok;
296 const char* argv[] = { "", NULL };
297 pcmk__supported_format_t formats[] = {
298 PCMK__SUPPORTED_FORMAT_LOG,
299 { NULL, NULL, NULL }
300 };
301
302 pcmk__register_formats(NULL, formats);
303 rc = pcmk__output_new(out, "log", NULL, (char **) argv);
304 if ((rc != pcmk_rc_ok) || (*out == NULL)) {
305 crm_err("Can't log certain messages due to internal error: %s",
306 pcmk_rc_str(rc));
307 return rc;
308 }
309 return pcmk_rc_ok;
310 }
311
312
313
314
315
316
317
318
319
320
321 int
322 pcmk__text_output_new(pcmk__output_t **out, const char *filename)
323 {
324 int rc = pcmk_rc_ok;
325 const char* argv[] = { "", NULL };
326 pcmk__supported_format_t formats[] = {
327 PCMK__SUPPORTED_FORMAT_TEXT,
328 { NULL, NULL, NULL }
329 };
330
331 pcmk__register_formats(NULL, formats);
332 rc = pcmk__output_new(out, "text", filename, (char **) argv);
333 if ((rc != pcmk_rc_ok) || (*out == NULL)) {
334 crm_err("Can't create text output object to internal error: %s",
335 pcmk_rc_str(rc));
336 return rc;
337 }
338 return pcmk_rc_ok;
339 }