Line data Source code
1 : /*
2 : * Copyright 2022 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/cib/internal.h>
13 : #include <crm/crm.h>
14 :
15 : #include <pacemaker.h>
16 : #include <pacemaker-internal.h>
17 :
18 : #include <inttypes.h> // PRIx32
19 : #include <stdint.h> // uint32_t
20 :
21 : /*!
22 : * \internal
23 : * \brief Display the name and/or description of a result code
24 : *
25 : * \param[in,out] out Output object
26 : * \param[in] code The result code
27 : * \param[in] type Interpret \c code as this type of result code.
28 : * Supported values: \c pcmk_result_legacy,
29 : * \c pcmk_result_rc, \c pcmk_result_exitcode.
30 : * \param[in] flags Group of \c pcmk_rc_disp_flags
31 : *
32 : * \return Standard Pacemaker return code
33 : */
34 : int
35 0 : pcmk__show_result_code(pcmk__output_t *out, int code,
36 : enum pcmk_result_type type, uint32_t flags)
37 : {
38 0 : int rc = pcmk_rc_ok;
39 0 : bool quiet_orig = out->quiet;
40 0 : const char *name = NULL;
41 0 : const char *desc = NULL;
42 :
43 0 : rc = pcmk_result_get_strings(code, type, &name, &desc);
44 0 : if (rc != pcmk_rc_ok) {
45 0 : out->err(out, "Error looking up result code %d", code);
46 0 : return rc;
47 : }
48 :
49 : // out->quiet controls whether the code is shown (if quiet is supported)
50 0 : out->quiet = !pcmk_is_set(flags, pcmk_rc_disp_code);
51 :
52 0 : out->message(out, "result-code", code,
53 0 : pcmk_is_set(flags, pcmk_rc_disp_name)? name : NULL,
54 0 : pcmk_is_set(flags, pcmk_rc_disp_desc)? desc : NULL);
55 0 : out->quiet = quiet_orig;
56 :
57 0 : return rc;
58 : }
59 :
60 : // Documented in header
61 : int
62 0 : pcmk_show_result_code(xmlNodePtr *xml, int code, enum pcmk_result_type type,
63 : uint32_t flags)
64 : {
65 0 : pcmk__output_t *out = NULL;
66 0 : int rc = pcmk_rc_ok;
67 :
68 0 : rc = pcmk__xml_output_new(&out, xml);
69 0 : if (rc != pcmk_rc_ok) {
70 0 : return rc;
71 : }
72 :
73 0 : pcmk__register_lib_messages(out);
74 :
75 0 : rc = pcmk__show_result_code(out, code, type, flags);
76 0 : pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
77 0 : return rc;
78 : }
79 :
80 : /*!
81 : * \internal
82 : * \brief List all valid result codes in a particular family
83 : *
84 : * \param[in,out] out Output object
85 : * \param[in] type The family of result codes to list. Supported
86 : * values: \c pcmk_result_legacy, \c pcmk_result_rc,
87 : * \c pcmk_result_exitcode.
88 : * \param[in] flags Group of \c pcmk_rc_disp_flags
89 : *
90 : * \return Standard Pacemaker return code
91 : */
92 : int
93 0 : pcmk__list_result_codes(pcmk__output_t *out, enum pcmk_result_type type,
94 : uint32_t flags)
95 : {
96 0 : int rc = pcmk_rc_ok;
97 0 : int start = 0;
98 0 : int end = 0;
99 0 : int code = 0;
100 :
101 0 : bool quiet_orig = out->quiet;
102 0 : const char *name = NULL;
103 0 : const char *desc = NULL;
104 :
105 0 : rc = pcmk__result_bounds(type, &start, &end);
106 0 : if (rc != pcmk_rc_ok) {
107 0 : out->err(out,
108 : "Failed to get result code bounds for result code type "
109 : "%#010x" PRIx32, (uint32_t) type);
110 0 : return rc;
111 : }
112 :
113 0 : code = start;
114 0 : while (code <= end) {
115 0 : int local_rc = pcmk_rc_ok;
116 :
117 0 : if (code == (pcmk_rc_error + 1)) {
118 : /* Values between pcmk_rc_error and pcmk_rc_ok are reserved for
119 : * callers, so skip them
120 : */
121 0 : code = pcmk_rc_ok;
122 0 : continue;
123 : }
124 :
125 : // Shouldn't affect the return code of the whole list operation
126 0 : local_rc = pcmk_result_get_strings(code, type, &name, &desc);
127 :
128 0 : if ((local_rc != pcmk_rc_ok) || (name == NULL)
129 0 : || pcmk__str_any_of(name, "Unknown", "CRM_EX_UNKNOWN", NULL)) {
130 :
131 0 : code++;
132 0 : continue;
133 : }
134 :
135 : // out->quiet controls whether the code is shown (if quiet is supported)
136 0 : out->quiet = !pcmk_is_set(flags, pcmk_rc_disp_code);
137 :
138 0 : out->message(out, "result-code", code,
139 0 : pcmk_is_set(flags, pcmk_rc_disp_name)? name : NULL,
140 0 : pcmk_is_set(flags, pcmk_rc_disp_desc)? desc : NULL);
141 0 : out->quiet = quiet_orig;
142 :
143 0 : code++;
144 : }
145 :
146 0 : return rc;
147 : }
148 :
149 : // Documented in header
150 : int
151 0 : pcmk_list_result_codes(xmlNodePtr *xml, enum pcmk_result_type type,
152 : uint32_t flags)
153 : {
154 0 : pcmk__output_t *out = NULL;
155 0 : int rc = pcmk_rc_ok;
156 :
157 0 : rc = pcmk__xml_output_new(&out, xml);
158 0 : if (rc != pcmk_rc_ok) {
159 0 : return rc;
160 : }
161 :
162 0 : pcmk__register_lib_messages(out);
163 :
164 0 : rc = pcmk__list_result_codes(out, type, flags);
165 0 : pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml);
166 0 : return rc;
167 : }
|