mirror of
https://github.com/rsyslog/rsyslog.git
synced 2025-12-07 11:10:41 +01:00
This commit applies the new canonical formatting style using `clang-format` with custom settings (notably 4-space indentation), as part of our shift toward automated formatting normalization. ⚠️ No functional changes are included — only whitespace and layout modifications as produced by `clang-format`. This change is part of the formatting modernization strategy discussed in: https://github.com/rsyslog/rsyslog/issues/5747 Key context: - Formatting is now treated as a disposable view, normalized via tooling. - The `.clang-format` file defines the canonical style. - A fixup script (`devtools/format-code.sh`) handles remaining edge cases. - Formatting commits are added to `.git-blame-ignore-revs` to reduce noise. - Developers remain free to format code however they prefer locally.
276 lines
7.3 KiB
C
276 lines
7.3 KiB
C
/* This is the output channel processing code of rsyslog.
|
|
* Output channels - in the long term - will define how
|
|
* messages will be sent to whatever file or other medium.
|
|
* Currently, they mainly provide a way to store some file-related
|
|
* information (most importantly the maximum file size allowed).
|
|
* Please see syslogd.c for license information.
|
|
* begun 2005-06-21 rgerhards
|
|
*
|
|
* Copyright (C) 2005-2016 Adiscon GmbH
|
|
*
|
|
* This file is part of rsyslog.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
* -or-
|
|
* see COPYING.ASL20 in the source distribution
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "config.h"
|
|
|
|
#include "rsyslog.h"
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <assert.h>
|
|
#include "stringbuf.h"
|
|
#include "outchannel.h"
|
|
#include "rsconf.h"
|
|
#include "debug.h"
|
|
|
|
/* Constructs a outchannel list object. Returns pointer to it
|
|
* or NULL (if it fails).
|
|
*/
|
|
struct outchannel *ochConstruct(void) {
|
|
struct outchannel *pOch;
|
|
if ((pOch = calloc(1, sizeof(struct outchannel))) == NULL) return NULL;
|
|
|
|
/* basic initialisaion is done via calloc() - need to
|
|
* initialize only values != 0. */
|
|
|
|
if (loadConf->och.ochLast == NULL) { /* we are the first element! */
|
|
loadConf->och.ochRoot = loadConf->och.ochLast = pOch;
|
|
} else {
|
|
loadConf->och.ochLast->pNext = pOch;
|
|
loadConf->och.ochLast = pOch;
|
|
}
|
|
|
|
return (pOch);
|
|
}
|
|
|
|
|
|
/* skips the next comma and any whitespace
|
|
* in front and after it.
|
|
*/
|
|
static void skip_Comma(uchar **pp) {
|
|
register uchar *p;
|
|
|
|
assert(pp != NULL);
|
|
assert(*pp != NULL);
|
|
|
|
p = *pp;
|
|
while (isspace(*p)) ++p;
|
|
if (*p == ',') ++p;
|
|
while (isspace(*p)) ++p;
|
|
*pp = p;
|
|
}
|
|
|
|
/* helper to ochAddLine. Parses a comma-delimited field
|
|
* The field is delimited by SP or comma. Leading whitespace
|
|
* is "eaten" and does not become part of the field content.
|
|
*/
|
|
static rsRetVal get_Field(uchar **pp, uchar **pField) {
|
|
DEFiRet;
|
|
register uchar *p;
|
|
cstr_t *pStrB = NULL;
|
|
|
|
assert(pp != NULL);
|
|
assert(*pp != NULL);
|
|
assert(pField != NULL);
|
|
|
|
skip_Comma(pp);
|
|
p = *pp;
|
|
|
|
CHKiRet(cstrConstruct(&pStrB));
|
|
|
|
/* copy the field */
|
|
while (*p && *p != ' ' && *p != ',') {
|
|
CHKiRet(cstrAppendChar(pStrB, *p++));
|
|
}
|
|
|
|
*pp = p;
|
|
cstrFinalize(pStrB);
|
|
CHKiRet(cstrConvSzStrAndDestruct(&pStrB, pField, 0));
|
|
|
|
finalize_it:
|
|
if (iRet != RS_RET_OK) {
|
|
if (pStrB != NULL) cstrDestruct(&pStrB);
|
|
}
|
|
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
/* helper to ochAddLine. Parses a off_t type from the
|
|
* input line.
|
|
* returns: 0 - ok, 1 - failure
|
|
*/
|
|
static int get_off_t(uchar **pp, off_t *pOff_t) {
|
|
register uchar *p;
|
|
off_t val;
|
|
|
|
assert(pp != NULL);
|
|
assert(*pp != NULL);
|
|
assert(pOff_t != NULL);
|
|
|
|
skip_Comma(pp);
|
|
p = *pp;
|
|
|
|
val = 0;
|
|
while (*p && isdigit((int)*p)) {
|
|
val = val * 10 + (*p - '0');
|
|
++p;
|
|
}
|
|
|
|
*pp = p;
|
|
*pOff_t = val;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* helper to ochAddLine. Parses everything from the
|
|
* current position to the end of line and returns it
|
|
* to the caller. Leading white space is removed, but
|
|
* not trailing.
|
|
*/
|
|
static rsRetVal get_restOfLine(uchar **pp, uchar **pBuf) {
|
|
DEFiRet;
|
|
register uchar *p;
|
|
cstr_t *pStrB = NULL;
|
|
|
|
assert(pp != NULL);
|
|
assert(*pp != NULL);
|
|
assert(pBuf != NULL);
|
|
|
|
skip_Comma(pp);
|
|
p = *pp;
|
|
|
|
CHKiRet(cstrConstruct(&pStrB));
|
|
|
|
/* copy the field */
|
|
while (*p) {
|
|
CHKiRet(cstrAppendChar(pStrB, *p++));
|
|
}
|
|
|
|
*pp = p;
|
|
cstrFinalize(pStrB);
|
|
CHKiRet(cstrConvSzStrAndDestruct(&pStrB, pBuf, 0));
|
|
|
|
finalize_it:
|
|
if (iRet != RS_RET_OK) {
|
|
if (pStrB != NULL) cstrDestruct(&pStrB);
|
|
}
|
|
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
/* Add a new outchannel line
|
|
* returns pointer to new object if it succeeds, NULL otherwise.
|
|
* An outchannel line is primarily a set of fields delemited by commas.
|
|
* There might be some whitespace between the field (but not within)
|
|
* and the commas. This can be removed.
|
|
*/
|
|
struct outchannel *ochAddLine(char *pName, uchar **ppRestOfConfLine) {
|
|
struct outchannel *pOch;
|
|
uchar *p;
|
|
|
|
assert(pName != NULL);
|
|
assert(ppRestOfConfLine != NULL);
|
|
|
|
if ((pOch = ochConstruct()) == NULL) return NULL;
|
|
|
|
pOch->iLenName = strlen(pName);
|
|
pOch->pszName = (char *)malloc(pOch->iLenName + 1);
|
|
if (pOch->pszName == NULL) {
|
|
dbgprintf("ochAddLine could not alloc memory for outchannel name!");
|
|
pOch->iLenName = 0;
|
|
return NULL;
|
|
/* I know - we create a memory leak here - but I deem
|
|
* it acceptable as it is a) a very small leak b) very
|
|
* unlikely to happen. rgerhards 2004-11-17
|
|
*/
|
|
}
|
|
memcpy(pOch->pszName, pName, pOch->iLenName + 1);
|
|
|
|
/* now actually parse the line */
|
|
p = *ppRestOfConfLine;
|
|
assert(p != NULL);
|
|
|
|
/* get params */
|
|
get_Field(&p, &pOch->pszFileTemplate);
|
|
if (*p) get_off_t(&p, &pOch->uSizeLimit);
|
|
if (*p) get_restOfLine(&p, &pOch->cmdOnSizeLimit);
|
|
|
|
*ppRestOfConfLine = p;
|
|
return (pOch);
|
|
}
|
|
|
|
|
|
/* Find a outchannel object based on name. Search
|
|
* currently is case-sensitive (should we change?).
|
|
* returns pointer to outchannel object if found and
|
|
* NULL otherwise.
|
|
* rgerhards 2004-11-17
|
|
*/
|
|
struct outchannel *ochFind(char *pName, int iLenName) {
|
|
struct outchannel *pOch;
|
|
|
|
assert(pName != NULL);
|
|
|
|
pOch = loadConf->och.ochRoot;
|
|
while (pOch != NULL && !(pOch->iLenName == iLenName && !strcmp(pOch->pszName, pName))) {
|
|
pOch = pOch->pNext;
|
|
}
|
|
return (pOch);
|
|
}
|
|
|
|
/* Destroy the outchannel structure. This is for de-initialization
|
|
* at program end. Everything is deleted.
|
|
* rgerhards 2005-02-22
|
|
*/
|
|
void ochDeleteAll(void) {
|
|
struct outchannel *pOch, *pOchDel;
|
|
|
|
pOch = runConf->och.ochRoot;
|
|
while (pOch != NULL) {
|
|
dbgprintf("Delete Outchannel: Name='%s'\n ", pOch->pszName == NULL ? "NULL" : pOch->pszName);
|
|
pOchDel = pOch;
|
|
pOch = pOch->pNext;
|
|
if (pOchDel->pszName != NULL) free(pOchDel->pszName);
|
|
if (pOchDel->pszFileTemplate != NULL) free(pOchDel->pszFileTemplate);
|
|
if (pOchDel->cmdOnSizeLimit != NULL) free(pOchDel->cmdOnSizeLimit);
|
|
free(pOchDel);
|
|
}
|
|
}
|
|
|
|
|
|
/* Print the outchannel structure. This is more or less a
|
|
* debug or test aid, but anyhow I think it's worth it...
|
|
*/
|
|
void ochPrintList(rsconf_t *cnf) {
|
|
struct outchannel *pOch;
|
|
|
|
pOch = cnf->och.ochRoot;
|
|
while (pOch != NULL) {
|
|
dbgprintf("Outchannel: Name='%s'\n", pOch->pszName == NULL ? "NULL" : pOch->pszName);
|
|
dbgprintf("\tFile Template: '%s'\n", pOch->pszFileTemplate == NULL ? "NULL" : (char *)pOch->pszFileTemplate);
|
|
dbgprintf("\tMax Size.....: %lu\n", (long unsigned)pOch->uSizeLimit);
|
|
dbgprintf("\tOnSizeLimtCmd: '%s'\n", pOch->cmdOnSizeLimit == NULL ? "NULL" : (char *)pOch->cmdOnSizeLimit);
|
|
pOch = pOch->pNext; /* done, go next */
|
|
}
|
|
}
|
|
/* vi:set ai:
|
|
*/
|