diff options
Diffstat (limited to 'tools/iminternal.c')
-rw-r--r-- | tools/iminternal.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/tools/iminternal.c b/tools/iminternal.c new file mode 100644 index 0000000..c4dd548 --- /dev/null +++ b/tools/iminternal.c @@ -0,0 +1,182 @@ +/* iminternal.c + * This file set implements the internal messages input module for rsyslog. + * Note: we currently do not have an input module spec, but + * we will have one in the future. This module needs then to be + * adapted. + * + * File begun on 2007-08-03 by RGerhards + * + * Copyright 2007-2022 Rainer Gerhards and 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 <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <signal.h> + +#include "syslogd.h" +#include "linkedlist.h" +#include "iminternal.h" +#include "unicode-helper.h" + +static linkedList_t llMsgs; +static pthread_mutex_t mutList = PTHREAD_MUTEX_INITIALIZER; + + +/* destructs an iminternal object + */ +static rsRetVal iminternalDestruct(iminternal_t *pThis) +{ + DEFiRet; + + if(pThis->pMsg != NULL) + msgDestruct(&pThis->pMsg); + + free(pThis); + + RETiRet; +} + + +/* Construct an iminternal object + */ +static rsRetVal iminternalConstruct(iminternal_t **ppThis) +{ + DEFiRet; + if((*ppThis = (iminternal_t*) calloc(1, sizeof(iminternal_t))) == NULL) { + iRet = RS_RET_OUT_OF_MEMORY; + } + RETiRet; +} + + +/* add a message to the linked list + * Note: the pMsg reference counter is not incremented. Consequently, + * the caller must NOT decrement it. The caller actually hands over + * full ownership of the pMsg object. + */ +rsRetVal iminternalAddMsg(smsg_t *pMsg) +{ + DEFiRet; + iminternal_t *pThis = NULL; + struct timespec to; + int r; + int is_locked = 0; + + /* we guard against deadlock, so we can guarantee rsyslog will never + * block due to internal messages. The 1 second timeout should be + * sufficient under all circumstances. + */ + to.tv_sec = time(NULL) + 1; + to.tv_nsec = 0; + #if !defined(__APPLE__) + r = pthread_mutex_timedlock(&mutList, &to); + #else + r = pthread_mutex_trylock(&mutList); // must check + #endif + if(r != 0) { + dbgprintf("iminternalAddMsg: timedlock for mutex failed with %d, msg %s\n", + r, getMSG(pMsg)); + /* the message is lost, nothing we can do against this! */ + msgDestruct(&pMsg); + ABORT_FINALIZE(RS_RET_ERR); + } + is_locked = 1; + CHKiRet(iminternalConstruct(&pThis)); + pThis->pMsg = pMsg; + CHKiRet(llAppend(&llMsgs, NULL, (void*) pThis)); + + if(PREFER_FETCH_32BIT(bHaveMainQueue)) { + DBGPRINTF("signaling new internal message via SIGTTOU: '%s'\n", + pThis->pMsg->pszRawMsg); + kill(glblGetOurPid(), SIGTTOU); + } + +finalize_it: + if(is_locked) { + pthread_mutex_unlock(&mutList); + } + if(iRet != RS_RET_OK) { + dbgprintf("iminternalAddMsg() error %d - can not otherwise report this error, message lost\n", iRet); + if(pThis != NULL) + iminternalDestruct(pThis); + } + + RETiRet; +} + + +/* pull the first error message from the linked list, remove it + * from the list and return it to the caller. The caller is + * responsible for freeing the message! + */ +rsRetVal iminternalRemoveMsg(smsg_t **ppMsg) +{ + DEFiRet; + iminternal_t *pThis; + linkedListCookie_t llCookie = NULL; + + pthread_mutex_lock(&mutList); + CHKiRet(llGetNextElt(&llMsgs, &llCookie, (void*)&pThis)); + if(!strcmp((char*)pThis->pMsg->pszHOSTNAME, "[localhost]")) { + /* early (pre-conf) startup message detected, need to set real hostname now */ + MsgSetHOSTNAME(pThis->pMsg, glblGetLocalHostName(), ustrlen(glblGetLocalHostName())); + } + *ppMsg = pThis->pMsg; + pThis->pMsg = NULL; /* we do no longer own it - important for destructor */ + + if(llDestroyRootElt(&llMsgs) != RS_RET_OK) { + dbgprintf("Root element of iminternal linked list could not be destroyed - there is " + "nothing we can do against it, we ignore it for now. Things may go wild " + "from here on. This is most probably a program logic error.\n"); + } + +finalize_it: + pthread_mutex_unlock(&mutList); + RETiRet; +} + + +/* initialize the iminternal subsystem + * must be called once at the start of the program + */ +rsRetVal modInitIminternal(void) +{ + DEFiRet; + iRet = llInit(&llMsgs, iminternalDestruct, NULL, NULL); + RETiRet; +} + + +/* de-initialize the iminternal subsystem + * must be called once at the end of the program + * Note: the error list must have been pulled first. We do + * NOT care if there are any errors left - we simply destroy + * them. + */ +rsRetVal modExitIminternal(void) +{ + DEFiRet; + iRet = llDestroy(&llMsgs); + RETiRet; +} |