From 80ff634c841d692c1d9f335b88e225d6ce7317f7 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 6 Aug 2010 17:25:38 +0200 Subject: added omuxsock, which permits to write message to local Unix sockets this is the counterpart to imuxsock, enabling fast local forwarding --- ChangeLog | 4 + Makefile.am | 7 +- configure.ac | 16 ++ doc/Makefile.am | 1 + doc/imuxsock.html | 2 +- doc/omuxsock.html | 43 +++++ doc/rsyslog_conf_modules.html | 1 + plugins/omuxsock/Makefile.am | 8 + plugins/omuxsock/omuxsock.c | 315 ++++++++++++++++++++++++++++++++++++ runtime/rsyslog.h | 1 + tests/Makefile.am | 8 +- tests/testsuites/uxsock_simple.conf | 10 ++ tests/uxsock_simple.sh | 31 ++++ tests/uxsockrcvr.c | 157 ++++++++++++++++++ 14 files changed, 600 insertions(+), 4 deletions(-) create mode 100644 doc/omuxsock.html create mode 100644 plugins/omuxsock/Makefile.am create mode 100644 plugins/omuxsock/omuxsock.c create mode 100644 tests/testsuites/uxsock_simple.conf create mode 100755 tests/uxsock_simple.sh create mode 100644 tests/uxsockrcvr.c diff --git a/ChangeLog b/ChangeLog index df0e77f1..1d5e05a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ --------------------------------------------------------------------------- +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 +--------------------------------------------------------------------------- Version 4.7.2 [v4-devel] (rgerhards), 2010-05-03 - bugfix: problems with atomic operations emulaton replaced atomic operation emulation with new code. The previous code diff --git a/Makefile.am b/Makefile.am index 8401606a..1a090abb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -99,6 +99,10 @@ if ENABLE_OMSTDOUT SUBDIRS += plugins/omstdout endif +if ENABLE_OMUXSOCK +SUBDIRS += plugins/omuxsock +endif + if ENABLE_OMTEMPLATE SUBDIRS += plugins/omtemplate endif @@ -138,5 +142,6 @@ SUBDIRS += tests # temporarily be removed below. The intent behind forcing everthing to compile # in a make distcheck is so that we detect code that accidently was not updated # when some global update happened. -DISTCHECK_CONFIGURE_FLAGS=--enable-gssapi_krb5 --enable-imfile --enable-snmp --enable-pgsql --enable-libdbi --enable-mysql --enable-omtemplate --enable-imtemplate --enable-relp --enable-rsyslogd --enable-mail --enable-klog --enable-diagtools --enable-gnutls --enable-omstdout --enable-omprog --enable-imdiag --enable-shave --enable-extended-tests +DISTCHECK_CONFIGURE_FLAGS=--enable-gssapi_krb5 --enable-imfile --enable-snmp --enable-pgsql --enable-libdbi --enable-mysql --enable-omtemplate --enable-imtemplate --enable-relp --enable-rsyslogd --enable-mail --enable-klog --enable-diagtools --enable-gnutls --enable-omstdout --enable-omprog --enable-imdiag --enable-shave --enable-extended-tests \ + --enable-omuxsock ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index 07ccabf5..ffbefa60 100644 --- a/configure.ac +++ b/configure.ac @@ -785,6 +785,20 @@ AC_ARG_ENABLE(omstdout, ) AM_CONDITIONAL(ENABLE_OMSTDOUT, test x$enable_omstdout = xyes) + +# 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. @@ -860,6 +874,7 @@ AC_CONFIG_FILES([Makefile \ plugins/omtemplate/Makefile \ plugins/omprog/Makefile \ plugins/omstdout/Makefile \ + plugins/omuxsock/Makefile \ plugins/imfile/Makefile \ plugins/imsolaris/Makefile \ plugins/imrelp/Makefile \ @@ -901,6 +916,7 @@ echo "---{ output plugins }---" echo " Mail support enabled: $enable_mail" echo " omprog module will be compiled: $enable_omprog" echo " omstdout module will be compiled: $enable_omstdout" +echo " omuxsock module will be compiled: $enable_omuxsock" echo " output template module will be compiled: $enable_omtemplate" echo echo "---{ database support }---" diff --git a/doc/Makefile.am b/doc/Makefile.am index 5beebf0e..24a0ea74 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -100,6 +100,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

This documentation is part of the rsyslog project.
-Copyright © 2008 by Rainer +Copyright © 2008-2010 by Rainer Gerhards and Adiscon. Released under the GNU GPL version 3 or higher.

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 @@ + +Unix sockets output module (omuxsock) - sending syslog messages to local socket +back + + +

Mail Output Module (omuxsock)

+

Module Name:    omuxsock

+

Available since:    4.7.3, 5.5.7

+

Author: Rainer Gerhards <rgerhards@adiscon.com>

+

Description:

+

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 imuxsock. +Note that the template used together with omuxsock must be suitable to be +processed by the receiver. +

Configuration Directives:

+ +Caveats/Known Bugs: +

Currently, only datagram sockets are supported. +

Sample:

+

The following sample writes all messages to the "/tmp/socksample" socket. +

+ +[manual index] [rsyslog site]

+

This documentation is part of the rsyslog +project.
+Copyright © 2010 by Rainer Gerhards and +Adiscon. +Released under the GNU GPL version 3 or higher.

+ + diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html index c36b8c6d..a6555c1a 100644 --- a/doc/rsyslog_conf_modules.html +++ b/doc/rsyslog_conf_modules.html @@ -52,6 +52,7 @@ SQLLite, Ingres, Oracle, mSQL)
  • ommail - permits rsyslog to alert folks by mail if something important happens
  • omoracle - output module for Oracle (native OCI interface)
  • +
  • omuxsock - output module Unix domain sockets
  • Library Modules

    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 . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include "rsyslog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 a6dfc9ed..04a57e43 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -377,6 +377,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_ERR_OPEN_KLOG = -2145, /**< error opening the kernel log socket (primarily solaris) */ RS_RET_ERR_AQ_CONLOG = -2146, /**< error aquiring console log (on solaris) */ RS_RET_ERR_DOOR = -2147, /**< some problems with handling the Solaris door functionality */ + RS_RET_NO_SOCK_CONFIGURED = -2148, /**< 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 8ec72d4f..201fbed6 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 \ validation-run.sh \ imtcp-multiport.sh \ @@ -26,7 +26,8 @@ TESTS = $(TESTRUNS) cfg.sh \ dynfile_invalid2.sh \ complex1.sh \ queue-persist.sh \ - pipeaction.sh + pipeaction.sh \ + uxsock_simple.sh \ execonlyonce.sh \ queue-persist.sh @@ -162,6 +163,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \ testsuites/sndrcv_gzip_rcvr.conf \ pipeaction.sh \ testsuites/pipeaction.conf \ + uxsock_simple.sh \ + testsuites/uxsock_simple.conf \ asynwr_simple.sh \ testsuites/asynwr_simple.conf \ asynwr_timeout.sh \ @@ -204,6 +207,7 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \ testsuites/execonlyonce.data \ 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 . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} -- cgit