This source file includes following definitions.
- pcmk__output_formatters
- pcmk__output_free
- 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
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 static GHashTable *formatters = NULL;
17
18 #if defined(PCMK__UNIT_TESTING)
19 GHashTable *
20 pcmk__output_formatters(void) {
21 return formatters;
22 }
23 #endif
24
25 void
26 pcmk__output_free(pcmk__output_t *out) {
27 if (out == NULL) {
28 return;
29 }
30
31 out->free_priv(out);
32
33 if (out->messages != NULL) {
34 g_hash_table_destroy(out->messages);
35 }
36
37 g_free(out->request);
38 free(out);
39 }
40
41 int
42 pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename,
43 char **argv) {
44 pcmk__output_factory_t create = NULL;
45
46 CRM_ASSERT(formatters != NULL && out != NULL);
47
48
49
50
51 if (fmt_name == NULL) {
52 create = g_hash_table_lookup(formatters, "text");
53 } else {
54 create = g_hash_table_lookup(formatters, fmt_name);
55 }
56
57 if (create == NULL) {
58 return pcmk_rc_unknown_format;
59 }
60
61 *out = create(argv);
62 if (*out == NULL) {
63 return ENOMEM;
64 }
65
66 if (pcmk__str_eq(filename, "-", pcmk__str_null_matches)) {
67 (*out)->dest = stdout;
68 } else {
69 (*out)->dest = fopen(filename, "w");
70 if ((*out)->dest == NULL) {
71 pcmk__output_free(*out);
72 *out = NULL;
73 return errno;
74 }
75 }
76
77 (*out)->quiet = false;
78 (*out)->messages = pcmk__strkey_table(free, NULL);
79
80 if ((*out)->init(*out) == false) {
81 pcmk__output_free(*out);
82 return ENOMEM;
83 }
84
85 setenv("OCF_OUTPUT_FORMAT", (*out)->fmt_name, 1);
86
87 return pcmk_rc_ok;
88 }
89
90 int
91 pcmk__register_format(GOptionGroup *group, const char *name,
92 pcmk__output_factory_t create,
93 const GOptionEntry *options)
94 {
95 CRM_ASSERT(create != NULL && !pcmk__str_empty(name));
96
97 if (formatters == NULL) {
98 formatters = pcmk__strkey_table(free, NULL);
99 }
100
101 if (options != NULL && group != NULL) {
102 g_option_group_add_entries(group, options);
103 }
104
105 g_hash_table_insert(formatters, strdup(name), create);
106 return pcmk_rc_ok;
107 }
108
109 void
110 pcmk__register_formats(GOptionGroup *group,
111 const pcmk__supported_format_t *formats)
112 {
113 if (formats == NULL) {
114 return;
115 }
116 for (const pcmk__supported_format_t *entry = formats; entry->name != NULL;
117 entry++) {
118 pcmk__register_format(group, entry->name, entry->create, entry->options);
119 }
120 }
121
122 void
123 pcmk__unregister_formats() {
124 if (formatters != NULL) {
125 g_hash_table_destroy(formatters);
126 formatters = NULL;
127 }
128 }
129
130 int
131 pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) {
132 va_list args;
133 int rc = pcmk_rc_ok;
134 pcmk__message_fn_t fn;
135
136 CRM_ASSERT(out != NULL && !pcmk__str_empty(message_id));
137
138 fn = g_hash_table_lookup(out->messages, message_id);
139 if (fn == NULL) {
140 crm_debug("Called unknown output message '%s' for format '%s'",
141 message_id, out->fmt_name);
142 return EINVAL;
143 }
144
145 va_start(args, message_id);
146 rc = fn(out, args);
147 va_end(args);
148
149 return rc;
150 }
151
152 void
153 pcmk__register_message(pcmk__output_t *out, const char *message_id,
154 pcmk__message_fn_t fn) {
155 CRM_ASSERT(out != NULL && !pcmk__str_empty(message_id) && fn != NULL);
156
157 g_hash_table_replace(out->messages, strdup(message_id), fn);
158 }
159
160 void
161 pcmk__register_messages(pcmk__output_t *out, const pcmk__message_entry_t *table)
162 {
163 for (const pcmk__message_entry_t *entry = table; entry->message_id != NULL;
164 entry++) {
165 if (pcmk__strcase_any_of(entry->fmt_name, "default", out->fmt_name, NULL)) {
166 pcmk__register_message(out, entry->message_id, entry->fn);
167 }
168 }
169 }
170
171 void
172 pcmk__output_and_clear_error(GError *error, pcmk__output_t *out)
173 {
174 if (error == NULL) {
175 return;
176 }
177
178 if (out != NULL) {
179 out->err(out, "%s: %s", g_get_prgname(), error->message);
180 } else {
181 fprintf(stderr, "%s: %s\n", g_get_prgname(), error->message);
182 }
183
184 g_clear_error(&error);
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200 int
201 pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml) {
202 pcmk__supported_format_t xml_format[] = {
203 PCMK__SUPPORTED_FORMAT_XML,
204 { NULL, NULL, NULL }
205 };
206
207 if (*xml != NULL) {
208 xmlFreeNode(*xml);
209 *xml = NULL;
210 }
211 pcmk__register_formats(NULL, xml_format);
212 return pcmk__output_new(out, "xml", NULL, NULL);
213 }
214
215
216
217
218
219
220
221
222 void
223 pcmk__xml_output_finish(pcmk__output_t *out, xmlNodePtr *xml) {
224 out->finish(out, 0, FALSE, (void **) xml);
225 pcmk__output_free(out);
226 }
227
228
229
230
231
232
233
234
235
236 int
237 pcmk__log_output_new(pcmk__output_t **out)
238 {
239 int rc = pcmk_rc_ok;
240 const char* argv[] = { "", NULL };
241 pcmk__supported_format_t formats[] = {
242 PCMK__SUPPORTED_FORMAT_LOG,
243 { NULL, NULL, NULL }
244 };
245
246 pcmk__register_formats(NULL, formats);
247 rc = pcmk__output_new(out, "log", NULL, (char **) argv);
248 if ((rc != pcmk_rc_ok) || (*out == NULL)) {
249 crm_err("Can't log certain messages due to internal error: %s",
250 pcmk_rc_str(rc));
251 return rc;
252 }
253 return pcmk_rc_ok;
254 }