summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xliblogging-stub.h310
-rw-r--r--syslogd.c206
-rw-r--r--template.c6
-rw-r--r--template.h4
4 files changed, 423 insertions, 103 deletions
diff --git a/liblogging-stub.h b/liblogging-stub.h
new file mode 100755
index 00000000..f618a967
--- /dev/null
+++ b/liblogging-stub.h
@@ -0,0 +1,310 @@
+/*! \file liblogging.h
+ * \brief global objects and defines
+ *
+ * THIS IS A STUB MODULE TAKEN FROM LIBLOGGING. It will be replaced
+ * once liblogging is fully integrated in rsyslog. rgerhards 2004-11-17.
+ *
+ * Include this header in your application!
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-08-04
+ * 0.1 version created.
+ *
+ * Copyright 2002-2003
+ * Rainer Gerhards and Adiscon GmbH. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Adiscon GmbH or Rainer Gerhards
+ * nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __LIB3195_LIBLOGGING_H_INCLUDED__
+#define __LIB3195_LIBLOGGING_H_INCLUDED__ 1
+#include <stdio.h> /* debug only */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum srRetVal_ /** return value. All methods return this if not specified otherwise */
+{
+ SR_RET_ERR = -1, /**< error occured, call error handler for details */
+ SR_RET_REMAIN_WIN_TOO_SMALL = -2, /**< can't send, because not enough octets left in RFC3081 window --> wait for SEQ */
+ SR_RET_INVALID_HANDLE = -3, /**< caller provided an invalid handle, e.g. NULL pointer or pointer to wrong object.
+ * This is only checked on the API layer. Internally, all functions check this via
+ * assert(), so protection is only available during debugging. This is a performance
+ * decision.
+ */
+ SR_RET_INVALID_DESTRUCTOR = -4, /**< used, when the caller must provide a pointer to a destructor function but does not */
+ SR_RET_NOT_FOUND = - 5, /**< a requested element was not found. May not be an error depending on what operation was
+ ** to be carried out... */
+ SR_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */
+ SR_RET_XML_INVALID_PARAMTAG = -7, /**< malformed tag parameter, most probably quotes are missing before value or intervening space */
+ SR_RET_XML_INVALID_TERMINATOR = -8, /**< missing terminator sequence, e.g. a "param='no_terminator" - notice the missing closing quote */
+ SR_RET_XML_MALFORMED = -9, /**< the XML is malformed (no specific reason given) */
+ SR_RET_MISSING_CLOSE_BRACE = -10, /**< closing brace in <tag /> missing */
+ SR_RET_XML_MISSING_CLOSETAG = -11, /**< close tag is missing or syntax invalid <tag>...</closetag> */
+ SR_RET_XML_MISSING_OPENTAG = -12, /**< open tag is missing, e.g <tag />othertag> */
+ SR_RET_XML_TAG_MISMATCH = -13, /**< start and close tag name do not match (<tag>...</othertag>) */
+ SR_RET_XML_INVALID_CDATA_HDR = -14, /**< invalid start of CDATA, e.g. <![CDTA... */
+ SR_RET_XML_INVALID_CDATA_TRAIL = -14, /**< invalid CDATA trailer, , e.g. "<![CDATA[test]>" (one ] missing) */
+ SR_RET_PEER_NONOK_RESPONSE = -15, /**< was waiting for a BEEP peer to respond "ok", but received other response */
+ SR_RET_PEER_INVALID_PROFILE = -16, /**< BEEP Peer did either not support the profile or did not return the correct on in response to a start message */
+ SR_RET_PEER_NO_URI = -17, /**< BEEP peer did not inclulde a mandatory URI element in its xml response */
+ SR_RET_PEER_NO_PROFILE = -18,/**< BEEP peer did not include a mandatory PROFILE element in its XML reponse */
+ SR_RET_PEER_NO_GREETING = -19, /**< BEEP peer did not send a (correctly formatted) greeting message */
+ SR_RET_PEER_DOESNT_SUPPORT_PROFILE = -20, /**< the reqeusted profile is not part of the peers profile set (from greeting message) */
+ SR_RET_INVALID_FRAME_STATE = -21, /**< a frame object has an invalid frame state (pFram->iState) */
+ SR_RET_PROFILE_ALREADY_SET = -22, /**< a profile should be assgined to a channel which already has one */
+ SR_RET_INVALID_CHAN_STATE = -23, /**< a channel object has an invalid or unexpected (at this point) channel state */
+ SR_RET_INVALID_GREETING = -24, /**< greeting message is (somehow) invalid, e.g. does not start with RPY) */
+ SR_RET_INVALID_CHAN0_MESG = -25, /**< channel 0 received an invalid or out-of-sequence message */
+ SR_RET_START_MISSING_NUMBER = -26, /**< a start message is missing the "number=" parameter */
+ SR_RET_START_INVALID_NUMBER = -27, /**< a start message's "number=" parameter specifies an invalid number */
+ SR_RET_START_EXISTING_NUMBER = -28, /**< a start message's "number=" parameter specifies a channel number which already exisits! */
+ SR_RET_NO_VALUE = -29, /**< a linked list was asked to provide an uValue, but there was none. Not necessarily an error, depends on caller's needs. */
+ SR_RET_START_EVEN_NUMBER = -30, /**< an initiator sent a even-numbered start number, which is invalid as of rfc 3080 2.3.1.2 */
+ SR_RET_NO_PROFILE_RQSTD = -31, /**< no profile at all was requested in a start message (may be caused by invalid format) */
+ SR_RET_WARNING_START_NO_PROFMATCH = -32,/**< WARNING only (no error) - during a start, no matching profile was found and the beep peer has been sent such an ERR frame */
+ SR_RET_ERR_EVENT_HANDLER_MISSING = -33,/**< a required (profile) event handler is missing */
+ SR_RET_ACKNO_ZERO = -34, /**< caller-provided ackno is zero. This can not be by design. */
+ SR_RET_CHAN_DOESNT_EXIST = -35, /**< a chanel specified does not exist */
+ SR_RET_ALREADY_LISTENING = -36, /**< caller tried to start an listener on the API object, but it is already one running */
+ SR_RET_INVALID_OPTVAL = -37, /**< invalid option value was provided to srAPISetOption() (param 2) */
+ SR_RET_INVALID_LIB_OPTION = -38, /**< invalid option was provided to srAPISetOption() (param 1) */
+ SR_RET_NULL_POINTER_PROVIDED = -39, /**< the caller has provided a NULL-Pointer where none were expected/allowed */
+ SR_RET_PROPERTY_NOT_AVAILABLE = -40,/**< a property asked for is not available, e.g. the TIMESTAMP in a not-wellformed message */
+ SR_RET_UNSUPPORTED_FORMAT = -41, /**< a non-supported format was requested by the caller */
+ SR_RET_UNALLOCATABLE_BUFFER = -42, /**< the operation can not be completed because a buffer that is under user control would need to be deallocated */
+ SR_RET_PRIO_OUT_OF_RANGE = -43, /**< a priority value is outside the allowed range */
+ SR_RET_FACIL_OUT_OF_RANGE = -44, /**< a facility value is outside the allowed range */
+ SR_RET_INVALID_TAG = -45, /**< a syslog TAG value (string) provided was invalid, e.g. over 32 chars or included invalid chars */
+ SR_RET_NULL_MSG_PROVIDED = -46, /**< caller provided a NULL pointer where a pointer to a MSG was expected */
+ SR_RET_ERR_RECEIVE = -47, /**< an error occured during message receive. no more detail is available */
+ SR_RET_UNEXPECTED_HDRCMD = -48, /**< an invalid HDR Command was received (e.g. an "MSG" in response to another "MSG") */
+ SR_RET_PEER_INDICATED_ERROR = -49, /**< the PEER send an error response */
+ SR_RET_PROVIDED_BUFFER_TOO_SMALL = -50,/**< the caller provided a buffer, but the called function sees the size of this buffer is too small - operation not carried out */
+ SR_RET_INVALID_PARAM = -51, /**< an invalid parameter was provided to a method */
+
+ /* socket error codes */
+ SR_RET_SOCKET_ERR = -1001, /**< generic error generated by socket subsystem */
+ SR_RET_CANT_BIND_SOCKET = -1002, /**< socket bind() operation failed */
+ SR_RET_INVALID_SOCKET = -1003, /**< invalid socket */
+ SR_RET_CONNECTION_CLOSED = -1004, /**< the remote peer closed the connection */
+ SR_RET_INVALID_OS_SOCKETS_VERSION = -1005,/**< the operating system socket subsystem version is inappropriate (this error will most probably occur under Win32, only) */
+ SR_RET_CAN_NOT_INIT_SOCKET = -1006, /**< socket() failed for whatever reason... */
+ SR_RET_UXDOMSOCK_CHMOD_ERR = -1007, /**< chmod() failed on Unix Domain Socket */
+
+ /* BEEP frame format & other errors */
+ SR_RET_INVALID_HDRCMD = -2001, /**< invalid HDRCMD (e.g. "MSG", "RPY",...) */
+ SR_RET_INVALID_WAITING_SP_CHAN = -2002, /**< invalid SP before channo */
+ SR_RET_INVALID_CHANNO = -2003, /**< invalid channo */
+ SR_RET_INVALID_WAITING_SP_MSGNO = -2004,/**< now the space before the next header */
+ SR_RET_INVALID_IN_MSGNO = -2005, /**< and the next (numeric) header */
+ SR_RET_INVALID_WAITING_SP_MORE = -2006, /**< now the space before the next header */
+ SR_RET_INVALID_IN_MORE = -2007, /**< and the next (char) header */
+ SR_RET_INVALID_WAITING_SP_SEQNO = -2008,/**< now the space before the next header */
+ SR_RET_INVALID_IN_SEQNO = -2009, /**< and the next (numeric) header */
+ SR_RET_INVALID_WAITING_SP_SIZE = -2010, /**< now the space before the next header */
+ SR_RET_INVALID_IN_SIZE = -2011, /**< and the next (numeric) header */
+ SR_RET_INVALID_WAITING_SP_ANSNO = -2012,/**< now the space before the next header */
+ SR_RET_INVALID_IN_ANSNO = -2013, /**< and the next (numeric) header */
+ SR_RET_INVALID_WAITING_HDRCR = -2014, /**< awaiting the HDR's CR */
+ SR_RET_INVALID_WAITING_HDRLF = -2015, /**< awaiting the HDR's LF */
+ SR_RET_INVALID_IN_PAYLOAD = -2016, /**< reading payload area */
+ SR_RET_INVALID_WAITING_END1 = -2017, /**< waiting for the 1st HDR character */
+ SR_RET_INVALID_WAITING_END2 = -2018, /**< waiting for the 2nd HDR character */
+ SR_RET_INVALID_WAITING_END3 = -2019, /**< waiting for the 3rd HDR character */
+ SR_RET_INVALID_WAITING_END4 = -2020, /**< waiting for the 4th HDR character */
+ SR_RET_INVALID_WAITING_END5 = -2021, /**< waiting for the 5th HDR character */
+ SR_RET_INVALID_WAITING_SP_ACKNO = -2022,/**< now the space before the next header */
+ SR_RET_INVALID_WAITING_SP_WINDOW = -2023,/**< now the space before the next header */
+ SR_RET_INAPROPRIATE_HDRCMD = -2024, /**< the beep header was syntactically correct, but could not be used semantically */
+ SR_RET_OVERSIZED_FRAME = -2025, /**< the frame's "size" field specifies a size that does not fit into the current windows. Eventually malicous. */
+
+ /* and finally the OK state... */
+ SR_RET_OK = 0 /**< operation successful */
+};
+/** friendly type for global return value */
+typedef enum srRetVal_ srRetVal;
+
+
+typedef unsigned SBchannel; /**< our own type for channel numbers */
+typedef unsigned SBseqno; /**< our own type for sequence numbers */
+typedef unsigned SBansno; /**< our own type for answer numbers */
+typedef unsigned SBsize; /**< our own type for frame size */
+typedef unsigned SBmsgno; /**< our own type for message numbers */
+typedef unsigned SBackno; /**< our own type for acknowledgment numbers */
+typedef unsigned SBwindow; /**< our own type for window sizes*/
+
+
+/** Object ID. These are for internal checking. Each
+ * object is assigned a specific ID. This is contained in
+ * all Object structs (just like C++ RTTI). We can use
+ * this field to see if we have been passed a correct ID.
+ * Other than that, there is currently no other use for
+ * the object id.
+ */
+enum srObjectID
+{
+ OID_Freed = -1, /**< assigned, when an object is freed. If this
+ * is seen during a method call, this is an
+ * invalid object pointer!
+ */
+ OID_Invalid = 0, /**< value created by calloc(), so do not use ;) */
+ /* The 0xCDAB is a debug aid. It helps us find object IDs in memory
+ * dumps (on X86, this is ABCD in the dump ;)
+ * If you are on an embedded device and you would like to save space
+ * make them 1 byte only.
+ */
+ OIDsbFram = 0xCDAB0001,
+ OIDsbChan = 0xCDAB0002,
+ OIDsbMesg = 0xCDAB0003,
+ OIDsbSess = 0xCDAB0004,
+ OIDsbSock = 0xCDAB0005,
+ OIDsbProf = 0xCDAB0006,
+ OIDsrAPI = 0xCDAB0007,
+ OIDsrSLMG = 0xCDAB0008,
+ OIDsbNVTR = 0xCDAB0009,
+ OIDsbNVTE = 0xCDAB000A,
+ OIDsbStrB = 0xCDAB000B,
+ OIDsbLstn = 0xCDAB000C,
+ OIDsbPSSR = 0xCDAB000D,
+ OIDsbPSRC = 0xCDAB000E
+};
+typedef enum srObjectID srObjID;
+
+
+/**
+ * Allowed options for 3195 client profile
+ * selection.
+ */
+enum srOPTION3195Profiles_
+{
+ USE_3195_PROFILE_ANY = 1,
+ USE_3195_PROFILE_RAW_ONLY = 2,
+ USE_3195_PROFILE_COOKED_ONLY = 3
+};
+typedef enum srOPTION3195Profiles_ srOPTION3195Profiles;
+
+/**
+ * Library options. Modify library behaviour.
+ * Currently, no options are defined.
+ */
+enum srOPTION
+{
+ srOPTION_INVALID = 0, /**< invalid option, if seen, caller made an error */
+ /**
+ * This option tells the library if it should instruct the
+ * socket parts of it to call the OS socket initialiser.
+ * Under Win32, for example, this is only allowed once per
+ * process. So if the lib is integrated into a process that
+ * already uses sockets, the sockets initializer (WSAStartup()
+ * in this case) should not be called.
+ * This is a global setting that NEEDS TO BE SET BEFORE the API
+ * object is created!!!!
+ */
+ srOPTION_CALL_OS_SOCKET_INITIALIZER = 1,
+ /**
+ * This option tells the library which RFC 3195 Profile
+ * should be used when talking to the remote peer. This
+ * option so far is only used in the client parts of
+ * liblogging. See \ref srOPTION3195Profiles for
+ * allowed values.
+ */
+ srOPTION_3195_ALLOWED_CLIENT_PROFILES = 2,
+ /**
+ * This options tells the lib if a UDP listener should
+ * be started. Option value must be TRUE or FALSE.
+ */
+ srOPTION_LISTEN_UDP = 3,
+ /**
+ * Sets the UDP listener port. Is only used if the
+ * UDP listener is activated.
+ */
+ srOPTION_UPD_LISTENPORT = 4,
+ /**
+ * This option tells the lib if a UNIX domain socket
+ * listener should be started. Supported values are
+ * TRUE and FALSE.
+ */
+ srOPTION_LISTEN_UXDOMSOCK = 5,
+ /**
+ * Provides a pointer to the UNIX domain socket that
+ * should be listened to (if listening is enabled).
+ */
+ srOPTION_UXDOMSOCK_LISTENAME = 6,
+ /**
+ * This option tells the lib if a BEEP
+ * listener should be started. Supported values are
+ * TRUE and FALSE.
+ */
+ srOPTION_LISTEN_BEEP = 7,
+ /**
+ * Sets the BEEP listener port. Is only used if the
+ * UDP listener is activated.
+ */
+ srOPTION_BEEP_LISTENPORT = 8
+};
+typedef enum srOPTION SRoption;
+
+/**
+ * This macro should be used to free objects.
+ * Microsoft VC automatically sets _DEBUG if compiling
+ * with debug settings. For other environments, you may
+ * want to add this to a debug makefile.
+ */
+#if DEBUGLEVEL > 0
+#define SRFREEOBJ(x) {(x)->OID = OID_Freed; free(x);}
+#else
+#define SRFREEOBJ(x) free(x)
+#endif
+
+/**
+ * Integer values for the various supported
+ * BEEP headers.
+ */
+enum BEEPHdrID_
+{
+ BEEPHDR_UNKNOWN = 0,
+ BEEPHDR_ANS,
+ BEEPHDR_ERR,
+ BEEPHDR_MSG,
+ BEEPHDR_NUL,
+ BEEPHDR_RPY,
+ BEEPHDR_SEQ
+};
+typedef enum BEEPHdrID_ BEEPHdrID;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* from liblogging config.h */
+#define STRINGBUF_ALLOC_INCREMENT 128
+#endif
diff --git a/syslogd.c b/syslogd.c
index 252974ec..5fca2657 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -2,6 +2,7 @@
* TODO:
* - check if syslogd really needs to be shut down totally if
* "syslog" service from etc/services can not be found
+ * - check if MsgGetProp() can be used for MySQL, too
*
* \brief This is what will become the rsyslogd daemon.
*
@@ -787,6 +788,7 @@ struct filed {
short f_file; /* file descriptor */
#ifdef WITH_DB
MYSQL f_hmysql; /* handle to MySQL */
+ /* TODO: optimize memory layout / consumption; rgerhards 2004-11-19 */
char f_dbsrv[MAXHOSTNAMELEN+1]; /* IP or hostname of DB server*/
char f_dbname[_DB_MAXDBLEN+1]; /* DB name */
char f_dbuid[_DB_MAXUNAMELEN+1]; /* DB user */
@@ -809,6 +811,8 @@ struct filed {
int f_prevcount; /* repetition cnt of prevline */
int f_repeatcount; /* number of "repeated" msgs */
int f_flags; /* store some additional flags */
+ struct template *f_pTpl; /* pointer to template to use */
+ struct iovec *f_iov; /* dyn allocated depinding on template */
struct msg* f_pMsg; /* pointer to the message (this wil
* replace the other vars with msg
* content later). This is preserved after
@@ -1312,29 +1316,14 @@ struct msg* MsgConstruct()
{
struct msg *pM;
- if((pM = malloc(sizeof(struct msg))) != NULL)
- { /* initialize members */
+ if((pM = calloc(1, sizeof(struct msg))) != NULL)
+ { /* initialize members that are non-zero */
pM->iRefCount = 1;
- pM->iMsgSource = 0;
pM->iSyslogVers = -1;
pM->iSeverity = -1;
pM->iFacility = -1;
- pM->pszRcvdAt3164 = NULL;
- pM->pszRawMsg = NULL;
- pM->pszUxTradMsg = NULL;
- pM->pszTAG = NULL;
- pM->pszHOSTNAME = NULL;
- pM->pszRcvFrom = NULL;
- pM->pszMSG = NULL;
- pM->iLenMSG = 0;
- pM->iLenRawMsg = 0;
- pM->iLenHOSTNAME = 0;
- pM->iLenRcvFrom = 0;
- pM->iLenTAG = 0;
- pM->iLenUxTradMsg = 0;
getCurrTime(&(pM->tRcvdAt));
/* TODO: we can set the time HERE! */
- pM->tTIMESTAMP.timeType = 0;
}
dprintf("MsgConstruct\t0x%x\n", (int)pM);
@@ -1635,6 +1624,7 @@ char *MsgGetProp(struct msg *pMsg, char *pName)
pRes = "INVALID PROPERTY NAME"; /* NULL;*/
}
+ dprintf("MsgGetProp(\"%s\"): \"%s\"\n", pName, pRes);
return(pRes);
}
@@ -2427,6 +2417,8 @@ void logmsgInternal(pri, msg, from, flags)
int flags;
{
struct msg *pMsg;
+ char buf[16];
+ char szMsg[1024];
if((pMsg = MsgConstruct()) == NULL){
/* rgerhards 2004-11-09: calling panic might not be the
@@ -2438,7 +2430,6 @@ void logmsgInternal(pri, msg, from, flags)
}
if(MsgSetMSG(pMsg, msg) != 0) return;
- if(MsgSetUxTradMsg(pMsg, msg) != 0) return;
if(MsgSetRawMsg(pMsg, msg) != 0) return;
if(MsgSetHOSTNAME(pMsg, from) != 0) return;
pMsg->iFacility = LOG_FAC(pri);
@@ -2446,6 +2437,13 @@ void logmsgInternal(pri, msg, from, flags)
pMsg->iMsgSource = SOURCE_INTERNAL;
getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
+ /* generate traditional Unix message... */
+ formatTimestamp3164(&pMsg->tTIMESTAMP, buf, sizeof(buf) / sizeof(char));
+
+ snprintf(szMsg, sizeof(szMsg) / sizeof(char), "%s %s %s",
+ buf, from, msg);
+ if(MsgSetUxTradMsg(pMsg, szMsg) != 0) return;
+
logmsg(pri, pMsg, flags);
MsgDestruct(pMsg);
}
@@ -2655,19 +2653,14 @@ void logmsg(pri, pMsg, flags)
*/
void writeFile(struct filed *f)
{
- struct iovec *iov;
register struct iovec *v;
int iIOVused;
- /*char szTIMESTAMP[40];*/
struct template *pTpl;
struct templateEntry *pTpe;
struct msg *pMsg;
assert(f != NULL);
- /* f->f_file == -1 is an indicator that the we couldn't
- open the file at startup. */
- if (f->f_file == -1)
- return; /* TODO: eventually do this check in caller! */
+
/* Now generate the message. This can eventually be moved to
* a generic subroutine (need to think about this....).
* for now, this is a quick and dirty dummy. We need to have the
@@ -2675,17 +2668,9 @@ void writeFile(struct filed *f)
* code this part of the function. rgerhards 2004-11-11
*/
- pMsg = f->f_pMsg;
-
- /*if((pTpl = tplFind("TraditionalFormat", strlen("TraditionalFormat"))) == NULL) {*/
- if((pTpl = tplFind("precise", strlen("precise"))) == NULL) {
- dprintf("Could not find template '%s'\n", "precise");
- return;
- }
-
- /* TODO: allocate iov in struct filed! */
- iov = calloc(tplGetEntryCount(pTpl), sizeof(struct iovec));
- v = iov;
+ pMsg = f->f_pMsg;
+ pTpl = f->f_pTpl;
+ v = f->f_iov;
iIOVused = 0;
pTpe = pTpl->pEntryRoot;
@@ -2696,7 +2681,7 @@ void writeFile(struct filed *f)
++v;
++iIOVused;
} else if(pTpe->eEntryType == FIELD) {
- v->iov_base = MsgGetProp(pMsg, pTpe->data.pPropRepl);
+ v->iov_base = MsgGetProp(pMsg, pTpe->data.field.pPropRepl);
v->iov_len = strlen(v->iov_base);
/* TODO: performance optimize - can we obtain the length? */
++v;
@@ -2720,7 +2705,7 @@ void writeFile(struct filed *f)
#endif
again:
- if (writev(f->f_file, iov, iIOVused) < 0) {
+ if (writev(f->f_file, f->f_iov, iIOVused) < 0) {
int e = errno;
/* If a named pipe is full, just ignore it for now
@@ -2794,7 +2779,7 @@ void fprintlog(f, flags)
v->iov_len = 1;
v++;
v->iov_base = f->f_prevhost;
- v->iov_len = strlen(v->iov_base);
+ v->iov_len = f->f_prevhost == 0 ? 0 : strlen(v->iov_base);
v++;
v->iov_base = " ";
v->iov_len = 1;
@@ -2925,58 +2910,10 @@ void fprintlog(f, flags)
case F_TTY:
case F_FILE:
case F_PIPE:
- writeFile(f);
-#if 0
- f->f_time = now;
- dprintf(" %s\n", f->f_un.f_fname);
- if (f->f_type == F_TTY || f->f_type == F_CONSOLE) {
- v->iov_base = "\r\n";
- v->iov_len = 2;
- } else {
- v->iov_base = "\n";
- v->iov_len = 1;
- }
- again:
/* f->f_file == -1 is an indicator that the we couldn't
open the file at startup. */
- if (f->f_file == -1)
- break;
-
- if (writev(f->f_file, iov, 6) < 0) {
- int e = errno;
-
- /* If a named pipe is full, just ignore it for now
- - mrn 24 May 96 */
- if (f->f_type == F_PIPE && e == EAGAIN)
- break;
-
- (void) close(f->f_file);
- /*
- * Check for EBADF on TTY's due to vhangup() XXX
- * Linux uses EIO instead (mrn 12 May 96)
- */
- if ((f->f_type == F_TTY || f->f_type == F_CONSOLE)
-#ifdef linux
- && e == EIO) {
-#else
- && e == EBADF) {
-#endif
- f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND|O_NOCTTY);
- if (f->f_file < 0) {
- f->f_type = F_UNUSED;
- logerror(f->f_un.f_fname);
- } else {
- untty();
- goto again;
- }
- } else {
- f->f_type = F_UNUSED;
- errno = e;
- logerror(f->f_un.f_fname);
- }
- } else if (f->f_flags & SYNC_FILE)
- (void) fsync(f->f_file);
-#endif
+ if (f->f_file != -1)
+ writeFile(f);
break;
case F_USERS:
@@ -3428,6 +3365,10 @@ void init()
*/
fprintlog(f, 0);
+ /* free iovec if it was allocated */
+ if(f->f_iov != NULL)
+ free(f->f_iov);
+
switch (f->f_type) {
case F_FILE:
case F_PIPE:
@@ -3646,6 +3587,72 @@ void init()
}}} /* balance parentheses for emacs */
#endif
+/* Helper to cfline(). Parses a file name up until the first
+ * comma and then looks for the template specifier. Tries
+ * to find that template. Everything is stored in the
+ * filed struct.
+ * rgerhards 2004-11-18
+ */
+void cflineParseFileName(struct filed *f, register char* p)
+{
+ register char *pName;
+ int i;
+ char szTemplateName[128]; /* should be more than sufficient */
+
+ if(*p == '|') {
+ f->f_type = F_PIPE;
+ ++p;
+ } else {
+ f->f_type = F_FILE;
+ }
+
+ pName = f->f_un.f_fname;
+ i = 0;
+ while(*p && *p != ',' && i < MAXFNAME - 1) {
+ *pName++ = *p++;
+ ++i;
+ }
+ *pName = '\0';
+
+ /* got the file name - now let's look for the template to use
+ * Just as a general precaution, we skip whitespace.
+ */
+ while(*p && isspace(*p))
+ ++p;
+ if(*p == ',')
+ ++p; /* eat it */
+ while(*p && isspace(*p))
+ ++p;
+
+ pName = szTemplateName;
+ i = 0;
+ while(*p && i < sizeof(szTemplateName) / sizeof(char) - 1) {
+ *pName++ = *p++;
+ ++i;
+ }
+ *pName = '\0';
+
+ /* Ok, we got everything, so it now is time to look up the
+ * template (Hint: templates MUST be defined before they are
+ * used!) and initialize the pointer to it PLUS the iov
+ * pointer. We do the later because the template tells us
+ * how many elements iov must have - and this can never change.
+ */
+ if((f->f_pTpl = tplFind(szTemplateName, i)) == NULL) {
+ dprintf("Could not find template '%s'\n", szTemplateName);
+ f->f_type = F_UNUSED;
+ } else {
+ if((f->f_iov = calloc(tplGetEntryCount(f->f_pTpl),
+ sizeof(struct iovec))) == NULL) {
+ dprintf("Could not allocate iovec memory for file '%s'\n", f->f_un.f_fname);
+ f->f_type = F_UNUSED;
+ }
+ }
+
+ dprintf("filename: '%s', template: '%s'\n", f->f_un.f_fname, szTemplateName);
+}
+
+
/*
* Crack a configuration file line
* rgerhards 2004-11-17: well, I somewhat changed this function. It now does NOT
@@ -3654,10 +3661,9 @@ void init()
* with "$" have been filtered out by the caller and are passed to another function.
* Please note, however, that I needed to make changes in the line syntax to support
* assignment of format definitions to a file. So it is not (yet) 100% transparent.
- * Eventually, we can overcome this limitation by prfexing the actual acton indicator
+ * Eventually, we can overcome this limitation by prefixing the actual action indicator
* (e.g. "/file..") by something (e.g. "$/file..") - but for now, we just modify it...
*/
-
void cfline(line, f)
char *line;
register struct filed *f;
@@ -3854,23 +3860,25 @@ void cfline(line, f)
case '|':
case '/':
- (void) strcpy(f->f_un.f_fname, p);
- dprintf ("filename: %s\n", p); /*ASP*/
+ /* rgerhards 2004-11-17: from now, we need to have different
+ * processing, because after the first comma, the template name
+ * to use is specified. So we need to scan for the first coma first
+ * and then look at the rest of the line.
+ */
+ cflineParseFileName(f, p);
if (syncfile)
f->f_flags |= SYNC_FILE;
- if ( *p == '|' ) {
- f->f_file = open(++p, O_RDWR|O_NONBLOCK);
- f->f_type = F_PIPE;
+ if (f->f_type == F_PIPE) {
+ f->f_file = open(f->f_un.f_fname, O_RDWR|O_NONBLOCK);
} else {
- f->f_file = open(p, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
0644);
- f->f_type = F_FILE;
}
if ( f->f_file < 0 ){
f->f_file = -1;
- dprintf("Error opening log file: %s\n", p);
- logerror(p);
+ dprintf("Error opening log file: %s\n", f->f_un.f_fname);
+ logerror(f->f_un.f_fname);
break;
}
if (isatty(f->f_file)) {
diff --git a/template.c b/template.c
index b3c5853a..3b0f3d16 100644
--- a/template.c
+++ b/template.c
@@ -167,7 +167,7 @@ static int do_Parameter(char **pp, struct template *pTpl)
return 1;
}
pTpe->eEntryType = FIELD;
- pTpe->data.pPropRepl = sbStrBFinish(pStrB);
+ pTpe->data.field.pPropRepl = sbStrBFinish(pStrB);
*pp = p;
return 0;
@@ -292,7 +292,7 @@ void tplPrintList(void)
dprintf("Template: Name='%s'\n", pTpl->pszName == NULL? "NULL" : pTpl->pszName);
pTpe = pTpl->pEntryRoot;
while(pTpe != NULL) {
- dprintf("\tEntry: type %d, ", pTpe->eEntryType);
+ dprintf("\tEntry(%x): type %d, ", (unsigned) pTpe, pTpe->eEntryType);
switch(pTpe->eEntryType) {
case UNDEFINED:
dprintf("(UNDEFINED)\n");
@@ -302,7 +302,7 @@ void tplPrintList(void)
pTpe->data.constant.pConstant);
break;
case FIELD:
- dprintf("(FIELD), value: '%s'\n", pTpe->data.pPropRepl);
+ dprintf("(FIELD), value: '%s'\n", pTpe->data.field.pPropRepl);
break;
}
pTpe = pTpe->pNext;
diff --git a/template.h b/template.h
index a3019828..604c317b 100644
--- a/template.h
+++ b/template.h
@@ -23,7 +23,9 @@ struct templateEntry {
char *pConstant; /* pointer to constant value */
int iLenConstant; /* its length */
} constant;
- char *pPropRepl; /* pointer to property replacer string */
+ struct {
+ char *pPropRepl; /* pointer to property replacer string */
+ } field;
} data;
};