root/lib/common/output_log.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. log_subprocess_output
  2. log_free_priv
  3. log_init
  4. log_finish
  5. log_reset
  6. log_version
  7. G_GNUC_PRINTF
  8. log_output_xml
  9. G_GNUC_PRINTF
  10. G_GNUC_PRINTF
  11. log_end_list
  12. G_GNUC_PRINTF
  13. log_is_quiet
  14. log_spacer
  15. log_progress
  16. log_prompt
  17. pcmk__mk_log_output
  18. pcmk__output_set_log_level

   1 /*
   2  * Copyright 2019-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 <ctype.h>
  13 #include <stdarg.h>
  14 #include <stdlib.h>
  15 #include <stdio.h>
  16 
  17 GOptionEntry pcmk__log_output_entries[] = {
  18     { NULL }
  19 };
  20 
  21 typedef struct private_data_s {
  22     /* gathered in log_begin_list */
  23     GQueue/*<char*>*/ *prefixes;
  24     int log_level;
  25 } private_data_t;
  26 
  27 static void
  28 log_subprocess_output(pcmk__output_t *out, int exit_status,
     /* [previous][next][first][last][top][bottom][index][help] */
  29                       const char *proc_stdout, const char *proc_stderr) {
  30     /* This function intentionally left blank */
  31 }
  32 
  33 static void
  34 log_free_priv(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
  35     private_data_t *priv = out->priv;
  36 
  37     if (priv == NULL) {
  38         return;
  39     }
  40 
  41     g_queue_free(priv->prefixes);
  42     free(priv);
  43     out->priv = NULL;
  44 }
  45 
  46 static bool
  47 log_init(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
  48     private_data_t *priv = NULL;
  49 
  50     /* If log_init was previously called on this output struct, just return. */
  51     if (out->priv != NULL) {
  52         return true;
  53     }
  54 
  55     out->priv = calloc(1, sizeof(private_data_t));
  56     if (out->priv == NULL) {
  57          return false;
  58     }
  59 
  60     priv = out->priv;
  61 
  62     priv->prefixes = g_queue_new();
  63     priv->log_level = LOG_INFO;
  64 
  65     return true;
  66 }
  67 
  68 static void
  69 log_finish(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest) {
     /* [previous][next][first][last][top][bottom][index][help] */
  70     /* This function intentionally left blank */
  71 }
  72 
  73 static void
  74 log_reset(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
  75     CRM_ASSERT(out != NULL);
  76 
  77     out->dest = freopen(NULL, "w", out->dest);
  78     CRM_ASSERT(out->dest != NULL);
  79 
  80     log_free_priv(out);
  81     log_init(out);
  82 }
  83 
  84 static void
  85 log_version(pcmk__output_t *out, bool extended) {
     /* [previous][next][first][last][top][bottom][index][help] */
  86     private_data_t *priv = NULL;
  87 
  88     CRM_ASSERT(out != NULL && out->priv != NULL);
  89     priv = out->priv;
  90 
  91     if (extended) {
  92         do_crm_log(priv->log_level, "Pacemaker %s (Build: %s): %s",
  93                    PACEMAKER_VERSION, BUILD_VERSION, CRM_FEATURES);
  94     } else {
  95         do_crm_log(priv->log_level, "Pacemaker %s", PACEMAKER_VERSION);
  96         do_crm_log(priv->log_level, "Written by Andrew Beekhof and"
  97                                     "the Pacemaker project contributors");
  98     }
  99 }
 100 
 101 G_GNUC_PRINTF(2, 3)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 static void
 103 log_err(pcmk__output_t *out, const char *format, ...) {
 104     va_list ap;
 105     char* buffer = NULL;
 106     int len = 0;
 107 
 108     CRM_ASSERT(out != NULL);
 109 
 110     va_start(ap, format);
 111     /* Informational output does not get indented, to separate it from other
 112      * potentially indented list output.
 113      */
 114     len = vasprintf(&buffer, format, ap);
 115     CRM_ASSERT(len >= 0);
 116     va_end(ap);
 117 
 118     crm_err("%s", buffer);
 119 
 120     free(buffer);
 121 }
 122 
 123 static void
 124 log_output_xml(pcmk__output_t *out, const char *name, const char *buf) {
     /* [previous][next][first][last][top][bottom][index][help] */
 125     xmlNodePtr node = NULL;
 126     private_data_t *priv = NULL;
 127 
 128     CRM_ASSERT(out != NULL && out->priv != NULL);
 129     priv = out->priv;
 130 
 131     node = create_xml_node(NULL, name);
 132     xmlNodeSetContent(node, (pcmkXmlStr) buf);
 133     do_crm_log_xml(priv->log_level, name, node);
 134     free(node);
 135 }
 136 
 137 G_GNUC_PRINTF(4, 5)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 static void
 139 log_begin_list(pcmk__output_t *out, const char *singular_noun, const char *plural_noun,
 140                const char *format, ...) {
 141     int len = 0;
 142     va_list ap;
 143     char* buffer = NULL;
 144     private_data_t *priv = NULL;
 145 
 146     CRM_ASSERT(out != NULL && out->priv != NULL);
 147     priv = out->priv;
 148 
 149     va_start(ap, format);
 150     len = vasprintf(&buffer, format, ap);
 151     CRM_ASSERT(len >= 0);
 152     va_end(ap);
 153 
 154     /* Don't skip empty prefixes,
 155      * otherwise there will be mismatch
 156      * in the log_end_list */
 157     if(strcmp(buffer, "") == 0) {
 158         /* nothing */
 159     }
 160 
 161     g_queue_push_tail(priv->prefixes, buffer);
 162 }
 163 
 164 G_GNUC_PRINTF(3, 4)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 static void
 166 log_list_item(pcmk__output_t *out, const char *name, const char *format, ...) {
 167     int len = 0;
 168     va_list ap;
 169     private_data_t *priv = NULL;
 170     char prefix[LINE_MAX] = { 0 };
 171     int offset = 0;
 172     char* buffer = NULL;
 173 
 174     CRM_ASSERT(out != NULL && out->priv != NULL);
 175     priv = out->priv;
 176 
 177     for (GList* gIter = priv->prefixes->head; gIter; gIter = gIter->next) {
 178         if (strcmp(prefix, "") != 0) {
 179             offset += snprintf(prefix + offset, LINE_MAX - offset, ": %s", (char *)gIter->data);
 180         } else {
 181             offset = snprintf(prefix, LINE_MAX, "%s", (char *)gIter->data);
 182         }
 183     }
 184 
 185     va_start(ap, format);
 186     len = vasprintf(&buffer, format, ap);
 187     CRM_ASSERT(len >= 0);
 188     va_end(ap);
 189 
 190     if (strcmp(buffer, "") != 0) { /* We don't want empty messages */
 191         if ((name != NULL) && (strcmp(name, "") != 0)) {
 192             if (strcmp(prefix, "") != 0) {
 193                 do_crm_log(priv->log_level, "%s: %s: %s", prefix, name, buffer);
 194             } else {
 195                 do_crm_log(priv->log_level, "%s: %s", name, buffer);
 196             }
 197         } else {
 198             if (strcmp(prefix, "") != 0) {
 199                 do_crm_log(priv->log_level, "%s: %s", prefix, buffer);
 200             } else {
 201                 do_crm_log(priv->log_level, "%s", buffer);
 202             }
 203         }
 204     }
 205     free(buffer);
 206 }
 207 
 208 static void
 209 log_end_list(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
 210     private_data_t *priv = NULL;
 211 
 212     CRM_ASSERT(out != NULL && out->priv != NULL);
 213     priv = out->priv;
 214 
 215     if (priv->prefixes == NULL) {
 216       return;
 217     }
 218     CRM_ASSERT(priv->prefixes->tail != NULL);
 219 
 220     free((char *)priv->prefixes->tail->data);
 221     g_queue_pop_tail(priv->prefixes);
 222 }
 223 
 224 G_GNUC_PRINTF(2, 3)
     /* [previous][next][first][last][top][bottom][index][help] */
 225 static int
 226 log_info(pcmk__output_t *out, const char *format, ...) {
 227     private_data_t *priv = NULL;
 228     int len = 0;
 229     va_list ap;
 230     char* buffer = NULL;
 231 
 232     CRM_ASSERT(out != NULL && out->priv != NULL);
 233     priv = out->priv;
 234 
 235     va_start(ap, format);
 236     len = vasprintf(&buffer, format, ap);
 237     CRM_ASSERT(len >= 0);
 238     va_end(ap);
 239 
 240     do_crm_log(priv->log_level, "%s", buffer);
 241 
 242     free(buffer);
 243     return pcmk_rc_ok;
 244 }
 245 
 246 static bool
 247 log_is_quiet(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
 248     return false;
 249 }
 250 
 251 static void
 252 log_spacer(pcmk__output_t *out) {
     /* [previous][next][first][last][top][bottom][index][help] */
 253     /* This function intentionally left blank */
 254 }
 255 
 256 static void
 257 log_progress(pcmk__output_t *out, bool end) {
     /* [previous][next][first][last][top][bottom][index][help] */
 258     /* This function intentionally left blank */
 259 }
 260 
 261 static void
 262 log_prompt(const char *prompt, bool echo, char **dest) {
     /* [previous][next][first][last][top][bottom][index][help] */
 263     /* This function intentionally left blank */
 264 }
 265 
 266 pcmk__output_t *
 267 pcmk__mk_log_output(char **argv) {
     /* [previous][next][first][last][top][bottom][index][help] */
 268     pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t));
 269 
 270     if (retval == NULL) {
 271         return NULL;
 272     }
 273 
 274     retval->fmt_name = "log";
 275     retval->request = argv == NULL ? NULL : g_strjoinv(" ", argv);
 276 
 277     retval->init = log_init;
 278     retval->free_priv = log_free_priv;
 279     retval->finish = log_finish;
 280     retval->reset = log_reset;
 281 
 282     retval->register_message = pcmk__register_message;
 283     retval->message = pcmk__call_message;
 284 
 285     retval->subprocess_output = log_subprocess_output;
 286     retval->version = log_version;
 287     retval->info = log_info;
 288     retval->err = log_err;
 289     retval->output_xml = log_output_xml;
 290 
 291     retval->begin_list = log_begin_list;
 292     retval->list_item = log_list_item;
 293     retval->end_list = log_end_list;
 294 
 295     retval->is_quiet = log_is_quiet;
 296     retval->spacer = log_spacer;
 297     retval->progress = log_progress;
 298     retval->prompt = log_prompt;
 299 
 300     return retval;
 301 }
 302 
 303 void
 304 pcmk__output_set_log_level(pcmk__output_t *out, int log_level) {
     /* [previous][next][first][last][top][bottom][index][help] */
 305     private_data_t *priv = NULL;
 306 
 307     CRM_ASSERT(out != NULL && out->priv != NULL);
 308 
 309     if (!pcmk__str_eq(out->fmt_name, "log", pcmk__str_none)) {
 310         return;
 311     }
 312 
 313     priv = out->priv;
 314     priv->log_level = log_level;
 315 }

/* [previous][next][first][last][top][bottom][index][help] */