/* 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) * -t timeout in seconds (default 60) * * 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 #if defined(_AIX) #include #include #include #include #else #include #endif #include #include #include #include #if defined(__FreeBSD__) #include #endif #define DFLT_TIMEOUT 60 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; int timeout = DFLT_TIMEOUT; FILE *fp = stdout; unsigned char data[128*1024]; struct sockaddr_un addr; /* address of server */ struct sockaddr from; socklen_t fromlen; struct pollfd fds[1]; if(argc < 2) { fprintf(stderr, "error: too few arguments!\n"); usage(); } while((opt = getopt(argc, argv, "s:o:lt:")) != 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; case 't': timeout = atoi(optarg); break; default:usage(); } } timeout = timeout * 1000; 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); } fds[0].fd = sock; fds[0].events = POLLIN; /* 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 = poll(fds, 1, timeout); if(rlen == -1) { perror("uxsockrcvr : poll\n"); exit(1); } else if(rlen == 0) { fprintf(stderr, "Socket timed out - nothing to receive\n"); exit(1); } else { 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; }