pacemaker  2.1.4-dc6eb4362
Scalable High-Availability cluster resource manager
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 
16 static GHashTable *formatters = NULL;
17 
18 void
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 
30 int
31 pcmk__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) {
70  pcmk__output_free(*out);
71  return ENOMEM;
72  }
73 
74  setenv("OCF_OUTPUT_FORMAT", (*out)->fmt_name, 1);
75 
76  return pcmk_rc_ok;
77 }
78 
79 int
80 pcmk__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 
98 void
99 pcmk__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 
111 void
113  if (formatters != NULL) {
114  g_hash_table_destroy(formatters);
115  }
116 }
117 
118 int
119 pcmk__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 
138 void
139 pcmk__register_message(pcmk__output_t *out, const char *message_id,
140  pcmk__message_fn_t fn) {
141  g_hash_table_replace(out->messages, strdup(message_id), fn);
142 }
143 
144 void
146  pcmk__message_entry_t *entry;
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 
155 void
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 }
int(* pcmk__message_fn_t)(pcmk__output_t *out, va_list args)
void pcmk__output_and_clear_error(GError *error, pcmk__output_t *out)
Definition: output.c:156
void pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *formats)
Definition: output.c:99
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 * name
Definition: cib.c:24
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:931
int(* message)(pcmk__output_t *out, const char *message_id,...)
const char * fmt_name
The name of this output formatter.
GHashTable * messages
Custom messages that are currently registered on this formatter.
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:145
#define crm_debug(fmt, args...)
Definition: logging.h:363
GOptionEntry * options
Format-specific command line options. This can be NULL if no command line options should be supported...
Utility functions.
const char * fmt_name
The format type this handler is for.
int setenv(const char *name, const char *value, int why)
void(* free_priv)(pcmk__output_t *out)
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
Wrappers for and extensions to libxml2.
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:31
pcmk__output_factory_t create
A function that creates a pcmk__output_t.
int pcmk__call_message(pcmk__output_t *out, const char *message_id,...)
Definition: output.c:119
void pcmk__unregister_formats()
Definition: output.c:112
pcmk__output_t *(* pcmk__output_factory_t)(char **argv)
void pcmk__register_message(pcmk__output_t *out, const char *message_id, pcmk__message_fn_t fn)
Definition: output.c:139
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:611
void pcmk__output_free(pcmk__output_t *out)
Definition: output.c:19
const char * name
The name of this output formatter, which should match the fmt_name parameter in some pcmk__output_t s...
gchar * request
A copy of the request that generated this output.
This structure contains everything that makes up a single output formatter.
int pcmk__register_format(GOptionGroup *group, const char *name, pcmk__output_factory_t create, GOptionEntry *options)
Definition: output.c:80
const char * message_id
The message to be handled.