File ucspi-tcp-0.88-systemd.patch of Package ucspi-tcp

(C) 2012 Peter Conrad <conrad@quisquis.de>

Licensed under the terms and conditions of the GNU General Public License
(version 2). See http://www.gnu.org/licenses/old-licenses/gpl-2.0 .

diff -rNU3 ucspi-tcp-0.88/Makefile ucspi-tcp-0.88.systemd/Makefile
--- ucspi-tcp-0.88/Makefile	2012-02-22 10:22:24.000000000 +0100
+++ ucspi-tcp-0.88.systemd/Makefile	2012-02-21 16:34:21.000000000 +0100
@@ -566,6 +566,16 @@
 compile subgetopt.c subgetopt.h
 	./compile subgetopt.c
 
+systemd.h: \
+trysystemd.c choose compile load systemd.h1 systemd.h2
+	cp /dev/null systemd.h
+	./choose cL trysystemd systemd.h1 systemd.h2 > systemd.h
+
+systemd.lib: \
+trysystemd.c choose compile load systemd.h1 systemd.h2
+	cp /dev/null systemd.lib
+	./choose cL trysystemd systemd.lib.1 systemd.lib.2 > systemd.lib
+
 systype: \
 find-systype.sh conf-cc conf-ld trycpp.c x86cpuid.c
 	( cat warn-auto.sh; \
@@ -651,9 +661,9 @@
 
 tcpserver: \
 load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a \
-time.a unix.a byte.a socket.lib
+time.a unix.a byte.a socket.lib systemd.lib
 	./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \
-	time.a unix.a byte.a  `cat socket.lib`
+	time.a unix.a byte.a  `cat socket.lib systemd.lib`
 
 tcpserver.o: \
 compile tcpserver.c uint16.h str.h byte.h fmt.h scan.h ip4.h fd.h \
@@ -661,7 +671,7 @@
 alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h \
 socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \
 stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \
-taia.h
+taia.h systemd.h
 	./compile tcpserver.c
 
 time.a: \
diff -rNU3 ucspi-tcp-0.88/systemd.h1 ucspi-tcp-0.88.systemd/systemd.h1
--- ucspi-tcp-0.88/systemd.h1	1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.h1	2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1 @@
+ 
diff -rNU3 ucspi-tcp-0.88/systemd.h2 ucspi-tcp-0.88.systemd/systemd.h2
--- ucspi-tcp-0.88/systemd.h2	1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.h2	2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1,9 @@
+#ifndef _MY_SYSTEMD_H_
+#define _MY_SYSTEMD_H_
+
+#include <systemd/sd-daemon.h>
+#include <sys/socket.h>
+
+#define HAVE_SYSTEMD
+
+#endif
diff -rNU3 ucspi-tcp-0.88/systemd.lib.1 ucspi-tcp-0.88.systemd/systemd.lib.1
--- ucspi-tcp-0.88/systemd.lib.1	1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.lib.1	2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1 @@
+ 
diff -rNU3 ucspi-tcp-0.88/systemd.lib.2 ucspi-tcp-0.88.systemd/systemd.lib.2
--- ucspi-tcp-0.88/systemd.lib.2	1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.lib.2	2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1 @@
+-lsystemd-daemon
diff -rNU3 ucspi-tcp-0.88/TARGETS ucspi-tcp-0.88.systemd/TARGETS
--- ucspi-tcp-0.88/TARGETS	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.systemd/TARGETS	2012-02-21 16:33:30.000000000 +0100
@@ -169,3 +169,6 @@
 it
 setup
 check
+trysystemd
+systemd.h
+systemd.lib
diff -rNU3 ucspi-tcp-0.88/tcpserver.c ucspi-tcp-0.88.systemd/tcpserver.c
--- ucspi-tcp-0.88/tcpserver.c	2012-02-22 10:22:24.000000000 +0100
+++ ucspi-tcp-0.88.systemd/tcpserver.c	2012-02-22 10:36:56.000000000 +0100
@@ -37,7 +37,13 @@
 #include "rules.h"
 #include "sig.h"
 #include "dns.h"
+#include "systemd.h"
 
+#ifndef HAVE_SYSTEMD
+#define SD_CRIT		""
+#define SD_WARNING	""
+#define SD_INFO		""
+#endif
 
 #ifdef SOLARIS
 #include <kstat.h>
@@ -50,6 +56,8 @@
 #define loaddouble(la) ((double)(la) / FSCALE)
 #endif
 
+static int systemd_fds = 0;
+
 int verbosity = 1;
 int flagkillopts = 1;
 int flagdelay = 1;
@@ -107,7 +115,7 @@
 
 void drop_nomem(void)
 {
-  strerr_die2sys(111,DROP,"out of memory");
+  strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP, "out of memory");
 }
 void cats(char *s)
 {
@@ -139,7 +147,8 @@
 }
 void drop_rules(void)
 {
-  strerr_die4sys(111,DROP,"unable to read ",fnrules,": ");
+  strerr_die4sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		 "unable to read ", fnrules, ": ");
 }
 
 unsigned long limit = 40;
@@ -228,12 +237,14 @@
   if (getnameinfo((struct sockaddr *) &remote, sizeof(remote), remoteipstr, sizeof(remoteipstr),
 		  remoteportstr, sizeof(remoteportstr),
 		  NI_NUMERICHOST|NI_NUMERICSERV)) {
-    strerr_die2sys(111,DROP,"unable to get remote host + port: ");
+    strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		   "unable to get remote host + port: ");
   }
 
   if (verbosity >= 2) {
     strnum[fmt_ulong(strnum,getpid())] = 0;
-    strerr_warn4("tcpserver: pid ",strnum," from ",remoteipstr,0);
+    strerr_warn5(systemd_fds > 0 ? SD_INFO : "", "tcpserver: pid ", strnum,
+		 " from ", remoteipstr, 0);
   }
 
   if (flagkillopts)
@@ -244,16 +255,19 @@
   if (*banner) {
     buffer_init(&b,write,t,bspace,sizeof bspace);
     if (buffer_putsflush(&b,banner) == -1)
-      strerr_die2sys(111,DROP,"unable to print banner: ");
+      strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		     "unable to print banner: ");
   }
 
   if (getsockname(t,(struct sockaddr *) &local, &addrlen))
-    strerr_die2sys(111,DROP,"unable to get local address: ");
+    strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		   "unable to get local address: ");
 
   if (getnameinfo((struct sockaddr *) &local, sizeof(local), localipstr, sizeof(localipstr),
 		  localportstr, sizeof(localportstr),
 		  NI_NUMERICHOST|NI_NUMERICSERV)) {
-    strerr_die2sys(111,DROP,"unable to get local host + port: ");
+    strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		   "unable to get local host + port: ");
   }
 
   if (!localhost) {
@@ -393,7 +407,8 @@
       buffer_init(&b,write,t,bspace,sizeof bspace);
       buffer_puts(&b,diemsg);
       if (buffer_putsflush(&b,"\r\n") == -1)
-        strerr_die2sys(111,DROP,"unable to print diemsg: ");
+        strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		       "unable to print diemsg: ");
     }
     sleep(1);
     _exit(100);
@@ -403,7 +418,6 @@
 
 
 /* ---------------------------- parent */
-
 #define FATAL "tcpserver: fatal: "
 
 void usage(void)
@@ -435,7 +449,8 @@
   if (verbosity < 2) return;
   strnum[fmt_ulong(strnum,numchildren)] = 0;
   strnum2[fmt_ulong(strnum2,limit)] = 0;
-  strerr_warn4("tcpserver: status: ",strnum,"/",strnum2,0);
+  strerr_warn5(systemd_fds > 0 ? SD_INFO : "", "tcpserver: status: ", strnum,
+	       "/", strnum2, 0);
 }
 
 void sigterm()
@@ -453,11 +468,13 @@
     if (verbosity >= 2) {
       strnum[fmt_ulong(strnum,pid)] = 0;
       strnum2[fmt_ulong(strnum2,wstat)] = 0;
-      strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
+      strerr_warn5(systemd_fds > 0 ? SD_INFO : "", "tcpserver: end ", strnum,
+		   " status ", strnum2, 0);
     }
     if (numchildren) --numchildren; printstatus();
     for (u=0; u < limit; u++) if (child[u].pid == pid) { child[u].pid = 0; break; }
-    if (u == limit) strerr_die1x(111,"tcpserver: ERROR: dead child not found?!"); /* never happens */
+    if (u == limit) strerr_die2x(111, systemd_fds > 0 ? SD_CRIT : "",
+				 "tcpserver: ERROR: dead child not found?!"); /* never happens */
   }
 }
 
@@ -538,6 +555,22 @@
   sig_catch(sig_term,sigterm);
   sig_ignore(sig_pipe);
 
+#ifdef HAVE_SYSTEMD
+ if ((systemd_fds = sd_listen_fds(0)) > 0) {
+  for (s = 1; s < systemd_fds; s++) {
+    if (!(pid = fork())) {
+      break;
+    } else if (pid < 0) {
+      strerr_die2sys(111, SD_CRIT FATAL, "unable to fork(): ");
+    }
+  }
+  s += SD_LISTEN_FDS_START-1;
+  if (sd_is_socket(s, AF_UNSPEC, SOCK_STREAM, 1) <= 0)
+    strerr_die2x(111, SD_CRIT FATAL, "expected only listening STREAM sockets");
+  if (getsockname(s, (struct sockaddr *) &local, &addrlen))
+    strerr_die2sys(111, SD_CRIT FATAL, "unable to get local address: ");
+ } else {
+#endif
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_flags = AI_PASSIVE;
   if (hints.ai_family == AF_UNSPEC) {
@@ -570,18 +599,24 @@
     strerr_die2sys(111,FATAL,"unable to get local address: ");
   if (socket_listen(s,backlog) == -1)
     strerr_die2sys(111,FATAL,"unable to listen: ");
+#ifdef HAVE_SYSTEMD
+ }
+#endif
   ndelay_off(s);
 
   if (gid) if (prot_gid(gid) == -1)
-    strerr_die2sys(111,FATAL,"unable to set gid: ");
+    strerr_die2sys(111, systemd_fds > 0 ? SD_CRIT FATAL : FATAL,
+		   "unable to set gid: ");
   if (uid) if (prot_uid(uid) == -1)
-    strerr_die2sys(111,FATAL,"unable to set uid: ");
+    strerr_die2sys(111, systemd_fds > 0 ? SD_CRIT FATAL : FATAL,
+		   "unable to set uid: ");
 
  
   if (getnameinfo((struct sockaddr *) &local, sizeof(local), NULL, 0,
 		  localportstr, sizeof(localportstr),
 		  NI_NUMERICHOST|NI_NUMERICSERV)) {
-    strerr_die2sys(111,DROP,"unable to get local name: ");
+    strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		  "unable to get local name: ");
   }
   if (flag1) {
     buffer_init(&b,write,1,bspace,sizeof bspace);
@@ -613,15 +657,18 @@
         close(s);
         doit(t);
         if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1))
-	  strerr_die2sys(111,DROP,"unable to set up descriptors: ");
+	  strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+			 "unable to set up descriptors: ");
         sig_uncatch(sig_child);
         sig_unblock(sig_child);
         sig_uncatch(sig_term);
         sig_uncatch(sig_pipe);
         pathexec(argv);
-	strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
+	strerr_die4sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		       "unable to run ", *argv, ": ");
       case -1:
-        strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
+        strerr_warn2(systemd_fds > 0 ? SD_WARNING DROP : DROP,
+		     "unable to fork: ", &strerr_sys);
         --numchildren; printstatus();
         break;
       default:
@@ -633,7 +680,7 @@
 	    byte_copy(child[u].ip, 16, remote.sa6.sin6_addr.s6_addr);
 	  child[u].pid = pid; break;
 	}
-	if (u == limit) strerr_die1x(111,"tcpserver: ERROR: no empty space for new child?!"); /* never happens */
+	if (u == limit) strerr_die2x(111, systemd_fds > 0 ? SD_CRIT : "", "tcpserver: ERROR: no empty space for new child?!"); /* never happens */
     }
     close(t);
   }
diff -rNU3 ucspi-tcp-0.88/trysystemd.c ucspi-tcp-0.88.systemd/trysystemd.c
--- ucspi-tcp-0.88/trysystemd.c	1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/trysystemd.c	2012-02-21 16:30:17.000000000 +0100
@@ -0,0 +1,7 @@
+#include <systemd/sd-daemon.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+    argc = write(1, SD_INFO "OK", strlen(SD_INFO) + 2);
+}
+
diff -rNU3 ucspi-tcp-0.88/ucspi-tcp-0.88-man/tcpserver-systemd.8 ucspi-tcp-0.88.systemd/ucspi-tcp-0.88-man/tcpserver-systemd.8
--- ucspi-tcp-0.88/ucspi-tcp-0.88-man/tcpserver-systemd.8	1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/ucspi-tcp-0.88-man/tcpserver-systemd.8	2012-02-22 10:59:22.000000000 +0100
@@ -0,0 +1,163 @@
+.TH tcpserver 8
+.SH NAME
+tcpserver \- tcpserver accepts incoming TCP connections.
+.SH SYNOPSIS
+\fBtcpserver\fI opts host port prog
+.SH DESCRIPTION
+\fIopts\fR is a series of getopt-style options:
+.TP
+\fIhost\fR
+is one argument.
+.TP
+\fIport\fR
+is one argument.
+.TP
+\fIprog\fR
+consists of one or more arguments.
+.PP
+\fBtcpserver\fR waits for connections from TCP clients.  For each connection, it runs
+\fIprog\fR, with descriptor 0 reading from the network and descriptor 1 
+writing to the network.  It also sets up several environment variables.
+.PP
+The server's address is given by \fIhost\fR and \fIport\fR.  \fIport\fR
+may be a name from /etc/services or a number; if it is 0, \fBtcpserver\fR
+will choose a free TCP port.  \fIhost\fR may be 0, allowing connections to 
+any local IP address; or a dotted-decimal IP address, allowing connections 
+only to that address; or a host name, allowing connections to the \fIfirst\fR 
+IP address for that host.  Host names are fed through qualification using 
+dns_ip4_qualify.
+.PP
+\fBtcpserver\fR exits when it receives SIGTERM.
+.PP
+\fBtcpserver\fR also has the following options:
+.PP
+General options:
+.TP
+\fB-q\fR
+Quiet.  Do not print error messages.
+.TP
+\fB-Q\fR
+(Default.)  Print error messages.
+.TP
+\fB-v\fR
+Verbose.  Print error messages and status messages.
+.PP
+Connection options:
+.TP
+\fB-c\fR n
+Do not handle more than n simultaneous connections.  If there are n
+simultaneous copies of \fIprog\fR running, defer acceptance of a new
+connection until one copy finishes.  n must be a positive integer.  Default:
+40.
+.TP
+\fB-x\fR cdb
+Follow the rules compiled into cdb by tcprules.  These rules may specify
+setting environment variables or rejecting connections from bad sources. 
+You can rerun tcprules to change the rules while \fBtcpserver\fR is running. 
+.TP
+\fB-X\fR
+With -x cdb, allows connections even if cdb does not exist.  Normally
+\fBtcpserver\fR will drop the connection if cdb does not exist.
+.TP
+\fB-B\fR banner
+Write banner to the network immediately after each connection is made. 
+\fBtcpserver\fR writes banner before looking up \fI$TCPREMOTEHOST\fR, before
+looking up \fI$TCPREMOTEINFO\fR, and before checking cdb.  This feature can be
+used to reduce latency in protocols where the client waits for a greeting
+from the server.
+.TP
+\fB-g\fR gid
+Switch group ID to gid after preparing to receive connections.  gid must be
+a positive integer.
+.TP
+\fB-u\fR uid
+Switch user ID to uid after preparing to receive connections.  uid must be a
+positive integer.
+.TP
+\fB-U\fR
+Same as \fI-g $GID -u $UID\fR.  Typically \fI$GID\fR and \fI$UID\fR are set 
+by \fBenvuidgid\fR.
+.TP
+\fB-1\fR
+After preparing to receive connections, print the local port number to 
+standard output.
+.TP
+\fB-b\fR n
+Allow a backlog of approximately n TCP SYNs.  On some systems, n is silently 
+limited to 5.  On systems supporting SYN cookies, the backlog is irrelevant.
+.TP
+\fB-o\fR
+Leave IP options alone.  If the client is sending packets along an IP source 
+route, send packets back along the same route.
+.TP
+\fB-O\fR
+(Default.) Kill IP options.  A client can still use source routing to connect 
+and to send data, but packets will be sent back along the default route.
+.TP
+\fB-d\fR
+Delay sending data for a fraction of a second whenever the remote host is 
+responding slowly.  This is currently the default, but it may not be in the 
+future; if you want it, set it explicitly.
+.TP
+\fB-D\fR
+Never delay sending data; enable \fITCP_NODELAY\fR.
+.PP
+Data-gathering options:
+.TP
+\fB-h\fR
+(Default.)  Look up the remote host name in DNS to set the environment variable 
+$TCPREMOTEHOST.
+.TP
+\fB-H\fR
+Do not look up the remote host name in DNS; remove the environment variable 
+\fI$TCPREMOTEHOST\fR.  To avoid loops, you \fImust\fR use this option for servers 
+on TCP port 53.
+.TP
+\fB-p\fR
+Paranoid.  After looking up the remote host name in DNS, look up the IP 
+addresses in DNS for that host name, and remove the environment variable 
+\fI$TCPREMOTEHOST\fR if none of the addresses match the client's IP address.
+.TP
+\fB-P\fR
+(Default.) Not paranoid.
+.TP
+\fB-l\fR localname
+Do not look up the local host name in DNS; use localname for the environment 
+variable \fI$TCPLOCALHOST\fR.  A common choice for localname is 0.  To avoid loops,
+you \fImust\fR use this option for servers on TCP port 53.
+.TP
+\fB-r\fR
+(Default.)  Attempt to obtain \fI$TCPREMOTEINFO\fR from the remote host.
+.TP
+\fB-R\fR
+Do not attempt to obtain \fI$TCPREMOTEINFO\fR from the remote host.  To avoid loops,
+you \fImust\fR use this option for servers on TCP ports 53 and 113.
+.TP
+\fB-t\fR n
+Give up on the \fI$TCPREMOTEINFO\fR connection attempt after n seconds.  Default: 26.
+.TP
+\fB-4\fR
+Listen on an IPv4 socket only. Default is to use what's available (see
+.B AI_ADDRCONFIG
+in
+.BR getaddrinfo(3) ).
+.TP
+\fB-6\fR
+Listen on an IPv6 socket only. Default is to use what's available (see
+.B AI_ADDRCONFIG
+in
+.BR getaddrinfo(3) ).
+
+\fBtcpserver\fR also supports the \fBsd-daemon\fR(1) interface. In particular,
+when \fBtcpserver\fR is run as a socket-activated service from \fBsystemd\fR(1),
+it will use the listening sockets provided by \fBsystemd\fR(1) and ignore the
+host and port arguments (which must still be present).
+
+Note that when run from systemd, tcpserver will create a separate process for
+each provided listening socket. This means that certain command line options
+(in particular \fB-c\fR) apply to each listening socket separately.
+
+.SH SEE ALSO
+tcp-environ(5),
+tcprules(8),
+envuidgid(8)
--- ucspi-tcp-0.88/tcpserver.c.orig	2012-02-23 15:28:47.000000000 +0100
+++ ucspi-tcp-0.88/tcpserver.c	2012-02-23 15:32:07.000000000 +0100
@@ -396,6 +396,7 @@
     	cats(" "); safecats ("MAXCONNC"); cats(":"); safecats(maxconstr);
     }
     cats("\n");
+    if (systemd_fds > 0) { buffer_puts(buffer_2, SD_INFO); }
     buffer_putflush(buffer_2,tmp.s,tmp.len);
   }
 
openSUSE Build Service is sponsored by