pacemaker  2.1.0-7c3f660
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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  return pcmk_rc_ok;
75 }
76 
77 int
78 pcmk__register_format(GOptionGroup *group, const char *name,
79  pcmk__output_factory_t create, GOptionEntry *options) {
80  if (create == NULL) {
81  return -EINVAL;
82  }
83 
84  if (formatters == NULL) {
85  formatters = pcmk__strkey_table(free, NULL);
86  }
87 
88  if (options != NULL && group != NULL) {
89  g_option_group_add_entries(group, options);
90  }
91 
92  g_hash_table_insert(formatters, strdup(name), create);
93  return 0;
94 }
95 
96 void
97 pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *formats) {
98  pcmk__supported_format_t *entry = NULL;
99 
100  if (formats == NULL) {
101  return;
102  }
103 
104  for (entry = formats; entry->name != NULL; entry++) {
105  pcmk__register_format(group, entry->name, entry->create, entry->options);
106  }
107 }
108 
109 void
111  if (formatters != NULL) {
112  g_hash_table_destroy(formatters);
113  }
114 }
115 
116 int
117 pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) {
118  va_list args;
119  int rc = pcmk_rc_ok;
121 
122  fn = g_hash_table_lookup(out->messages, message_id);
123  if (fn == NULL) {
124  crm_debug("Called unknown output message '%s' for format '%s'",
125  message_id, out->fmt_name);
126  return EINVAL;
127  }
128 
129  va_start(args, message_id);
130  rc = fn(out, args);
131  va_end(args);
132 
133  return rc;
134 }
135 
136 void
137 pcmk__register_message(pcmk__output_t *out, const char *message_id,
138  pcmk__message_fn_t fn) {
139  g_hash_table_replace(out->messages, strdup(message_id), fn);
140 }
141 
142 void
144  pcmk__message_entry_t *entry;
145 
146  for (entry = table; entry->message_id != NULL; entry++) {
147  if (pcmk__strcase_any_of(entry->fmt_name, "default", out->fmt_name, NULL)) {
148  pcmk__register_message(out, entry->message_id, entry->fn);
149  }
150  }
151 }
152 
153 void
155 {
156  if (error == NULL) {
157  return;
158  }
159 
160  if (out != NULL) {
161  out->err(out, "%s: %s", g_get_prgname(), error->message);
162  } else {
163  fprintf(stderr, "%s: %s\n", g_get_prgname(), error->message);
164  }
165 
166  g_clear_error(&error);
167 }
pcmk__output_t *(* pcmk__output_factory_t)(char **argv)
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_...
void pcmk__output_and_clear_error(GError *error, pcmk__output_t *out)
Definition: output.c:154
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:929
const char * fmt_name
The name of this output formatter.
void pcmk__register_message(pcmk__output_t *out, const char *message_id, pcmk__message_fn_t fn)
Definition: output.c:137
int(* message)(pcmk__output_t *out, const char *message_id,...)
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void pcmk__register_formats(GOptionGroup *group, pcmk__supported_format_t *table)
Definition: output.c:97
int pcmk__call_message(pcmk__output_t *out, const char *message_id,...)
Definition: output.c:117
GHashTable * messages
Custom messages that are currently registered on this formatter.
int rc
Definition: pcmk_fence.c:35
#define crm_debug(fmt, args...)
Definition: logging.h:355
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 pcmk__register_format(GOptionGroup *group, const char *name, pcmk__output_factory_t create, GOptionEntry *options)
Definition: output.c:78
int(* pcmk__message_fn_t)(pcmk__output_t *out, va_list args)
Wrappers for and extensions to libxml2.
pcmk__output_factory_t create
A function that creates a pcmk__output_t.
void pcmk__output_free(pcmk__output_t *out)
Definition: output.c:19
void pcmk__unregister_formats(void)
Definition: output.c:110
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:610
const char * name
The name of this output formatter, which should match the fmt_name parameter in some pcmk__output_t s...
void(* free_priv)(pcmk__output_t *out)
gchar * request
A copy of the request that generated this output.
This structure contains everything that makes up a single output formatter.
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:143
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:31
char * name
Definition: pcmk_fence.c:31
const char * message_id
The message to be handled.