root/include/crm/common/xml_internal.h

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

INCLUDED FROM


   1 /*
   2  * Copyright 2017 Jan Pokorny <jpokorny@redhat.com>
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) any later version.
   8  *
   9  * This software is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 #ifndef CRM_COMMON_XML_INTERNAL__H
  19 #  define CRM_COMMON_XML_INTERNAL__H
  20 
  21 /*
  22  * Internal-only wrappers for and extensions to libxml2 (libxslt)
  23  */
  24 
  25 #  include <stdlib.h>
  26 #  include <stdio.h>
  27 #  include <string.h>
  28 
  29 #  include <crm/crm.h>  /* transitively imports qblog.h */
  30 
  31 
  32 /*!
  33  * \brief Base for directing lib{xml2,xslt} log into standard libqb backend
  34  *
  35  * This macro implements the core of what can be needed for directing
  36  * libxml2 or libxslt error messaging into standard, preconfigured
  37  * libqb-backed log stream.
  38  *
  39  * It's a bit unfortunate that libxml2 (and more sparsely, also libxslt)
  40  * emits a single message by chunks (location is emitted separatedly from
  41  * the message itself), so we have to take the effort to combine these
  42  * chunks back to single message.  Whether to do this or not is driven
  43  * with \p dechunk toggle.
  44  *
  45  * The form of a macro was chosen for implicit deriving of __FILE__, etc.
  46  * and also because static dechunking buffer should be differentiated per
  47  * library (here we assume different functions referring to this macro
  48  * will not ever be using both at once), preferably also per-library
  49  * context of use to avoid clashes altogether.
  50  *
  51  * Note that we cannot use qb_logt, because callsite data have to be known
  52  * at the moment of compilation, which it is not always the case -- xml_log
  53  * (and unfortunately there's no clear explanation of the fail to compile).
  54  *
  55  * Also note that there's no explicit guard against said libraries producing
  56  * never-newline-terminated chunks (which would just keep consuming memory),
  57  * as it's quite improbable.  Termination of the program in between the
  58  * same-message chunks will raise a flag with valgrind and the likes, though.
  59  *
  60  * \param[in] priority Syslog priority for the message to be logged
  61  * \param[in] dechunk  Whether to dechunk new-line terminated message
  62  * \param[in] postemit Code to be executed once message is sent out
  63  * \param[in] prefix   How to prefix the message or NULL for raw passing
  64  * \param[in] fmt      Format string as with printf-like functions
  65  * \param[in] ap       Variable argument list to supplement \p fmt format string
  66  */
  67 #define CRM_XML_LOG_BASE(priority, dechunk, postemit, prefix, fmt, ap)          \
  68 do {                                                                            \
  69     if (!(dechunk) && (prefix) == NULL) {  /* quick pass */                     \
  70         qb_log_from_external_source_va(__FUNCTION__, __FILE__, (fmt),           \
  71                                        (priority), __LINE__, 0, (ap));          \
  72         (void) (postemit);                                                      \
  73     } else {                                                                    \
  74         int CXLB_len = 0;                                                       \
  75         char *CXLB_buf = NULL;                                                  \
  76         static int CXLB_buffer_len = 0;                                         \
  77         static char *CXLB_buffer = NULL;                                        \
  78                                                                                 \
  79         CXLB_len = vasprintf(&CXLB_buf, (fmt), (ap));                           \
  80                                                                                 \
  81         if (CXLB_len <= 0 || CXLB_buf[CXLB_len - 1] == '\n' || !(dechunk)) {    \
  82             if (CXLB_len < 0) {                                                 \
  83                 CXLB_buf = (char *) "LOG CORRUPTION HAZARD"; /*we don't modify*/\
  84             } else if (CXLB_len > 0 /* && (dechunk) */                          \
  85                        && CXLB_buf[CXLB_len - 1] == '\n') {                     \
  86                 CXLB_buf[CXLB_len - 1] = '\0';                                  \
  87             }                                                                   \
  88             if (CXLB_buffer) {                                                  \
  89                 qb_log_from_external_source(__FUNCTION__, __FILE__, "%s%s%s",   \
  90                                             (priority), __LINE__, 0,            \
  91                                             (prefix) != NULL ? (prefix) : "",   \
  92                                             CXLB_buffer, CXLB_buf);             \
  93                 free(CXLB_buffer);                                              \
  94             } else {                                                            \
  95                 qb_log_from_external_source(__FUNCTION__, __FILE__, "%s%s",     \
  96                                             (priority), __LINE__, 0,            \
  97                                             (prefix) != NULL ? (prefix) : "",   \
  98                                             CXLB_buf);                          \
  99             }                                                                   \
 100             if (CXLB_len < 0) {                                                 \
 101                 CXLB_buf = NULL;  /* restore temporary override */              \
 102             }                                                                   \
 103             CXLB_buffer = NULL;                                                 \
 104             CXLB_buffer_len = 0;                                                \
 105             (void) (postemit);                                                  \
 106                                                                                 \
 107         } else if (CXLB_buffer == NULL) {                                       \
 108             CXLB_buffer_len = CXLB_len;                                         \
 109             CXLB_buffer = CXLB_buf;                                             \
 110             CXLB_buf = NULL;                                                    \
 111                                                                                 \
 112         } else {                                                                \
 113             CXLB_buffer = realloc(CXLB_buffer, 1 + CXLB_buffer_len + CXLB_len); \
 114             memcpy(CXLB_buffer + CXLB_buffer_len, CXLB_buf, CXLB_len);          \
 115             CXLB_buffer_len += CXLB_len;                                        \
 116             CXLB_buffer[CXLB_buffer_len] = '\0';                                \
 117         }                                                                       \
 118         free(CXLB_buf);                                                         \
 119     }                                                                           \
 120 } while (0)
 121 
 122 #endif

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