summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/imdiag/Makefile.am6
-rw-r--r--plugins/imdiag/imdiag.c197
-rw-r--r--plugins/imuxsock/imuxsock.c63
-rw-r--r--plugins/ommail/ommail.c116
4 files changed, 351 insertions, 31 deletions
diff --git a/plugins/imdiag/Makefile.am b/plugins/imdiag/Makefile.am
new file mode 100644
index 00000000..da5a3ddc
--- /dev/null
+++ b/plugins/imdiag/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imdiag.la
+
+imdiag_la_SOURCES = imdiag.c
+imdiag_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
+imdiag_la_LDFLAGS = -module -avoid-version
+imdiag_la_LIBADD =
diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c
new file mode 100644
index 00000000..3cd2dcf8
--- /dev/null
+++ b/plugins/imdiag/imdiag.c
@@ -0,0 +1,197 @@
+/* imdiag.c
+ * This is a diagnostics module, primarily meant for troubleshooting
+ * and information about the runtime state of rsyslog. It is implemented
+ * as an input plugin, because that interface best suits our needs
+ * and also enables us to inject test messages (something not yet
+ * implemented).
+ *
+ * File begun on 2008-07-25 by RGerhards
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+//#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "net.h"
+#include "netstrm.h"
+#include "errmsg.h"
+
+MODULE_TYPE_INPUT
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(errmsg)
+
+/* Module static data */
+netstrms_t *pNS; /**< pointer to network stream subsystem */
+netstrm_t **ppLstn[10]; /**< our netstream listners */
+int iLstnMax = 0; /**< max nbr of listeners currently supported */
+
+
+/* config settings */
+
+
+/* add a listen socket to our listen socket array. This is a callback
+ * invoked from the netstrm class. -- rgerhards, 2008-04-23
+ */
+static rsRetVal
+addTcpLstn(void *pUsr, netstrm_t *pLstn)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pLstn, netstrm);
+
+ if(iLstnMax >= sizeof(ppLstn)/sizeof(netstrm_t))
+ ABORT_FINALIZE(RS_RET_MAX_LSTN_REACHED);
+
+ ppLstn[pThis->iLstnMax] = pLstn;
+ ++iLstnMax;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* initialize network stream subsystem */
+static rsRetVal
+initNetstrm(void)
+{
+ DEFiRet;
+
+ /* prepare network stream subsystem */
+ CHKiRet(netstrms.Construct(&pNS));
+ CHKiRet(netstrms.SetDrvrMode(pNS, 0)); /* always plain text */
+ //CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode));
+ //CHKiRet(netstrms.SetDrvrPermPeers(pThis->pNS, pThis->pPermPeers));
+ // TODO: set driver!
+ CHKiRet(netstrms.ConstructFinalize(pThis->pNS));
+
+ /* set up listeners */
+ CHKiRet(netstrm.LstnInit(pNS, NULL, addTcpLstn, "127.0.0.1", "44514", 1));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pNS != NULL)
+ netstrms.Destruct(&pThis->pNS);
+ }
+ RETiRet;
+}
+
+
+/* This function is called to gather input. In our case, it is a bit abused
+ * to drive the listener loop for the diagnostics code.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ iRet = initNetstrm();
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ /* do cleanup here */
+ /* finally close our listen streams */
+ for(i = 0 ; i < iLstnMax ; ++i) {
+ netstrm.Destruct(ppLstn + i);
+ }
+
+ /* destruct netstream subsystem */
+ netstrms.Destruct(pNS);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release objects we used */
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(errmsg, CORE_COMPONENT);
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ return RS_RET_OK;
+}
+
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ pOurTcpsrv = NULL;
+ /* request objects we use */
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+
+#if 0
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverrun", 0, eCmdHdlrGetWord,
+ addTCPListener, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpmaxsessions", 0, eCmdHdlrInt,
+ NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdrivermode", 0,
+ eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverauthmode", 0,
+ eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputtcpserverstreamdriverpermittedpeer", 0,
+ eCmdHdlrGetWord, setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+#endif
+ENDmodInit
+
+
+/* vim:set ai:
+ */
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 05bcb642..4f1fcea4 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -73,12 +73,16 @@ static int startIndexUxLocalSockets; /* process funix from that index on (used t
static int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */
static int funixFlags[MAXFUNIX] = { ADDDATE, }; /* should parser parse host name? read-only after startup */
static uchar *funixn[MAXFUNIX] = { (uchar*) _PATH_LOG }; /* read-only after startup */
+static uchar *funixHName[MAXFUNIX] = { NULL, }; /* host-name override - if set, use this instead of actual name */
+static int funixFlowCtl[MAXFUNIX] = { eFLOWCTL_NO_DELAY, }; /* flow control settings for this socket */
static int funix[MAXFUNIX] = { -1, }; /* read-only after startup */
static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
/* config settings */
static int bOmitLocalLogging = 0;
static uchar *pLogSockName = NULL;
+static uchar *pLogHostName = NULL; /* host name to use with this socket */
+static int bUseFlowCtl = 0; /* use flow control or not (if yes, only LIGHT is used! */
static int bIgnoreTimestamp = 1; /* ignore timestamps present in the incoming message? */
@@ -93,6 +97,14 @@ static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal,
RETiRet;
}
+/* set flowcontrol for the system log socket
+ */
+static rsRetVal setSystemLogFlowControl(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+ funixFlowCtl[0] = iNewVal ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
+ RETiRet;
+}
/* add an additional listen socket. Socket names are added
* until the array is filled up. It is never reset, only at
@@ -100,6 +112,7 @@ static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal,
* TODO: we should change the array to a list so that we
* can support any number of listen socket names.
* rgerhards, 2007-12-20
+ * added capability to specify hostname for socket -- rgerhards, 2008-08-01
*/
static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal)
{
@@ -110,6 +123,9 @@ static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNe
else {
funixParseHost[nfunix] = 0;
}
+ funixHName[nfunix] = pLogHostName;
+ pLogHostName = NULL; /* re-init for next, not freed because funixHName[] now owns it */
+ funixFlowCtl[nfunix] = bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
funixFlags[nfunix] = bIgnoreTimestamp ? ADDDATE : NOFLAG;
funixn[nfunix++] = pNewVal;
}
@@ -134,6 +150,10 @@ static rsRetVal discardFunixn(void)
free(funixn[i]);
funixn[i] = NULL;
}
+ if(funixHName[i] != NULL) {
+ free(funixHName[i]);
+ funixHName[i] = NULL;
+ }
}
return RS_RET_OK;
@@ -144,7 +164,6 @@ static int create_unix_socket(const char *path)
{
struct sockaddr_un sunx;
int fd;
- char line[MAXLINE +1];
if (path[0] == '\0')
return -1;
@@ -155,11 +174,9 @@ static int create_unix_socket(const char *path)
sunx.sun_family = AF_UNIX;
(void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path));
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
- if (fd < 0 || bind(fd, (struct sockaddr *) &sunx,
- SUN_LEN(&sunx)) < 0 ||
+ if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, SUN_LEN(&sunx)) < 0 ||
chmod(path, 0666) < 0) {
- snprintf(line, sizeof(line), "cannot create %s", path);
- errmsg.LogError(errno, NO_ERRCODE, "%s", line);
+ errmsg.LogError(errno, NO_ERRCODE, "connot create '%s'", path);
dbgprintf("cannot create %s (%d).\n", path, errno);
close(fd);
return -1;
@@ -171,18 +188,23 @@ static int create_unix_socket(const char *path)
/* This function receives data from a socket indicated to be ready
* to receive and submits the message received for processing.
* rgerhards, 2007-12-20
+ * Interface changed so that this function is passed the array index
+ * of the socket which is to be processed. This eases access to the
+ * growing number of properties. -- rgerhards, 2008-08-01
*/
-static rsRetVal readSocket(int fd, int bParseHost, int flags)
+static rsRetVal readSocket(int fd, int iSock)
{
DEFiRet;
int iRcvd;
uchar line[MAXLINE +1];
+ assert(iSock >= 0);
iRcvd = recv(fd, line, MAXLINE - 1, 0);
dbgprintf("Message from UNIX socket: #%d\n", fd);
if (iRcvd > 0) {
- parseAndSubmitMessage(glbl.GetLocalHostName(), (uchar*)"127.0.0.1", line,
- iRcvd, bParseHost, flags, eFLOWCTL_NO_DELAY);
+ parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock],
+ (uchar*)"127.0.0.1", line,
+ iRcvd, funixParseHost[iSock], funixFlags[iSock], funixFlowCtl[iSock]);
} else if (iRcvd < 0 && errno != EINTR) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
@@ -194,8 +216,7 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags)
}
-/* This function is called to gather input.
- */
+/* This function is called to gather input. */
BEGINrunInput
int maxfds;
int nfds;
@@ -237,7 +258,7 @@ CODESTARTrunInput
for (i = 0; i < nfunix && nfds > 0; i++) {
if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) {
- readSocket(fd, funixParseHost[i], funixFlags[i]);
+ readSocket(fd, i);
--nfds; /* indicate we have processed one */
}
}
@@ -282,6 +303,9 @@ CODESTARTafterRun
/* free no longer needed string */
if(pLogSockName != NULL)
free(pLogSockName);
+ if(pLogHostName != NULL) {
+ free(pLogHostName);
+ }
discardFunixn();
nfunix = 1;
@@ -307,10 +331,15 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
free(pLogSockName);
pLogSockName = NULL;
}
+ if(pLogHostName != NULL) {
+ free(pLogHostName);
+ pLogHostName = NULL;
+ }
discardFunixn();
nfunix = 1;
bIgnoreTimestamp = 1;
+ bUseFlowCtl = 0;
return RS_RET_OK;
}
@@ -324,6 +353,8 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ dbgprintf("imuxsock version %s initializing\n", PACKAGE_VERSION);
+
/* initialize funixn[] array */
for(i = 1 ; i < MAXFUNIX ; ++i) {
funixn[i] = NULL;
@@ -337,18 +368,24 @@ CODEmodInit_QueryRegCFSLineHdlr
NULL, &bIgnoreTimestamp, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketname", 0, eCmdHdlrGetWord,
NULL, &pLogSockName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensockethostname", 0, eCmdHdlrGetWord,
+ NULL, &pLogHostName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary,
+ NULL, &bUseFlowCtl, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord,
addLstnSocketName, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
/* the following one is a (dirty) trick: the system log socket is not added via
- * an "addUnixListenSocket" config format. As such, the timestamp can not be modified
- * via $InputUnixListenSocketIgnoreMsgTimestamp". So we need to add a special directive
+ * an "addUnixListenSocket" config format. As such, it's properties can not be modified
+ * via $InputUnixListenSocket*". So we need to add a special directive
* for that. We should revisit all of that once we have the new config format...
* rgerhards, 2008-03-06
*/
CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketignoremsgtimestamp", 0, eCmdHdlrBinary,
setSystemLogTimestampIgnore, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketflowcontrol", 0, eCmdHdlrBinary,
+ setSystemLogFlowControl, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
/* vim:set ai:
*/
diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c
index 4bbb844a..5faadce3 100644
--- a/plugins/ommail/ommail.c
+++ b/plugins/ommail/ommail.c
@@ -60,10 +60,18 @@ DEF_OMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
+/* we add a little support for multiple recipients. We do this via a
+ * singly-linked list, enqueued from the top. -- rgerhards, 2008-08-04
+ */
+typedef struct toRcpt_s toRcpt_t;
+struct toRcpt_s {
+ uchar *pszTo;
+ toRcpt_t *pNext;
+};
+static toRcpt_t *lstRcpt = NULL;
static uchar *pszSrv = NULL;
static uchar *pszSrvPort = NULL;
static uchar *pszFrom = NULL;
-static uchar *pszTo = NULL;
static uchar *pszSubject = NULL;
static int bEnableBody = 1; /* should a mail body be generated? (set to 0 eg for SMS gateways) */
@@ -76,7 +84,7 @@ typedef struct _instanceData {
uchar *pszSrv;
uchar *pszSrvPort;
uchar *pszFrom;
- uchar *pszTo;
+ toRcpt_t *lstRcpt;
char RcvBuf[1024]; /* buffer for receiving server responses */
size_t lenRcvBuf;
size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */
@@ -85,6 +93,83 @@ typedef struct _instanceData {
} md; /* mode-specific data */
} instanceData;
+/* forward definitions (as few as possible) */
+static rsRetVal Send(int sock, char *msg, size_t len);
+static rsRetVal readResponse(instanceData *pData, int *piState, int iExpected);
+
+
+/* helpers for handling the recipient lists */
+
+/* destroy a complete recipient list */
+static void lstRcptDestruct(toRcpt_t *pRoot)
+{
+ toRcpt_t *pDel;
+
+ while(pRoot != NULL) {
+ pDel = pRoot;
+ pRoot = pRoot->pNext;
+ /* ready to disalloc */
+ free(pDel->pszTo);
+ free(pDel);
+ }
+}
+
+/* This function is called when a new recipient email address is to be
+ * added. rgerhards, 2008-08-04
+ */
+static rsRetVal
+addRcpt(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ DEFiRet;
+ toRcpt_t *pNew = NULL;
+
+ CHKmalloc(pNew = calloc(1, sizeof(toRcpt_t)));
+
+ pNew->pszTo = pNewVal;
+ pNew->pNext = lstRcpt;
+ lstRcpt = pNew;
+
+ dbgprintf("ommail::addRcpt adds recipient %s\n", pNewVal);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ free(pNew);
+ free(pNewVal); /* in any case, this is no longer needed */
+ }
+
+ RETiRet;
+}
+
+
+/* output the recipient list to the mail server
+ * iStatusToCheck < 0 means no checking should happen
+ */
+static rsRetVal
+WriteRcpts(instanceData *pData, uchar *pszOp, size_t lenOp, int iStatusToCheck)
+{
+ toRcpt_t *pRcpt;
+ int iState;
+ DEFiRet;
+
+ assert(pData != NULL);
+ assert(pszOp != NULL);
+ assert(lenOp != 0);
+
+ for(pRcpt = pData->md.smtp.lstRcpt ; pRcpt != NULL ; pRcpt = pRcpt->pNext) {
+ dbgprintf("Sending '%s: <%s>'\n", pszOp, pRcpt->pszTo);
+ CHKiRet(Send(pData->md.smtp.sock, (char*)pszOp, lenOp));
+ CHKiRet(Send(pData->md.smtp.sock, ": <", sizeof(": <") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)pRcpt->pszTo, strlen((char*)pRcpt->pszTo)));
+ CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+ if(iStatusToCheck >= 0)
+ CHKiRet(readResponse(pData, &iState, iStatusToCheck));
+ }
+
+finalize_it:
+ RETiRet;
+}
+/* end helpers for handling the recipient lists */
BEGINcreateInstance
CODESTARTcreateInstance
@@ -107,8 +192,7 @@ CODESTARTfreeInstance
free(pData->md.smtp.pszSrvPort);
if(pData->md.smtp.pszFrom != NULL)
free(pData->md.smtp.pszFrom);
- if(pData->md.smtp.pszTo != NULL)
- free(pData->md.smtp.pszTo);
+ lstRcptDestruct(pData->md.smtp.lstRcpt);
}
ENDfreeInstance
@@ -426,10 +510,7 @@ sendSMTP(instanceData *pData, uchar *body, uchar *subject)
CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
CHKiRet(readResponse(pData, &iState, 250));
- CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: <", sizeof("RCPT TO: <") - 1));
- CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo)));
- CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
- CHKiRet(readResponse(pData, &iState, 250));
+ CHKiRet(WriteRcpts(pData, (uchar*)"RCPT TO", sizeof("RCPT TO") - 1, 250));
CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1));
CHKiRet(readResponse(pData, &iState, 354));
@@ -443,9 +524,7 @@ sendSMTP(instanceData *pData, uchar *body, uchar *subject)
CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom)));
CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
- CHKiRet(Send(pData->md.smtp.sock, "To: <", sizeof("To: <") - 1));
- CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo)));
- CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+ CHKiRet(WriteRcpts(pData, (uchar*)"To", sizeof("To") - 1, -1));
CHKiRet(Send(pData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1));
CHKiRet(Send(pData->md.smtp.sock, (char*)subject, strlen((char*)subject)));
@@ -531,13 +610,14 @@ CODESTARTparseSelectorAct
errmsg.LogError(0, RS_RET_MAIL_NO_FROM, "no sender address given - specify $ActionMailFrom");
ABORT_FINALIZE(RS_RET_MAIL_NO_FROM);
}
- if(pszTo == NULL) {
+ if(lstRcpt == NULL) {
errmsg.LogError(0, RS_RET_MAIL_NO_TO, "no recipient address given - specify $ActionMailTo");
ABORT_FINALIZE(RS_RET_MAIL_NO_TO);
}
pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom);
- pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo);
+ pData->md.smtp.lstRcpt = lstRcpt; /* we "hand over" this memory */
+ lstRcpt = NULL; /* note: this is different from pre-3.21.2 versions! */
if(pszSubject == NULL) {
/* if no subject is configured, we need just one template string */
@@ -576,10 +656,8 @@ static rsRetVal freeConfigVariables(void)
free(pszFrom);
pszFrom = NULL;
}
- if(pszTo != NULL) {
- free(pszTo);
- pszTo = NULL;
- }
+ lstRcptDestruct(lstRcpt);
+ lstRcpt = NULL;
RETiRet;
}
@@ -621,10 +699,12 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ dbgprintf("ommail version %s initializing\n", VERSION);
+
CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &pszSrv, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &pszSrvPort, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &pszFrom, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, NULL, &pszTo, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, addRcpt, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsubject", 0, eCmdHdlrGetWord, NULL, &pszSubject, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailenablebody", 0, eCmdHdlrBinary, NULL, &bEnableBody, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr( (uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));