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 CRM_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 CRM_ASSERT(create != NULL && !pcmk__str_empty(name));
134
135 name_copy = strdup(name);
136 if (name_copy == NULL) {
137 return ENOMEM;
138 }
139
140 if (formatters == NULL) {
141 formatters = pcmk__strkey_table(free, NULL);
142 }
143
144 if (options != NULL && group != NULL) {
145 g_option_group_add_entries(group, options);
146 }
147
148 g_hash_table_insert(formatters, name_copy, create);
149 return pcmk_rc_ok;
150 }
151
152 void
153 pcmk__register_formats(GOptionGroup *group,
154 const pcmk__supported_format_t *formats)
155 {
156 if (formats == NULL) {
157 return;
158 }
159 for (const pcmk__supported_format_t *entry = formats; entry->name != NULL;
160 entry++) {
161 pcmk__register_format(group, entry->name, entry->create, entry->options);
162 }
163 }
164
165 void
166 pcmk__unregister_formats(void) {
167 if (formatters != NULL) {
168 g_hash_table_destroy(formatters);
169 formatters = NULL;
170 }
171 }
172
173 int
174 pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) {
175 va_list args;
176 int rc = pcmk_rc_ok;
177 pcmk__message_fn_t fn;
178
179 CRM_ASSERT(out != NULL && !pcmk__str_empty(message_id));
180
181 fn = g_hash_table_lookup(out->messages, message_id);
182 if (fn == NULL) {
183 crm_debug("Called unknown output message '%s' for format '%s'",
184 message_id, out->fmt_name);
185 return EINVAL;
186 }
187
188 va_start(args, message_id);
189 rc = fn(out, args);
190 va_end(args);
191
192 return rc;
193 }
194
195 void
196 pcmk__register_message(pcmk__output_t *out, const char *message_id,
197 pcmk__message_fn_t fn) {
198 CRM_ASSERT(out != NULL && !pcmk__str_empty(message_id) && fn != NULL);
199
200 g_hash_table_replace(out->messages, pcmk__str_copy(message_id), fn);
201 }
202
203 void
204 pcmk__register_messages(pcmk__output_t *out, const pcmk__message_entry_t *table)
205 {
206 for (const pcmk__message_entry_t *entry = table; entry->message_id != NULL;
207 entry++) {
208 if (pcmk__strcase_any_of(entry->fmt_name, "default", out->fmt_name, NULL)) {
209 pcmk__register_message(out, entry->message_id, entry->fn);
210 }
211 }
212 }
213
214 void
215 pcmk__output_and_clear_error(GError **error, pcmk__output_t *out)
216 {
217 if (error == NULL || *error == NULL) {
218 return;
219 }
220
221 if (out != NULL) {
222 out->err(out, "%s: %s", g_get_prgname(), (*error)->message);
223 } else {
224 fprintf(stderr, "%s: %s\n", g_get_prgname(), (*error)->message);
225 }
226
227 g_clear_error(error);
228 }
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 int
244 pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml) {
245 pcmk__supported_format_t xml_format[] = {
246 PCMK__SUPPORTED_FORMAT_XML,
247 { NULL, NULL, NULL }
248 };
249
250 if (xml == NULL) {
251 return EINVAL;
252 }
253
254 if (*xml != NULL) {
255 xmlFreeNode(*xml);
256 *xml = NULL;
257 }
258 pcmk__register_formats(NULL, xml_format);
259 return pcmk__output_new(out, "xml", NULL, NULL);
260 }
261
262
263
264
265
266
267
268
269
270 void
271 pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status,
272 xmlNodePtr *xml)
273 {
274 if (out == NULL) {
275 return;
276 }
277
278 out->finish(out, exit_status, FALSE, (void **) xml);
279 pcmk__output_free(out);
280 }
281
282
283
284
285
286
287
288
289
290 int
291 pcmk__log_output_new(pcmk__output_t **out)
292 {
293 int rc = pcmk_rc_ok;
294 const char* argv[] = { "", NULL };
295 pcmk__supported_format_t formats[] = {
296 PCMK__SUPPORTED_FORMAT_LOG,
297 { NULL, NULL, NULL }
298 };
299
300 pcmk__register_formats(NULL, formats);
301 rc = pcmk__output_new(out, "log", NULL, (char **) argv);
302 if ((rc != pcmk_rc_ok) || (*out == NULL)) {
303 crm_err("Can't log certain messages due to internal error: %s",
304 pcmk_rc_str(rc));
305 return rc;
306 }
307 return pcmk_rc_ok;
308 }
309
310
311
312
313
314
315
316
317
318
319 int
320 pcmk__text_output_new(pcmk__output_t **out, const char *filename)
321 {
322 int rc = pcmk_rc_ok;
323 const char* argv[] = { "", NULL };
324 pcmk__supported_format_t formats[] = {
325 PCMK__SUPPORTED_FORMAT_TEXT,
326 { NULL, NULL, NULL }
327 };
328
329 pcmk__register_formats(NULL, formats);
330 rc = pcmk__output_new(out, "text", filename, (char **) argv);
331 if ((rc != pcmk_rc_ok) || (*out == NULL)) {
332 crm_err("Can't create text output object to internal error: %s",
333 pcmk_rc_str(rc));
334 return rc;
335 }
336 return pcmk_rc_ok;
337 }