pacemaker  2.0.2-debe490
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 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/common/util.h>
11 #include <crm/common/xml.h>
12 #include <crm/common/internal.h>
13 #include <crm/common/output.h>
14 #include <libxml/tree.h>
15 
16 static GHashTable *formatters = NULL;
17 
18 void
20  pcmk__output_factory_t fn = g_hash_table_lookup(formatters, out->fmt_name);
21  CRM_ASSERT(fn != NULL);
22 
23  out->finish(out, exit_status);
24  out->free_priv(out);
25 
26  g_hash_table_destroy(out->messages);
27  free(out->fmt_name);
28  free(out->request);
29  free(out);
30 }
31 
32 int
33 pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename,
34  char **argv) {
35  pcmk__output_factory_t create = NULL;;
36 
37  if (formatters == NULL) {
38  return EINVAL;
39  }
40 
41  /* If no name was given, just try "text". It's up to each tool to register
42  * what it supports so this also may not be valid.
43  */
44  if (fmt_name == NULL) {
45  create = g_hash_table_lookup(formatters, "text");
46  } else {
47  create = g_hash_table_lookup(formatters, fmt_name);
48  }
49 
50  if (create == NULL) {
52  }
53 
54  *out = create(argv);
55  if (*out == NULL) {
56  return ENOMEM;
57  }
58 
59  if (fmt_name == NULL) {
60  (*out)->fmt_name = strdup("text");
61  } else {
62  (*out)->fmt_name = strdup(fmt_name);
63  }
64 
65  if (filename == NULL || safe_str_eq(filename, "-")) {
66  (*out)->dest = stdout;
67  } else {
68  (*out)->dest = fopen(filename, "w");
69  if ((*out)->dest == NULL) {
70  return errno;
71  }
72  }
73 
74  (*out)->messages = g_hash_table_new_full(crm_str_hash, g_str_equal, free, NULL);
75 
76  if ((*out)->init(*out) == false) {
77  pcmk__output_free(*out, 0);
78  return ENOMEM;
79  }
80 
81  return 0;
82 }
83 
84 bool
85 pcmk__parse_output_args(const char *argname, char *argvalue, char **output_ty, char **output_dest) {
86  if (safe_str_eq("output-as", argname)) {
87  *output_ty = argvalue;
88  return true;
89  } else if (safe_str_eq("output-to", argname)) {
90  if (safe_str_eq(argvalue, "-")) {
91  *output_dest = NULL;
92  } else {
93  *output_dest = argvalue;
94  }
95 
96  return true;
97  }
98 
99  return false;
100 }
101 
102 int
103 pcmk__register_format(const char *fmt_name, pcmk__output_factory_t create) {
104  if (create == NULL) {
105  return -EINVAL;
106  }
107 
108  if (formatters == NULL) {
109  formatters = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
110  }
111 
112  g_hash_table_insert(formatters, strdup(fmt_name), create);
113  return 0;
114 }
115 
116 int
117 pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) {
118  va_list args;
119  int rc = 0;
121 
122  fn = g_hash_table_lookup(out->messages, message_id);
123  if (fn == NULL) {
124  return -EINVAL;
125  }
126 
127  va_start(args, message_id);
128  rc = fn(out, args);
129  va_end(args);
130 
131  return rc;
132 }
133 
134 void
135 pcmk__register_message(pcmk__output_t *out, const char *message_id,
136  pcmk__message_fn_t fn) {
137  g_hash_table_replace(out->messages, strdup(message_id), fn);
138 }
139 
140 void
142  pcmk__message_entry_t *entry;
143 
144  for (entry = table; entry->message_id != NULL; entry++) {
145  if (safe_str_eq(out->fmt_name, entry->fmt_name)) {
146  pcmk__register_message(out, entry->message_id, entry->fn);
147  }
148  }
149 }
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status)
Definition: output.h:214
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_...
Definition: output.h:107
Definition: output.h:84
Formatted output for pacemaker tools.
void pcmk__output_free(pcmk__output_t *out, crm_exit_t exit_status)
Definition: output.c:19
char * fmt_name
The name of this output formatter.
Definition: output.h:128
enum crm_exit_e crm_exit_t
pcmk__output_t *(* pcmk__output_factory_t)(char **argv)
Definition: output.h:55
GHashTable * messages
Custom messages that are currently registered on this formatter.
Definition: output.h:161
int pcmk__call_message(pcmk__output_t *out, const char *message_id,...)
Definition: output.c:117
char * request
A copy of the request that generated this output.
Definition: output.h:136
Utility functions.
const char * fmt_name
The format type this handler is for.
Definition: output.h:101
int(* pcmk__message_fn_t)(pcmk__output_t *out, va_list args)
Definition: output.h:71
bool pcmk__parse_output_args(const char *argname, char *argvalue, char **output_ty, char **output_dest)
Definition: output.c:85
Wrappers for and extensions to libxml2.
int pcmk__register_format(const char *fmt_name, pcmk__output_factory_t create)
Definition: output.c:103
void pcmk__register_messages(pcmk__output_t *out, pcmk__message_entry_t *table)
Definition: output.c:141
#define CRM_ASSERT(expr)
Definition: results.h:42
#define pcmk_err_unknown_format
Definition: results.h:76
void(* free_priv)(pcmk__output_t *out)
Definition: output.h:197
This structure contains everything that makes up a single output formatter.
Definition: output.h:124
#define crm_str_hash
Definition: util.h:60
#define safe_str_eq(a, b)
Definition: util.h:59
void pcmk__register_message(pcmk__output_t *out, const char *message_id, pcmk__message_fn_t fn)
Definition: output.c:135
const char * message_id
The message to be handled.
Definition: output.h:91
int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, const char *filename, char **argv)
Definition: output.c:33