rsyslog/outchannel.c
Rainer Gerhards b326c76f45 style: normalize C source formatting via clang-format (PoC)
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.
2025-07-16 13:56:21 +02:00

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:
*/