diff options
Diffstat (limited to 'outchannel.c')
-rw-r--r-- | outchannel.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/outchannel.c b/outchannel.c new file mode 100644 index 0000000..2f456b5 --- /dev/null +++ b/outchannel.c @@ -0,0 +1,303 @@ +/* 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(char **pp) +{ + register char *p; + + assert(pp != NULL); + assert(*pp != NULL); + + p = *pp; + while(isspace((int)*p)) + ++p; + if(*p == ',') + ++p; + while(isspace((int)*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((char**)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((char**)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((char**)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: + */ |