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. pcmk__mk_log_output

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

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