diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | doc/Makefile.am | 1 | ||||
-rw-r--r-- | doc/imuxsock.html | 2 | ||||
-rw-r--r-- | doc/omuxsock.html | 43 | ||||
-rw-r--r-- | doc/rsyslog_conf_modules.html | 1 | ||||
-rw-r--r-- | plugins/omuxsock/Makefile.am | 8 | ||||
-rw-r--r-- | plugins/omuxsock/omuxsock.c | 315 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/testsuites/uxsock_simple.conf | 10 | ||||
-rwxr-xr-x | tests/uxsock_simple.sh | 31 | ||||
-rw-r--r-- | tests/uxsockrcvr.c | 157 |
14 files changed, 599 insertions, 2 deletions
@@ -1,4 +1,5 @@ --------------------------------------------------------------------------- +<<<<<<< HEAD Version 5.5.7 [V5-BETA] (rgerhards), 2010-08-?? - changed omudpspoof default spoof address to simplify typical use case thanks to David Lang for suggesting this @@ -473,6 +474,11 @@ increase. superior performance (for databases potentially far superior performance) - increased ompgsql performance by adapting to new transactional output module interface +======= +Version 4.7.3 [v4-devel] (rgerhards), 2010-??-?? +- added omuxsock, which permits to write message to local Unix sockets + this is the counterpart to imuxsock, enabling fast local forwarding +>>>>>>> 80ff634c841d692c1d9f335b88e225d6ce7317f7 --------------------------------------------------------------------------- Version 4.7.2 [v4-devel] (rgerhards), 2010-05-03 - bugfix: problems with atomic operations emulaton diff --git a/Makefile.am b/Makefile.am index f4cd98f4..67ae66bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -117,6 +117,9 @@ endif if ENABLE_OMUDPSPOOF SUBDIRS += plugins/omudpspoof + +if ENABLE_OMUXSOCK +SUBDIRS += plugins/omuxsock endif if ENABLE_OMTEMPLATE @@ -179,6 +182,7 @@ DISTCHECK_CONFIGURE_FLAGS= --enable-gssapi_krb5 \ --enable-omruleset \ --enable-omprog \ --enable-imdiag \ + --enable-omuxsock \ --enable-shave \ --enable-extended-tests \ --enable-memcheck diff --git a/configure.ac b/configure.ac index bcfdaf2f..117c08dc 100644 --- a/configure.ac +++ b/configure.ac @@ -909,6 +909,20 @@ AM_CONDITIONAL(ENABLE_GUI, test x$enable_gui = xyes) AC_SUBST(RELP_CFLAGS) AC_SUBST(RELP_LIBS) + +# settings for omuxsock +AC_ARG_ENABLE(omuxsock, + [AS_HELP_STRING([--enable-omuxsock],[Compiles stdout module @<:@default=no@:>@])], + [case "${enableval}" in + yes) enable_omuxsock="yes" ;; + no) enable_omuxsock="no" ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-omuxsock) ;; + esac], + [enable_omuxsock=no] +) +AM_CONDITIONAL(ENABLE_OMUXSOCK, test x$enable_omuxsock = xyes) + + # This provides a vehicle to integrate custom modules, that are not # part of rsyslog, into the build process. It is named cust1, so that # additional such modules can easily be added. @@ -983,6 +997,7 @@ AC_CONFIG_FILES([Makefile \ plugins/pmlastmsg/Makefile \ plugins/omruleset/Makefile \ plugins/omdbalerting/Makefile \ + plugins/omuxsock/Makefile \ plugins/imfile/Makefile \ plugins/imsolaris/Makefile \ plugins/imrelp/Makefile \ @@ -1029,6 +1044,7 @@ echo " omstdout module will be compiled: $enable_omstdout" echo " omruleset module will be compiled: $enable_omruleset" echo " omdbalerting module will be compiled: $enable_omdbalerting" echo " omudpspoof module will be compiled: $enable_omudpspoof" +echo " omuxsock module will be compiled: $enable_omuxsock" echo " output template module will be compiled: $enable_omtemplate" echo echo "---{ parser modules }---" diff --git a/doc/Makefile.am b/doc/Makefile.am index e4e7696b..4b39e633 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -108,6 +108,7 @@ html_files = \ gssapi.html \ licensing.html \ ommail.html \ + omuxsock.html \ omrelp.html \ syslog_parsing.html \ troubleshoot.html \ diff --git a/doc/imuxsock.html b/doc/imuxsock.html index 15c365a6..381374d2 100644 --- a/doc/imuxsock.html +++ b/doc/imuxsock.html @@ -100,7 +100,7 @@ $InputUnixListenSocketHostName /var/run/sshd/dev/log <p><font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a> project.<br> -Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer +Copyright © 2008-2010 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and <a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL version 3 or higher.</font></p> diff --git a/doc/omuxsock.html b/doc/omuxsock.html new file mode 100644 index 00000000..4ffc53eb --- /dev/null +++ b/doc/omuxsock.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html><head><title>Unix sockets output module (omuxsock) - sending syslog messages to local socket</title> +<a href="features.html">back</a> +</head> +<body> +<h1>Mail Output Module (omuxsock)</h1> +<p><b>Module Name: omuxsock</b></p> +<p><b>Available since: </b> 4.7.3, 5.5.7</p> +<p><b>Author: </b>Rainer Gerhards <rgerhards@adiscon.com></p> +<p><b>Description</b>:</p> +<p>This module supports sending syslog messages to local Unix sockets. +Thus it provided a fast message-passing interface between different rsyslog +instances. The counterpart to omuxsock is <a href="imuxsock.html">imuxsock</a>. +Note that the template used together with omuxsock must be suitable to be +processed by the receiver. +<p><b>Configuration Directives</b>:</p> +<ul> +<li><b>$OMUxSockSocket</b><br> +Name of the socket to send data to. This has no default and <b>must</b> +be set. +</li> +<li><b>$OMUxSockDefaultTemplate</b><br> +This can be used to override the default template to be used together +with omuxsock. This is primarily useful if there are many forwarding +actions and each of them should use the same template.</li> +</ul> +<b>Caveats/Known Bugs:</b> +<p>Currently, only datagram sockets are supported. +<p><b>Sample:</b></p> +<p>The following sample writes all messages to the "/tmp/socksample" socket. +</p> +<textarea rows="4" cols="80">$ModLoad omucsock +$OMUxSockSocket /tmp/socksample +*.* :omuxsock: +</textarea> +[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> +<p><font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a> +project.<br> +Copyright © 2010 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and +<a href="http://www.adiscon.com/">Adiscon</a>. +Released under the GNU GPL version 3 or higher.</font></p> + +</body></html> diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html index ef83d2ec..213769d2 100644 --- a/doc/rsyslog_conf_modules.html +++ b/doc/rsyslog_conf_modules.html @@ -63,6 +63,7 @@ SQLLite, Ingres, Oracle, mSQL)</li> permits rsyslog to alert folks by mail if something important happens</li> <li><a href="omoracle.html">omoracle</a> - output module for Oracle (native OCI interface)</li> <li><a href="omudpspoof.html">omudpspoof</a> - output module sending UDP syslog messages with a spoofed address</li> +<li><a href="omuxsock.html">omuxsock</a> - output module Unix domain sockets</li> </ul> <a name="pm"></a><h2>Parser Modules</h2> diff --git a/plugins/omuxsock/Makefile.am b/plugins/omuxsock/Makefile.am new file mode 100644 index 00000000..997232d9 --- /dev/null +++ b/plugins/omuxsock/Makefile.am @@ -0,0 +1,8 @@ +pkglib_LTLIBRARIES = omuxsock.la + +omuxsock_la_SOURCES = omuxsock.c +omuxsock_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) +omuxsock_la_LDFLAGS = -module -avoid-version +omuxsock_la_LIBADD = + +EXTRA_DIST = diff --git a/plugins/omuxsock/omuxsock.c b/plugins/omuxsock/omuxsock.c new file mode 100644 index 00000000..c66e63aa --- /dev/null +++ b/plugins/omuxsock/omuxsock.c @@ -0,0 +1,315 @@ +/* omuxsock.c + * This is the implementation of datgram unix domain socket forwarding. + * + * NOTE: read comments in module-template.h to understand how this file + * works! + * + * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c) + * This file is under development and has not yet arrived at being fully + * self-contained and a real object. So far, it is mostly an excerpt + * of the "old" message code without any modifications. However, it + * helps to have things at the right place one we go to the meat of it. + * + * Copyright 2010 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 "rsyslog.h" +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <assert.h> +#include <errno.h> +#include <unistd.h> +#include "conf.h" +#include "srUtils.h" +#include "template.h" +#include "msg.h" +#include "cfsysline.h" +#include "module-template.h" +#include "glbl.h" +#include "errmsg.h" +#include "unicode-helper.h" + +MODULE_TYPE_OUTPUT + +/* internal structures + */ +DEF_OMOD_STATIC_DATA +DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) + +#define INVLD_SOCK -1 + +typedef struct _instanceData { + permittedPeers_t *pPermPeers; + uchar *sockName; + int sock; + int bIsConnected; /* are we connected to remote host? 0 - no, 1 - yes, UDP means addr resolved */ + struct sockaddr_un addr; +} instanceData; + +/* config data */ +static uchar *tplName = NULL; /* name of the default template to use */ +static uchar *sockName = NULL; /* name of the default template to use */ + +static rsRetVal doTryResume(instanceData *pData); + +/* Close socket. + */ +static inline rsRetVal +closeSocket(instanceData *pData) +{ + DEFiRet; + if(pData->sock != INVLD_SOCK) { + close(pData->sock); + pData->sock = INVLD_SOCK; + } +pData->bIsConnected = 0; // TODO: remove this variable altogether + RETiRet; +} + + + +BEGINcreateInstance +CODESTARTcreateInstance + pData->sock = INVLD_SOCK; +ENDcreateInstance + + +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + if(eFeat == sFEATURERepeatedMsgReduction) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + + +BEGINfreeInstance +CODESTARTfreeInstance + /* final cleanup */ + closeSocket(pData); + free(pData->sockName); +ENDfreeInstance + + +BEGINdbgPrintInstInfo +CODESTARTdbgPrintInstInfo + DBGPRINTF("%s", pData->sockName); +ENDdbgPrintInstInfo + + +/* Send a message via UDP + * rgehards, 2007-12-20 + */ +static rsRetVal sendMsg(instanceData *pData, char *msg, size_t len) +{ + DEFiRet; + unsigned lenSent = 0; + + if(pData->sock == INVLD_SOCK) { + CHKiRet(doTryResume(pData)); + } + + if(pData->sock != INVLD_SOCK) { + /* we need to track if we have success sending to the remote + * peer. Success is indicated by at least one sendto() call + * succeeding. We track this be bSendSuccess. We can not simply + * rely on lsent, as a call might initially work, but a later + * call fails. Then, lsent has the error status, even though + * the sendto() succeeded. -- rgerhards, 2007-06-22 + */ + lenSent = sendto(pData->sock, msg, len, 0, &pData->addr, sizeof(pData->addr)); + if(lenSent == len) { + int eno = errno; + char errStr[1024]; + DBGPRINTF("omuxsock suspending: sendto(), socket %d, error: %d = %s.\n", + pData->sock, eno, rs_strerror_r(eno, errStr, sizeof(errStr))); + } + } + +finalize_it: + RETiRet; +} + + +/* open socket to remote system + */ +static inline rsRetVal +openSocket(instanceData *pData) +{ + DEFiRet; + assert(pData->sock == INVLD_SOCK); + + if((pData->sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { + char errStr[1024]; + int eno = errno; + DBGPRINTF("error %d creating AF_UNIX/SOCK_DGRAM: %s.\n", + eno, rs_strerror_r(eno, errStr, sizeof(errStr))); + pData->sock = INVLD_SOCK; + ABORT_FINALIZE(RS_RET_NO_SOCKET); + + } + + /* set up server address structure */ + memset(&pData->addr, 0, sizeof(pData->addr)); + pData->addr.sun_family = AF_UNIX; + strcpy(pData->addr.sun_path, (char*)pData->sockName); + +finalize_it: + if(iRet != RS_RET_OK) { + closeSocket(pData); + } + RETiRet; +} + + + +/* try to resume connection if it is not ready + */ +static rsRetVal doTryResume(instanceData *pData) +{ + DEFiRet; + + DBGPRINTF("omuxsock trying to resume\n"); + closeSocket(pData); + iRet = openSocket(pData); + + if(iRet != RS_RET_OK) { + iRet = RS_RET_SUSPENDED; + } + + RETiRet; +} + + +BEGINtryResume +CODESTARTtryResume + iRet = doTryResume(pData); +ENDtryResume + +BEGINdoAction + char *psz = NULL; /* temporary buffering */ + register unsigned l; + int iMaxLine; +CODESTARTdoAction + CHKiRet(doTryResume(pData)); + + iMaxLine = glbl.GetMaxLine(); + + DBGPRINTF(" omuxsock:%s\n", pData->sockName); + + psz = (char*) ppString[0]; + l = strlen((char*) psz); + if((int) l > iMaxLine) + l = iMaxLine; + + CHKiRet(sendMsg(pData, psz, l)); + +finalize_it: +ENDdoAction + + +BEGINparseSelectorAct +CODESTARTparseSelectorAct +CODE_STD_STRING_REQUESTparseSelectorAct(1) + + /* first check if this config line is actually for us */ + if(strncmp((char*) p, ":omuxsock:", sizeof(":omuxsock:") - 1)) { + ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); + } + + /* ok, if we reach this point, we have something for us */ + p += sizeof(":omuxsock:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ + CHKiRet(createInstance(&pData)); + + /* check if a non-standard template is to be applied */ + if(*(p-1) == ';') + --p; + CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, tplName == NULL ? UCHAR_CONSTANT("RSYSLOG_TraditionalForwardFormat") + : tplName )); + + if(sockName == NULL) { + errmsg.LogError(0, RS_RET_NO_SOCK_CONFIGURED, "No output socket configured for omuxsock\n"); + ABORT_FINALIZE(RS_RET_NO_SOCK_CONFIGURED); + } + + pData->sockName = sockName; + sockName = NULL; /* pData is now owner and will fee it */ + +CODE_STD_FINALIZERparseSelectorAct +ENDparseSelectorAct + + +/* a common function to free our configuration variables - used both on exit + * and on $ResetConfig processing. -- rgerhards, 2008-05-16 + */ +static inline void +freeConfigVars(void) +{ + free(tplName); + tplName = NULL; + free(sockName); + sockName = NULL; +} + + +BEGINmodExit +CODESTARTmodExit + /* release what we no longer need */ + objRelease(errmsg, CORE_COMPONENT); + objRelease(glbl, CORE_COMPONENT); + + freeConfigVars(); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_OMOD_QUERIES +ENDqueryEtryPt + + +/* Reset config variables for this module to default values. + * rgerhards, 2008-03-28 + */ +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + freeConfigVars(); + return RS_RET_OK; +} + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + + CHKiRet(regCfSysLineHdlr((uchar *)"omuxsockdefaulttemplate", 0, eCmdHdlrGetWord, NULL, &tplName, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"omuxsocksocket", 0, eCmdHdlrGetWord, NULL, &sockName, NULL)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +ENDmodInit + +/* vim:set ai: + */ diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index a8b5d401..81b446e3 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -449,6 +449,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_ERR_EPOLL_CTL = -2163, /**< epol_ctll() returned with an unexpected error code */ RS_RET_TIMEOUT = -2164, /**< timeout occured during operation */ RS_RET_RCV_ERR = -2165, /**< error occured during socket rcv operation */ + RS_RET_NO_SOCK_CONFIGURED = -2166, /**< no socket (name) was configured where one is required */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 7f9d8cd5..d630da3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ if ENABLE_TESTBENCH TESTRUNS = rt_init rscript -check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen diagtalker +check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen diagtalker uxsockrcvr TESTS = $(TESTRUNS) cfg.sh \ arrayqueue.sh \ linkedlistqueue.sh \ @@ -34,6 +34,7 @@ TESTS = $(TESTRUNS) cfg.sh \ complex1.sh \ queue-persist.sh \ pipeaction.sh \ + uxsock_simple.sh \ execonlyonce.sh \ execonlywhenprevsuspended.sh \ execonlywhenprevsuspended2.sh \ @@ -224,6 +225,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \ testsuites/pipeaction.conf \ pipe_noreader.sh \ testsuites/pipe_noreader.conf \ + uxsock_simple.sh \ + testsuites/uxsock_simple.conf \ asynwr_simple.sh \ testsuites/asynwr_simple.conf \ asynwr_timeout.sh \ @@ -293,6 +296,7 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \ testsuites/dircreate_off.conf \ cfg.sh +uxsockrcvr_SOURCES = uxsockrcvr.c ourtail_SOURCES = ourtail.c msleep_SOURCES = msleep.c chkseq_SOURCES = chkseq.c diff --git a/tests/testsuites/uxsock_simple.conf b/tests/testsuites/uxsock_simple.conf new file mode 100644 index 00000000..efffdd90 --- /dev/null +++ b/tests/testsuites/uxsock_simple.conf @@ -0,0 +1,10 @@ +# Test for pipe output action (see .sh file for details) +# rgerhards, 2009-11-05 +$IncludeConfig diag-common.conf + +$MainMsgQueueTimeoutShutdown 10000 + +$ModLoad ../plugins/omuxsock/.libs/omuxsock +$template outfmt,"%msg:F,58:2%\n" +$OMUXSockSocket rsyslog-testbench-dgram-uxsock +:msg, contains, "msgnum:" :omuxsock:;outfmt diff --git a/tests/uxsock_simple.sh b/tests/uxsock_simple.sh new file mode 100755 index 00000000..7f00f4bc --- /dev/null +++ b/tests/uxsock_simple.sh @@ -0,0 +1,31 @@ +# This tests basic omuxsock functionality. A socket receiver is started which sends +# all data to an output file, then a rsyslog instance is started which generates +# messages and sends them to the unix socket. Datagram sockets are being used. +# added 2010-08-06 by Rgerhards +echo =============================================================================== +echo \[uxsock_simple.sh\]: simple tests for omuxsock functionality + +# create the pipe and start a background process that copies data from +# it to the "regular" work file +source $srcdir/diag.sh init +./uxsockrcvr -srsyslog-testbench-dgram-uxsock -orsyslog.out.log & +BGPROCESS=$! +echo background uxsockrcvr process id is $BGPROCESS + +# now do the usual run +source $srcdir/diag.sh startup uxsock_simple.conf +# 10000 messages should be enough +source $srcdir/diag.sh injectmsg 0 10000 +source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages +source $srcdir/diag.sh wait-shutdown + +# wait for the cp process to finish, do pipe-specific cleanup +echo shutting down uxsockrcvr... +# TODO: we should do this more reliable in the long run! (message counter? timeout?) +kill $BGPROCESS +wait $BGPROCESS +echo background process has terminated, continue test... + +# and continue the usual checks +source $srcdir/diag.sh seq-check 0 9999 +source $srcdir/diag.sh exit diff --git a/tests/uxsockrcvr.c b/tests/uxsockrcvr.c new file mode 100644 index 00000000..551f0ef3 --- /dev/null +++ b/tests/uxsockrcvr.c @@ -0,0 +1,157 @@ +/* receives messages from a specified unix sockets and writes + * output to specfied file. + * + * Command line options: + * -s name of socket (required) + * -o name of output file (stdout if not given) + * -l add newline after each message received (default: do not add anything) + * + * Part of the testbench for rsyslog. + * + * Copyright 2010 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <getopt.h> +#include <sys/un.h> +#include <netdb.h> + +char *sockName = NULL; +int sock; +int addNL = 0; + + +/* called to clean up on exit + */ +void +cleanup(void) +{ + unlink(sockName); + close(sock); +} + + +void +doTerm(int __attribute__((unused)) signum) +{ + exit(1); +} + + +void +usage(void) +{ + fprintf(stderr, "usage: uxsockrcvr -s /socket/name -o /output/file -l\n" + "-l adds newline after each message received\n" + "-s MUST be specified\n" + "if -o ist not specified, stdout is used\n"); + exit(1); +} + + +int +main(int argc, char *argv[]) +{ + int opt; + int rlen; + FILE *fp = stdout; + unsigned char data[128*1024]; + struct sockaddr_un addr; /* address of server */ + struct sockaddr from; + socklen_t fromlen; + + if(argc < 2) { + fprintf(stderr, "error: too few arguments!\n"); + usage(); + } + + while((opt = getopt(argc, argv, "s:o:l")) != EOF) { + switch((char)opt) { + case 'l': + addNL = 1; + break; + case 's': + sockName = optarg; + break; + case 'o': + if((fp = fopen(optarg, "w")) == NULL) { + perror(optarg); + exit(1); + } + break; + default:usage(); + } + } + + if(sockName == NULL) { + fprintf(stderr, "error: -s /socket/name must be specified!\n"); + exit(1); + } + + if(signal(SIGTERM, doTerm) == SIG_ERR) { + perror("signal(SIGTERM, ...)"); + exit(1); + } + if(signal(SIGINT, doTerm) == SIG_ERR) { + perror("signal(SIGINT, ...)"); + exit(1); + } + + /* Create a UNIX datagram socket for server */ + if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { + perror("server: socket"); + exit(1); + } + + atexit(cleanup); + + /* Set up address structure for server socket */ + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, sockName); + + if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) { + close(sock); + perror("server: bind"); + exit(1); + } + + /* we now run in an endless loop. We do not check who sends us + * data. This should be no problem for our testbench use. + */ + while(1) { + fromlen = sizeof(from); + rlen = recvfrom(sock, data, 2000, 0, &from, &fromlen); + if(rlen == -1) { + perror("uxsockrcvr : recv\n"); + exit(1); + } else { + fwrite(data, 1, rlen, fp); + if(addNL) + fputc('\n', fp); + } + } + + return 0; +} |