summaryrefslogtreecommitdiffstats
path: root/tools/iminternal.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/iminternal.c')
-rw-r--r--tools/iminternal.c182
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;
+}