]> jfr.im git - solanum.git/commitdiff
replacing ssld with servlink
authorValery Yatsko <redacted>
Wed, 2 Apr 2008 13:00:18 +0000 (17:00 +0400)
committerValery Yatsko <redacted>
Wed, 2 Apr 2008 13:00:18 +0000 (17:00 +0400)
16 files changed:
Makefile.in
include/s_conf.h
servlink/.cvsignore [deleted file]
servlink/.indent.pro [deleted file]
servlink/Makefile.in [deleted file]
servlink/README [deleted file]
servlink/TODO [deleted file]
servlink/control.c [deleted file]
servlink/control.h [deleted file]
servlink/io.c [deleted file]
servlink/io.h [deleted file]
servlink/servlink.c [deleted file]
servlink/servlink.h [deleted file]
ssld/Makefile.am [new file with mode: 0644]
ssld/Makefile.in [new file with mode: 0644]
ssld/ssld.c [new file with mode: 0644]

index 7714844d8a121b7281989d54a9f2b6afd237d58e..f86c522ccc00488f646a3f7a83ccfc6dd7bb5d83 100644 (file)
@@ -46,7 +46,7 @@ CFLAGS                = @CFLAGS@
 # the system one.
 #CFLAGS= -DNDEBUG -g -O2 -D"FD_SETSIZE=1024"
 SHELL=/bin/sh
-SUBDIRS=libratbox modules extensions src tools servlink doc help
+SUBDIRS=libratbox modules extensions src tools ssld doc help
 CLEANDIRS = ${SUBDIRS}
 RSA_FILES=rsa_respond/README rsa_respond/respond.c rsa_respond/Makefile
 
index 3fa389dcea2d369b672333b48d4df9c4d2976052..5b9174816f4e916b5e8f97303ef80f8cd35f706d 100644 (file)
@@ -54,22 +54,26 @@ struct ip_value
 extern FILE *conf_fbfile_in;
 extern char conf_line_in[256];
 
-struct ConfItem
-{
-       struct ConfItem *next;  /* list node pointer */
-       unsigned int status;    /* If CONF_ILLEGAL, delete when no clients */
-       unsigned int flags;
-       int clients;            /* Number of *LOCAL* clients using this */
-       char *name;             /* IRC name, nick, server name, or original u@h */
-       char *host;             /* host part of user@host */
-       char *passwd;           /* doubles as kline reason *ugh* */
-       char *spasswd;          /* Password to send. */
-       char *user;             /* user part of user@host */
-       int port;
-       time_t hold;            /* Hold action until this time (calendar time) */
-       char *className;        /* Name of class */
-       struct Class *c_class;  /* Class of connection */
-       rb_patricia_node_t *pnode;      /* Our patricia node */
+struct ConfItem\r
+{\r
+       unsigned int status;    /* If CONF_ILLEGAL, delete when no clients */\r
+       unsigned int flags;\r
+       int clients;            /* Number of *LOCAL* clients using this */\r
+\r
+       union\r
+       {\r
+               char *name;             /* IRC name, nick, server name, or original u@h */\r
+               const char *oper;\r
+       } info;\r
+\r
+       char *host;             /* host part of user@host */\r
+       char *passwd;           /* doubles as kline reason *ugh* */\r
+       char *spasswd;          /* Password to send. */\r
+       char *user;             /* user part of user@host */\r
+       int port;\r
+       time_t hold;            /* Hold action until this time (calendar time) */\r
+       struct Class *c_class;  /* Class of connection */\r
+       rb_patricia_node_t *pnode;\r
 };
 
 #define CONF_ILLEGAL            0x80000000
diff --git a/servlink/.cvsignore b/servlink/.cvsignore
deleted file mode 100644 (file)
index 224f7c6..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-setup.h
-servlink
diff --git a/servlink/.indent.pro b/servlink/.indent.pro
deleted file mode 100644 (file)
index a498166..0000000
+++ /dev/null
@@ -1 +0,0 @@
--i8 -bli0 -ut -nsai -l100 -npcs
\ No newline at end of file
diff --git a/servlink/Makefile.in b/servlink/Makefile.in
deleted file mode 100644 (file)
index a047012..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# Makefile.in for servlink/src
-#
-# $Id: Makefile.in 1285 2006-05-05 15:03:53Z nenolod $
-#
-
-CC              = @CC@
-INSTALL         = @INSTALL@
-INSTALL_BIN     = @INSTALL_PROGRAM@
-INSTALL_DATA    = @INSTALL_DATA@
-INSTALL_SUID    = @INSTALL_PROGRAM@ -o root -m 4755
-RM              = @RM@
-LEX             = @LEX@
-LEXLIB          = @LEXLIB@
-CFLAGS          = @IRC_CFLAGS@ -DIRCD_PREFIX=\"@prefix@\"
-LDFLAGS         = @LDFLAGS@
-MKDEP           = @MKDEP@ -DIRCD_PREFIX=\"@prefix@\"
-MV              = @MV@
-RM              = @RM@
-prefix          = @prefix@
-exec_prefix     = @exec_prefix@
-bindir          = @bindir@
-libexecdir      = @libexecdir@
-confdir         = @confdir@
-localstatedir   = @localstatedir@
-
-ZIP_LIB                = @ZLIB_LD@
-
-IRCDLIBS        = @LIBS@ $(ZIP_LIB)
-
-INCLUDES        = -I. -I../include $(SSL_INCLUDES)
-CPPFLAGS        = ${INCLUDES} @CPPFLAGS@
-
-PROGS          = servlink
-
-SOURCES =     \
-  servlink.c  \
-  io.c        \
-  control.c
-  
-
-OBJECTS = ${SOURCES:.c=.o}
-
-all: servlink
-
-build: all
-
-servlink: ${OBJECTS}
-       ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJECTS} ${IRCDLIBS}
-
-install: build
-       @echo "ircd: installing servlink ($(PROGS))"
-       @for i in $(PROGS); do \
-                if test -f $(DESTDIR)$(bindir)/$$i; then \
-                        $(MV) $(DESTDIR)$(bindir)/$$i $(DESTDIR)$(bindir)/$$i.old; \
-                fi; \
-                $(INSTALL_BIN) $$i $(DESTDIR)$(bindir); \
-        done
-
-.c.o:
-       ${CC} ${CPPFLAGS} ${CFLAGS} -c $<
-
-.PHONY: depend clean distclean
-depend:
-       @${MKDEP} ${CPPFLAGS} ${SOURCES} > .depend.tmp
-       @sed -e '/^# DO NOT DELETE THIS LINE/,$$d' <Makefile >Makefile.depend
-       @echo '# DO NOT DELETE THIS LINE!!!' >>Makefile.depend
-       @echo '# make depend needs it.' >>Makefile.depend
-       @cat .depend.tmp >>Makefile.depend
-       @mv Makefile.depend Makefile
-       @rm -f .depend.tmp
-
-clean:
-       ${RM} -f *.o *~ *.core core servlink
-
-lint:
-       lint -aacgprxhH $(CPPFLAGS) -DIRCD_PREFIX=\"@prefix@\" $(SOURCES) >>../lint.out
-
-distclean: clean
-       ${RM} -f Makefile
-
-# End of Makefile
diff --git a/servlink/README b/servlink/README
deleted file mode 100644 (file)
index 2ccfcd6..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-Servlink protocol documentation.
-$Id: README 1285 2006-05-05 15:03:53Z nenolod $
---------------
-
-After negotiating an incoming/outgoing server connection, the ircd will
-fork, then execve servlink, with fd 0 as one end of a control pipe and
-fd 1 as one end of a data pipe. fd 2 will be the socket connected to
-the remote server.
-
-The data pipe is used by the ircd to send/receive normal, decrypted,
-uncompressed IRC commands to/from the remote server.  The socket is used to
-send the (processed) data to the remote server, and receive the data from
-the remote server.
-
-The control pipe is used to activate encryption/compression and to set the
-encryption key/algorithm to be used.
-
-Format of control messages:
-
-<u8 command><optional data>
-
-data format:
-<u16 len><data>
-
-Commands:
-
-001 - SET_ZIP_OUT_LEVEL
-       data: yes
-       description:
-               set compression level (0 [use default, 6], or 1-9)
-
-002 - START_ZIP_OUT
-       data: no
-       description:
-               all data written to the data pipe will be compressed
-               prior to being sent to the remote server.
-
-003 - START_ZIP_IN
-       data: no
-       description:
-               all data not yet read from the slink program will be
-               decompressed before reading
-
-004 - INJECT_RECVQ
-       data: recvq
-
-       Used before INIT to inject any data read from the server fd which
-       should be pre-processed by servlink before being sent back
-       to the LOCAL_FD through the data fd.
-
-005 - INJECT_SENDQ
-       data: sendq
-
-       As above, but sent to remote server without processing.
-
-006 - INIT
-
-007 - ZIPSTATS
-       request to send ziplinks statistics reply.
-
-replies
-
-001 - ERROR
-       data: u32 len/char error[len]
-
-       fatal error message.
-
-002 - ZIPSTATS
-        data: u32 in/u32 in_wire/u32 out/u32 out_wire                           
-
-       ziplinks commpression statistics
diff --git a/servlink/TODO b/servlink/TODO
deleted file mode 100644 (file)
index 6fcefa1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Servlink todo list
-$Id: TODO 6 2005-09-10 01:02:21Z nenolod $
-------------------
-
-Fix any bugs that come up
-
-Think of improvements :)
diff --git a/servlink/control.c b/servlink/control.c
deleted file mode 100644 (file)
index 1f341a7..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/************************************************************************
- *   IRC - Internet Relay Chat, servlink/servlink.c
- *
- *   This program 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 1, or (at your option)
- *   any later version.
- *
- *   This program 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 this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   $Id: control.c 1285 2006-05-05 15:03:53Z nenolod $
- */
-
-#include "setup.h"
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-#include "servlink.h"
-#include "io.h"
-#include "control.h"
-
-static cmd_handler cmd_set_zip_out_level;
-static cmd_handler cmd_start_zip_out;
-static cmd_handler cmd_start_zip_in;
-static cmd_handler cmd_init;
-
-struct command_def command_table[] = {
-       {CMD_SET_ZIP_OUT_LEVEL, cmd_set_zip_out_level, COMMAND_FLAG_DATA},
-       {CMD_START_ZIP_OUT, cmd_start_zip_out, 0},
-       {CMD_START_ZIP_IN, cmd_start_zip_in, 0},
-       {CMD_INJECT_RECVQ, process_recvq, COMMAND_FLAG_DATA},
-       {CMD_INJECT_SENDQ, process_sendq, COMMAND_FLAG_DATA},
-       {CMD_INIT, cmd_init, 0},
-       {CMD_ZIPSTATS, send_zipstats, 0},
-       {0, 0, 0}
-};
-
-void
-cmd_set_zip_out_level(struct ctrl_command *cmd)
-{
-#ifdef HAVE_LIBZ
-       out_state.zip_state.level = *cmd->data;
-       if((out_state.zip_state.level < -1) || (out_state.zip_state.level > 9))
-               send_error("invalid compression level %d", out_state.zip_state.level);
-#else
-       send_error("can't set compression level - no libz support!");
-#endif
-}
-
-void
-cmd_start_zip_out(struct ctrl_command *cmd)
-{
-#ifdef HAVE_LIBZ
-       int ret;
-
-       if(out_state.zip)
-               send_error("can't start compression - already started!");
-
-       out_state.zip_state.z_stream.total_in = 0;
-       out_state.zip_state.z_stream.total_out = 0;
-       out_state.zip_state.z_stream.zalloc = (alloc_func) 0;
-       out_state.zip_state.z_stream.zfree = (free_func) 0;
-       out_state.zip_state.z_stream.data_type = Z_ASCII;
-
-       if(out_state.zip_state.level <= 0)
-               out_state.zip_state.level = Z_DEFAULT_COMPRESSION;
-
-       if((ret = deflateInit(&out_state.zip_state.z_stream, out_state.zip_state.level)) != Z_OK)
-               send_error("deflateInit failed: %s", zError(ret));
-
-       out_state.zip = 1;
-#else
-       send_error("can't start compression - no libz support!");
-#endif
-}
-
-void
-cmd_start_zip_in(struct ctrl_command *cmd)
-{
-#ifdef HAVE_LIBZ
-       int ret;
-
-       if(in_state.zip)
-               send_error("can't start decompression - already started!");
-
-       in_state.zip_state.z_stream.total_in = 0;
-       in_state.zip_state.z_stream.total_out = 0;
-       in_state.zip_state.z_stream.zalloc = (alloc_func) 0;
-       in_state.zip_state.z_stream.zfree = (free_func) 0;
-       in_state.zip_state.z_stream.data_type = Z_ASCII;
-       if((ret = inflateInit(&in_state.zip_state.z_stream)) != Z_OK)
-               send_error("inflateInit failed: %s", zError(ret));
-       in_state.zip = 1;
-#else
-       send_error("can't start decompression - no libz support!");
-#endif
-}
-
-
-void
-cmd_init(struct ctrl_command *cmd)
-{
-       if(in_state.active || out_state.active)
-               send_error("CMD_INIT sent twice!");
-
-       in_state.active = 1;
-       out_state.active = 1;
-       CONTROL.read_cb = read_ctrl;
-       CONTROL.write_cb = NULL;
-       LOCAL.read_cb = read_data;
-       LOCAL.write_cb = NULL;
-       REMOTE.read_cb = read_net;
-       REMOTE.write_cb = NULL;
-}
diff --git a/servlink/control.h b/servlink/control.h
deleted file mode 100644 (file)
index 294eeb9..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/************************************************************************
- *   IRC - Internet Relay Chat, servlink/control.h
- *
- *   This program 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 1, or (at your option)
- *   any later version.
- *
- *   This program 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 this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   $Id: control.h 1285 2006-05-05 15:03:53Z nenolod $
- */
-
-#ifndef INCLUDED_servlink_control_h
-#define INCLUDED_servlink_control_h
-
-#define CMD_SET_ZIP_OUT_LEVEL           1  /* data */
-#define CMD_START_ZIP_OUT               2
-#define CMD_START_ZIP_IN                3
-#define CMD_INJECT_RECVQ                4  /* data */
-#define CMD_INJECT_SENDQ                5  /* data */ 
-#define CMD_INIT                        6
-#define CMD_ZIPSTATS                    7
-
-#define RPL_ERROR                       1      /* data */
-#define RPL_ZIPSTATS                    2      /* data */
-
-/* flags */
-#define COMMAND_FLAG_DATA               0x0001 /* command has data
-                                                  following */
-struct ctrl_command
-{
-       int command;
-       int datalen;
-       int gotdatalen;
-       int readdata;
-       unsigned char *data;
-};
-
-typedef void cmd_handler(struct ctrl_command *);
-
-struct command_def
-{
-       unsigned int commandid;
-       cmd_handler *handler;
-       unsigned int flags;
-};
-
-extern struct command_def command_table[];
-#endif /* INCLUDED_servlink_control_h */
diff --git a/servlink/io.c b/servlink/io.c
deleted file mode 100644 (file)
index f4f91f2..0000000
+++ /dev/null
@@ -1,657 +0,0 @@
-/************************************************************************
- *   IRC - Internet Relay Chat, servlink/io.c
- *
- *   This program 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 1, or (at your option)
- *   any later version.
- *
- *   This program 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 this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   $Id: io.c 3319 2007-03-29 20:03:06Z jilles $
- */
-
-#include "setup.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-#include "servlink.h"
-#include "io.h"
-#include "control.h"
-
-static int check_error(int, int, int);
-
-static const char *
-fd_name(int fd)
-{
-       if(fd == CONTROL.fd)
-               return "control";
-       if(fd == LOCAL.fd)
-               return "data";
-       if(fd == REMOTE.fd)
-               return "network";
-
-       /* uh oh... */
-       return "unknown";
-}
-
-#if defined( HAVE_LIBZ )
-static unsigned char tmp_buf[BUFLEN];
-static unsigned char tmp2_buf[BUFLEN];
-#endif
-
-static unsigned char ctrl_buf[256] = "";
-static unsigned int ctrl_len = 0;
-static unsigned int ctrl_ofs = 0;
-
-void
-io_loop(int nfds)
-{
-       fd_set rfds;
-       fd_set wfds;
-       int i, ret;
-
-       /* loop forever */
-       for (;;)
-       {
-               FD_ZERO(&rfds);
-               FD_ZERO(&wfds);
-
-               for (i = 0; i < 3; i++)
-               {
-                       if(fds[i].read_cb)
-                               FD_SET(fds[i].fd, &rfds);
-                       if(fds[i].write_cb)
-                               FD_SET(fds[i].fd, &wfds);
-               }
-
-               /* we have <3 fds ever, so I don't think select is too painful */
-               ret = select(nfds, &rfds, &wfds, NULL, NULL);
-
-               if(ret < 0)
-               {
-                       check_error(ret, IO_SELECT, -1);        /* exit on fatal errors */
-               }
-               else if(ret > 0)
-               {
-                       /* call any callbacks */
-                       for (i = 2; i >= 0; i--)
-                       {
-                               if(FD_ISSET(fds[i].fd, &rfds) && fds[i].read_cb)
-                                       (*fds[i].read_cb) ();
-                               if(FD_ISSET(fds[i].fd, &wfds) && fds[i].write_cb)
-                                       (*fds[i].write_cb) ();
-                       }
-               }
-       }
-}
-
-void
-send_data_blocking(int fd, unsigned char *data, int datalen)
-{
-       int ret;
-       fd_set wfds;
-
-       while (1)
-       {
-               ret = write(fd, data, datalen);
-
-               if(ret == datalen)
-                       return;
-               else if(ret > 0)
-               {
-                       data += ret;
-                       datalen -= ret;
-               }
-
-               ret = check_error(ret, IO_WRITE, fd);
-
-               FD_ZERO(&wfds);
-               FD_SET(fd, &wfds);
-
-               /* sleep until we can write to the fd */
-               while (1)
-               {
-                       ret = select(fd + 1, NULL, &wfds, NULL, NULL);
-
-                       if(ret > 0)     /* break out so we can write */
-                               break;
-
-                       if(ret < 0)     /* error ? */
-                               check_error(ret, IO_SELECT, fd);        /* exit on fatal errors */
-
-                       /* loop on non-fatal errors */
-               }
-       }
-}
-
-/*
- * process_sendq:
- * 
- * used before CMD_INIT to pass contents of SendQ from ircd
- * to servlink.  This data must _not_ be encrypted/compressed.
- */
-void
-process_sendq(struct ctrl_command *cmd)
-{
-       send_data_blocking(REMOTE.fd, cmd->data, cmd->datalen);
-}
-
-/*
- * process_recvq:
- *
- * used before CMD_INIT to pass contents of RecvQ from ircd
- * to servlink.  This data must be decrypted/decopmressed before
- * sending back to the ircd.
- */
-void
-process_recvq(struct ctrl_command *cmd)
-{
-       int ret;
-       unsigned char *buf;
-       int blen;
-       unsigned char *data = cmd->data;
-       unsigned int datalen = cmd->datalen;
-
-       buf = data;
-       blen = datalen;
-       ret = -1;
-       if(datalen > READLEN)
-               send_error("Error processing INJECT_RECVQ - buffer too long (%d > %d)",
-                          datalen, READLEN);
-
-#ifdef HAVE_LIBZ
-       if(in_state.zip)
-       {
-               /* decompress data */
-               in_state.zip_state.z_stream.next_in = buf;
-               in_state.zip_state.z_stream.avail_in = blen;
-               in_state.zip_state.z_stream.next_out = tmp2_buf;
-               in_state.zip_state.z_stream.avail_out = BUFLEN;
-
-               buf = tmp2_buf;
-               while (in_state.zip_state.z_stream.avail_in)
-               {
-                       if((ret = inflate(&in_state.zip_state.z_stream, Z_NO_FLUSH)) != Z_OK)
-                       {
-                               if(!strncmp("ERROR ", (char *)in_state.zip_state.z_stream.next_in, 6))
-                                       send_error("Received uncompressed ERROR");
-                               else
-                                       send_error("Inflate failed: %s", zError(ret));
-                       }
-                       blen = BUFLEN - in_state.zip_state.z_stream.avail_out;
-
-                       if(in_state.zip_state.z_stream.avail_in)
-                       {
-                               send_data_blocking(LOCAL.fd, buf, blen);
-                               blen = 0;
-                               in_state.zip_state.z_stream.next_out = buf;
-                               in_state.zip_state.z_stream.avail_out = BUFLEN;
-                       }
-               }
-
-               if(!blen)
-                       return;
-       }
-#endif
-
-       send_data_blocking(LOCAL.fd, buf, blen);
-}
-
-void
-send_zipstats(struct ctrl_command *unused)
-{
-#ifdef HAVE_LIBZ
-       int i = 0;
-       int ret;
-       u_int32_t len;
-       if(!in_state.active || !out_state.active)
-               send_error("Error processing CMD_ZIPSTATS - link is not active!");
-       if(!in_state.zip || !out_state.zip)
-               send_error("Error processing CMD_ZIPSTATS - link is not compressed!");
-
-       ctrl_buf[i++] = RPL_ZIPSTATS;
-       ctrl_buf[i++] = 0;
-       ctrl_buf[i++] = 16;
-
-       len = (u_int32_t) in_state.zip_state.z_stream.total_out;
-       ctrl_buf[i++] = ((len >> 24) & 0xFF);
-       ctrl_buf[i++] = ((len >> 16) & 0xFF);
-       ctrl_buf[i++] = ((len >> 8) & 0xFF);
-       ctrl_buf[i++] = ((len) & 0xFF);
-
-       len = (u_int32_t) in_state.zip_state.z_stream.total_in;
-       ctrl_buf[i++] = ((len >> 24) & 0xFF);
-       ctrl_buf[i++] = ((len >> 16) & 0xFF);
-       ctrl_buf[i++] = ((len >> 8) & 0xFF);
-       ctrl_buf[i++] = ((len) & 0xFF);
-
-       len = (u_int32_t) out_state.zip_state.z_stream.total_in;
-       ctrl_buf[i++] = ((len >> 24) & 0xFF);
-       ctrl_buf[i++] = ((len >> 16) & 0xFF);
-       ctrl_buf[i++] = ((len >> 8) & 0xFF);
-       ctrl_buf[i++] = ((len) & 0xFF);
-
-       len = (u_int32_t) out_state.zip_state.z_stream.total_out;
-       ctrl_buf[i++] = ((len >> 24) & 0xFF);
-       ctrl_buf[i++] = ((len >> 16) & 0xFF);
-       ctrl_buf[i++] = ((len >> 8) & 0xFF);
-       ctrl_buf[i++] = ((len) & 0xFF);
-
-       in_state.zip_state.z_stream.total_in = 0;
-       in_state.zip_state.z_stream.total_out = 0;
-       out_state.zip_state.z_stream.total_in = 0;
-       out_state.zip_state.z_stream.total_out = 0;
-
-       ret = check_error(write(CONTROL.fd, ctrl_buf, i), IO_WRITE, CONTROL.fd);
-       if(ret < i)
-       {
-               /* write incomplete, register write cb */
-               CONTROL.write_cb = write_ctrl;
-               /*  deregister read_cb */
-               CONTROL.read_cb = NULL;
-               ctrl_ofs = ret;
-               ctrl_len = i - ret;
-               return;
-       }
-#else
-       send_error("can't send_zipstats -- no zlib support!");
-#endif
-}
-
-/* send_error
- *   - we ran into some problem, make a last ditch effort to 
- *     flush the control fd sendq, then (blocking) send an
- *     error message over the control fd.
- */
-void
-send_error(const char *message, ...)
-{
-       va_list args;
-       static int sending_error = 0;
-       struct linger linger_opt = { 1, 30 };   /* wait 30 seconds */
-       int len;
-
-       if(sending_error)
-               exit(1);        /* we did _try_ */
-
-       sending_error = 1;
-
-       if(ctrl_len)            /* attempt to flush any data we have... */
-       {
-               send_data_blocking(CONTROL.fd, (ctrl_buf + ctrl_ofs), ctrl_len);
-       }
-
-       /* prepare the message, in in_buf, since we won't be using it again.. */
-       in_state.buf[0] = RPL_ERROR;
-       in_state.buf[1] = 0;
-       in_state.buf[2] = 0;
-
-       va_start(args, message);
-       len = vsprintf((char *) in_state.buf + 3, message, args);
-       va_end(args);
-
-       in_state.buf[3 + len++] = '\0';
-       in_state.buf[1] = len >> 8;
-       in_state.buf[2] = len & 0xFF;
-       len += 3;
-
-       send_data_blocking(CONTROL.fd, in_state.buf, len);
-
-       /* XXX - is this portable?
-        *       this obviously will fail on a non socket.. */
-       setsockopt(CONTROL.fd, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(struct linger));
-
-       /* well, we've tried... */
-       exit(1);                /* now abort */
-}
-
-/* read_ctrl
- *      called when a command is waiting on the control pipe
- */
-void
-read_ctrl(void)
-{
-       int ret;
-       unsigned char tmp[2];
-       unsigned char *len;
-       struct command_def *cdef;
-       static struct ctrl_command cmd = { 0, 0, 0, 0, NULL };
-
-       if(cmd.command == 0)    /* we don't have a command yet */
-       {
-               cmd.gotdatalen = 0;
-               cmd.datalen = 0;
-               cmd.readdata = 0;
-               cmd.data = NULL;
-
-               /* read the command */
-               if(!(ret = check_error(read(CONTROL.fd, tmp, 1), IO_READ, CONTROL.fd)))
-                       return;
-
-               cmd.command = tmp[0];
-       }
-
-       for (cdef = command_table; cdef->commandid; cdef++)
-       {
-               if((int)cdef->commandid == cmd.command)
-                       break;
-       }
-
-       if(!cdef->commandid)
-       {
-               send_error("Unsupported command (servlink/ircd out of sync?): %d", cmd.command);
-               /* NOTREACHED */
-       }
-
-       /* read datalen for commands including data */
-       if(cdef->flags & COMMAND_FLAG_DATA)
-       {
-               if(cmd.gotdatalen < 2)
-               {
-                       len = tmp;
-                       if(!(ret = check_error(read(CONTROL.fd, len,
-                                                   (2 - cmd.gotdatalen)), IO_READ, CONTROL.fd)))
-                               return;
-
-                       if(cmd.gotdatalen == 0)
-                       {
-                               cmd.datalen = len[0] << 8;
-                               cmd.gotdatalen++;
-                               ret--;
-                               len++;
-                       }
-                       if(ret && (cmd.gotdatalen == 1))
-                       {
-                               cmd.datalen |= len[0];
-                               cmd.gotdatalen++;
-                               if(cmd.datalen > 0)
-                                       cmd.data = calloc(cmd.datalen, 1);
-                       }
-               }
-       }
-
-       if(cmd.readdata < cmd.datalen)  /* try to get any remaining data */
-       {
-               if(!(ret = check_error(read(CONTROL.fd,
-                                           (cmd.data + cmd.readdata),
-                                           cmd.datalen - cmd.readdata), IO_READ, CONTROL.fd)))
-                       return;
-
-               cmd.readdata += ret;
-               if(cmd.readdata < cmd.datalen)
-                       return;
-       }
-
-       /* we now have the command and any data */
-       (*cdef->handler) (&cmd);
-
-       if(cmd.datalen > 0)
-               free(cmd.data);
-       cmd.command = 0;
-}
-
-void
-write_ctrl(void)
-{
-       int ret;
-
-       assert(ctrl_len);
-
-       if(!(ret = check_error(write(CONTROL.fd, (ctrl_buf + ctrl_ofs),
-                                    ctrl_len), IO_WRITE, CONTROL.fd)))
-               return;         /* no data waiting */
-
-       ctrl_len -= ret;
-
-       if(!ctrl_len)
-       {
-               /* write completed, de-register write cb */
-               CONTROL.write_cb = NULL;
-               /* reregister read_cb */
-               CONTROL.read_cb = read_ctrl;
-               ctrl_ofs = 0;
-       }
-       else
-               ctrl_ofs += ret;
-}
-
-void
-read_data(void)
-{
-       int ret, ret2;
-       unsigned char *buf = out_state.buf;
-       int blen;
-       ret2 = -1;
-       assert(!out_state.len);
-
-#if defined(HAVE_LIBZ) 
-       if(out_state.zip || out_state.crypt)
-               buf = tmp_buf;
-#endif
-
-       while ((ret = check_error(read(LOCAL.fd, buf, READLEN), IO_READ, LOCAL.fd)))
-       {
-               blen = ret;
-#ifdef HAVE_LIBZ
-               if(out_state.zip)
-               {
-                       out_state.zip_state.z_stream.next_in = buf;
-                       out_state.zip_state.z_stream.avail_in = ret;
-
-                       buf = out_state.buf;
-                       out_state.zip_state.z_stream.next_out = buf;
-                       out_state.zip_state.z_stream.avail_out = BUFLEN;
-                       if(!(ret2 = deflate(&out_state.zip_state.z_stream,
-                                           Z_PARTIAL_FLUSH)) == Z_OK)
-                               send_error("error compressing outgoing data - deflate returned: %s",
-                                          zError(ret2));
-
-                       if(!out_state.zip_state.z_stream.avail_out)
-                               send_error("error compressing outgoing data - avail_out == 0");
-                       if(out_state.zip_state.z_stream.avail_in)
-                               send_error("error compressing outgoing data - avail_in != 0");
-
-                       blen = BUFLEN - out_state.zip_state.z_stream.avail_out;
-               }
-#endif
-
-
-               ret = check_error(write(REMOTE.fd, out_state.buf, blen), IO_WRITE, REMOTE.fd);
-               if(ret < blen)
-               {
-                       /* write incomplete, register write cb */
-                       REMOTE.write_cb = write_net;
-                       /*  deregister read_cb */
-                       LOCAL.read_cb = NULL;
-                       out_state.ofs = ret;
-                       out_state.len = blen - ret;
-                       return;
-               }
-#if defined(HAVE_LIBZ) 
-               if(out_state.zip)
-                       buf = tmp_buf;
-#endif
-       }
-
-}
-
-void
-write_net(void)
-{
-       int ret;
-
-       assert(out_state.len);
-
-       if(!(ret = check_error(write(REMOTE.fd,
-                                    (out_state.buf + out_state.ofs),
-                                    out_state.len), IO_WRITE, REMOTE.fd)))
-               return;         /* no data waiting */
-
-       out_state.len -= ret;
-
-       if(!out_state.len)
-       {
-               /* write completed, de-register write cb */
-               REMOTE.write_cb = NULL;
-               /* reregister read_cb */
-               LOCAL.read_cb = read_data;
-               out_state.ofs = 0;
-       }
-       else
-               out_state.ofs += ret;
-}
-
-void
-read_net(void)
-{
-       int ret;
-       int ret2;
-       unsigned char *buf = in_state.buf;
-       int blen;
-       ret2 = -1;
-       assert(!in_state.len);
-
-#if defined(HAVE_LIBZ)
-       if(in_state.zip)
-               buf = tmp_buf;
-#endif
-
-       while ((ret = check_error(read(REMOTE.fd, buf, READLEN), IO_READ, REMOTE.fd)))
-       {
-               blen = ret;
-#ifdef HAVE_LIBZ
-               if(in_state.zip)
-               {
-                       /* decompress data */
-                       in_state.zip_state.z_stream.next_in = buf;
-                       in_state.zip_state.z_stream.avail_in = ret;
-                       in_state.zip_state.z_stream.next_out = in_state.buf;
-                       in_state.zip_state.z_stream.avail_out = BUFLEN;
-
-                       while (in_state.zip_state.z_stream.avail_in)
-                       {
-                               if((ret2 = inflate(&in_state.zip_state.z_stream,
-                                                  Z_NO_FLUSH)) != Z_OK)
-                               {
-                                       if(!strncmp("ERROR ", (char *)buf, 6))
-                                               send_error("Received uncompressed ERROR");
-                                       send_error("Inflate failed: %s", zError(ret2));
-                               }
-                               blen = BUFLEN - in_state.zip_state.z_stream.avail_out;
-
-                               if(in_state.zip_state.z_stream.avail_in)
-                               {
-                                       if(blen)
-                                       {
-                                               send_data_blocking(LOCAL.fd, in_state.buf, blen);
-                                               blen = 0;
-                                       }
-
-                                       in_state.zip_state.z_stream.next_out = in_state.buf;
-                                       in_state.zip_state.z_stream.avail_out = BUFLEN;
-                               }
-                       }
-
-                       if(!blen)
-                               return; /* that didn't generate any decompressed input.. */
-               }
-#endif
-
-               ret = check_error(write(LOCAL.fd, in_state.buf, blen), IO_WRITE, LOCAL.fd);
-
-               if(ret < blen)
-               {
-                       in_state.ofs = ret;
-                       in_state.len = blen - ret;
-                       /* write incomplete, register write cb */
-                       LOCAL.write_cb = write_data;
-                       /* deregister read_cb */
-                       REMOTE.read_cb = NULL;
-                       return;
-               }
-#if defined(HAVE_LIBZ)
-               if(in_state.zip)
-                       buf = tmp_buf;
-#endif
-       }
-}
-
-void
-write_data(void)
-{
-       int ret;
-
-       assert(in_state.len);
-
-       if(!(ret = check_error(write(LOCAL.fd,
-                                    (in_state.buf + in_state.ofs),
-                                    in_state.len), IO_WRITE, LOCAL.fd)))
-               return;
-
-       in_state.len -= ret;
-
-       if(!in_state.len)
-       {
-               /* write completed, de-register write cb */
-               LOCAL.write_cb = NULL;
-               /* reregister read_cb */
-               REMOTE.read_cb = read_net;
-               in_state.ofs = 0;
-       }
-       else
-               in_state.ofs += ret;
-}
-
-int
-check_error(int ret, int io, int fd)
-{
-       if(ret > 0)             /* no error */
-               return ret;
-       if(ret == 0)            /* EOF */
-       {
-               send_error("%s failed on %s: EOF", IO_TYPE(io), FD_NAME(fd));
-               exit(1);        /* NOTREACHED */
-       }
-
-       /* ret == -1.. */
-       switch (errno)
-       {
-       case EINPROGRESS:
-       case EWOULDBLOCK:
-#if EAGAIN != EWOULDBLOCK
-       case EAGAIN:
-#endif
-       case EALREADY:
-       case EINTR:
-#ifdef ERESTART
-       case ERESTART:
-#endif
-               /* non-fatal error, 0 bytes read */
-               return 0;
-       }
-
-       /* fatal error */
-       send_error("%s failed on %s: %s", IO_TYPE(io), FD_NAME(fd), strerror(errno));
-       exit(1);                /* NOTREACHED */
-}
diff --git a/servlink/io.h b/servlink/io.h
deleted file mode 100644 (file)
index da2126a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/************************************************************************
- *   IRC - Internet Relay Chat, servlink/io.h
- *
- *   This program 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 1, or (at your option)
- *   any later version.
- *
- *   This program 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 this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   $Id: io.h 6 2005-09-10 01:02:21Z nenolod $
- */
-
-#ifndef INCLUDED_servlink_io_h
-#define INCLUDED_servlink_io_h
-
-#include "control.h"
-
-#define IO_READ                 0
-#define IO_WRITE                1
-#define IO_SELECT               2
-
-#define IO_TYPE(io)     ((io==IO_SELECT)?"select": \
-                         ((io==IO_WRITE)?"write":"read"))
-
-#define FD_NAME(fd)     (fd_name(fd))
-
-extern void io_loop(int nfds);
-extern void write_data(void);
-extern void read_data(void);
-extern void write_ctrl(void);
-extern void read_ctrl(void);
-extern void write_net(void);
-extern void read_net(void);
-extern void send_error(const char *, ...);
-extern void send_data_blocking(int fd, unsigned char *data, int datalen);
-extern cmd_handler process_recvq;
-extern cmd_handler process_sendq;
-extern cmd_handler send_zipstats;
-
-#endif /* INCLUDED_servlink_io_h */
diff --git a/servlink/servlink.c b/servlink/servlink.c
deleted file mode 100644 (file)
index 1276200..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/************************************************************************
- *   IRC - Internet Relay Chat, servlink/servlink.c
- *
- *   This program 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 1, or (at your option)
- *   any later version.
- *
- *   This program 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 this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   $Id: servlink.c 6 2005-09-10 01:02:21Z nenolod $
- */
-
-#include "setup.h"
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-#include "servlink.h"
-#include "io.h"
-#include "control.h"
-
-static void usage(void);
-
-struct slink_state in_state;
-struct slink_state out_state;
-
-struct fd_table fds[3] = {
-       {0, read_ctrl, NULL},   /* ctrl */
-       {0, NULL, NULL},        /* data */
-       {0, NULL, NULL},        /* net */
-};
-
-/* usage();
- *
- * Display usage message
- */
-static void
-usage(void)
-{
-       fprintf(stderr, "ircd-ratbox server link v1.2\n");
-       fprintf(stderr, "2004-03-02\n");
-       fprintf(stderr, "\n");
-       fprintf(stderr, "This program is called by the ircd-ratbox ircd.\n");
-       fprintf(stderr, "It cannot be used on its own.\n");
-       exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
-       int max_fd = 0;
-       int i, x;
-#ifdef SERVLINK_DEBUG
-       int GDBAttached = 0;
-
-       while (!GDBAttached)
-               sleep(1);
-#endif
-
-       /* Make sure we are running under ircd.. */
-       
-       if(argc != 4 || strcmp(argv[0], "-slink"))
-               usage();        /* exits */
-
-
-       for (i = 0; i < 3; i++)
-       {
-               fds[i].fd = atoi(argv[i + 1]);
-               if(fds[i].fd < 0)
-                       exit(1);
-       }
-
-       for (i = 0; i < 3; i++)
-       {               
-               /* XXX: Hack alert...we need to do dup2() here for some dumb
-                * platforms (Solaris) that don't like select using fds > 255
-                */
-
-               if(fds[i].fd >= 255)
-               {
-                       for(x = 0; x < 255; x++)
-                       {
-                               if(x != fds[0].fd && x != fds[1].fd && x != fds[2].fd)
-                               {
-                                       if(dup2(fds[i].fd, x) < 0)
-                                               exit(1);
-                                       close(fds[i].fd);
-                                       fds[i].fd = x;
-                                       break;
-                               }
-                       }
-               }               
-               fcntl(fds[i].fd, F_SETFL, O_NONBLOCK);
-               if(fds[i].fd > max_fd)
-                       max_fd = fds[i].fd;
-       }
-       
-       /* enter io loop */
-       io_loop(max_fd + 1);
-
-       /* NOTREACHED */
-       return (0);
-}                              /* main() */
diff --git a/servlink/servlink.h b/servlink/servlink.h
deleted file mode 100644 (file)
index a0f37de..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/************************************************************************
- *   IRC - Internet Relay Chat, servlink/servlink.h
- *
- *   This program 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 1, or (at your option)
- *   any later version.
- *
- *   This program 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 this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   $Id: servlink.h 1285 2006-05-05 15:03:53Z nenolod $
- */
-
-#ifndef INCLUDED_servlink_servlink_h
-#define INCLUDED_servlink_servlink_h
-
-#include "setup.h"
-
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-/* do not use stdin/out/err, as it seems to break on solaris */
-#define CONTROL               fds[0]
-#define LOCAL                 fds[1]
-#define REMOTE                 fds[2]
-
-#undef  SERVLINK_DEBUG
-
-#define READLEN                  16384
-
-#ifdef HAVE_LIBZ
-#define BUFLEN                   READLEN * 6   /* allow for decompression */
-#else
-#define BUFLEN                   READLEN
-#endif
-
-
-#ifdef HAVE_LIBZ
-struct zip_state
-{
-       z_stream z_stream;
-       int level;              /* compression level */
-};
-#endif
-
-struct slink_state
-{
-       unsigned int crypt:1;
-       unsigned int zip:1;
-       unsigned int active:1;
-
-       unsigned char buf[BUFLEN * 2];
-       unsigned int ofs;
-       unsigned int len;
-
-#ifdef HAVE_LIBZ
-       struct zip_state zip_state;
-#endif
-};
-
-
-typedef void (io_callback) (void);
-
-struct fd_table
-{
-       int fd;
-       io_callback *read_cb;
-       io_callback *write_cb;
-};
-
-extern struct slink_state in_state;
-extern struct slink_state out_state;
-extern struct fd_table fds[3];
-
-#endif /* INCLUDED_servlink_servlink_h */
diff --git a/ssld/Makefile.am b/ssld/Makefile.am
new file mode 100644 (file)
index 0000000..f6aeb4c
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# $Id: Makefile.am 24818 2008-01-02 18:38:26Z androsyn $
+#
+bin_PROGRAMS = ssld
+AM_CFLAGS=$(WARNFLAGS)
+
+INCLUDES = -I../include -I../libratbox/include 
+
+
+ssld_SOURCES = ssld.c
+
+ssld_LDADD = ../libratbox/src/libratbox.la @ZLIB_LD@
+
+
diff --git a/ssld/Makefile.in b/ssld/Makefile.in
new file mode 100644 (file)
index 0000000..7504608
--- /dev/null
@@ -0,0 +1,499 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = ssld$(EXEEXT)
+subdir = ssld
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/setup.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_ssld_OBJECTS = ssld.$(OBJEXT)
+ssld_OBJECTS = $(am_ssld_OBJECTS)
+ssld_DEPENDENCIES = ../libratbox/src/libratbox.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(ssld_SOURCES)
+DIST_SOURCES = $(ssld_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CP = @CP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETC_DIR = @ETC_DIR@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+HELP_DIR = @HELP_DIR@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IRCD_PREFIX = @IRCD_PREFIX@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBLTDL = @LIBLTDL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN = @LN@
+LN_S = @LN_S@
+LOG_DIR = @LOG_DIR@
+LTLIBOBJS = @LTLIBOBJS@
+LT_OBJDIR = @LT_OBJDIR@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MODULE_DIR = @MODULE_DIR@
+MV = @MV@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PICFLAGS = @PICFLAGS@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SEDOBJ = @SEDOBJ@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHLIBEXT = @SHLIBEXT@
+SQLITE_INCLUDES = @SQLITE_INCLUDES@
+SQLITE_LD = @SQLITE_LD@
+SQLITE_SUBDIR = @SQLITE_SUBDIR@
+SSL_INCLUDES = @SSL_INCLUDES@
+SSL_LIBS = @SSL_LIBS@
+SSL_SRCS_ENABLE = @SSL_SRCS_ENABLE@
+STRIP = @STRIP@
+TOUCH = @TOUCH@
+VERSION = @VERSION@
+WARNFLAGS = @WARNFLAGS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+ZLIB_LD = @ZLIB_LD@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+confdir = @confdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+helpdir = @helpdir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+logdir = @logdir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = $(WARNFLAGS)
+INCLUDES = -I../include -I../libratbox/include 
+ssld_SOURCES = ssld.c
+ssld_LDADD = ../libratbox/src/libratbox.la @ZLIB_LD@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  ssld/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --gnu  ssld/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+         rm -f "$(DESTDIR)$(bindir)/$$f"; \
+       done
+
+clean-binPROGRAMS:
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
+       done
+ssld$(EXEEXT): $(ssld_OBJECTS) $(ssld_DEPENDENCIES) 
+       @rm -f ssld$(EXEEXT)
+       $(LINK) $(ssld_OBJECTS) $(ssld_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssld.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic clean-libtool ctags distclean distclean-compile \
+       distclean-generic distclean-libtool distclean-tags distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-binPROGRAMS install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags uninstall uninstall-am \
+       uninstall-binPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ssld/ssld.c b/ssld/ssld.c
new file mode 100644 (file)
index 0000000..238201c
--- /dev/null
@@ -0,0 +1,1096 @@
+/*
+ *  ssld.c: The ircd-ratbox ssl/zlib helper daemon thingy
+ *  Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
+ *  Copyright (C) 2007 ircd-ratbox development team
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ *
+ *  $Id: ssld.c 25179 2008-03-30 16:34:57Z androsyn $
+ */
+
+
+#include "stdinc.h"
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+#define MAXPASSFD 4
+#ifndef READBUF_SIZE
+#define READBUF_SIZE 16384
+#endif
+
+static void setup_signals(void);
+
+static inline rb_int32_t buf_to_int32(char *buf)
+{
+       rb_int32_t x;
+       x = *buf << 24;
+       x |= *(++buf) << 16;
+       x |= *(++buf) << 8;
+       x |= *(++buf);
+       return x;
+}
+
+static inline void int32_to_buf(char *buf, rb_int32_t x)
+{
+       *(buf)   = x >> 24 & 0xFF;
+       *(++buf) = x >> 16 & 0xFF; 
+       *(++buf) = x >> 8 & 0xFF;
+       *(++buf) = x & 0xFF;
+       return;
+}
+
+static inline rb_uint16_t buf_to_uint16(char *buf)
+{
+       rb_uint16_t x;
+       x = *(buf) << 8;
+       x |= *(++buf);
+       return x;
+}
+
+static inline void uint16_to_buf(char *buf, rb_uint16_t x)
+{
+       *(buf) = x >> 8 & 0xFF;
+       *(++buf) = x & 0xFF;
+       return;
+}
+
+
+static char inbuf[READBUF_SIZE];
+static char outbuf[READBUF_SIZE];
+
+typedef struct _mod_ctl_buf
+{
+       rb_dlink_node node;
+       char *buf;
+       size_t buflen;
+       rb_fde_t *F[MAXPASSFD];
+       int nfds;
+} mod_ctl_buf_t;
+
+typedef struct _mod_ctl
+{
+       rb_dlink_node node;
+       int cli_count;
+       rb_fde_t *F;
+       rb_fde_t *F_pipe;
+       rb_dlink_list readq;
+       rb_dlink_list writeq;
+} mod_ctl_t;
+
+static mod_ctl_t *mod_ctl;
+
+
+#ifdef HAVE_ZLIB
+typedef struct _zlib_stream
+{
+       z_stream instream;
+       z_stream outstream;
+} zlib_stream_t;
+#endif
+
+typedef struct _conn
+{
+       rb_dlink_node node;
+       mod_ctl_t *ctl;
+       rawbuf_head_t *modbuf_out;
+       rawbuf_head_t *plainbuf_out;
+
+       rb_int32_t id;
+
+       rb_fde_t *mod_fd;
+       rb_fde_t *plain_fd;
+       unsigned long long mod_out;
+       unsigned long long mod_in;
+       unsigned long long plain_in;
+       unsigned long long plain_out;
+       rb_uint8_t flags;
+       void *stream;
+} conn_t;
+
+#define FLAG_SSL       0x01
+#define FLAG_ZIP       0x02
+#define FLAG_CORK      0x04
+#define FLAG_DEAD      0x08
+
+
+#define IsSSL(x) ((x)->flags & FLAG_SSL)
+#define IsZip(x) ((x)->flags & FLAG_ZIP)
+#define IsCork(x) ((x)->flags & FLAG_CORK)
+#define IsDead(x) ((x)->flags & FLAG_DEAD)
+
+#define SetSSL(x) ((x)->flags |= FLAG_SSL)
+#define SetZip(x) ((x)->flags |= FLAG_ZIP)
+#define SetCork(x) ((x)->flags |= FLAG_CORK)
+#define SetDead(x) ((x)->flags |= FLAG_DEAD)
+
+#define ClearSSL(x) ((x)->flags &= ~FLAG_SSL)
+#define ClearZip(x) ((x)->flags &= ~FLAG_ZIP)
+#define ClearCork(x) ((x)->flags &= ~FLAG_CORK)
+#define ClearDead(x) ((x)->flags &= ~FLAG_DEAD)
+
+#define NO_WAIT 0x0
+#define WAIT_PLAIN 0x1
+
+#define CONN_HASH_SIZE 2000
+#define connid_hash(x) (&connid_hash_table[(x % CONN_HASH_SIZE)])
+
+static rb_dlink_list connid_hash_table[CONN_HASH_SIZE];
+static rb_dlink_list dead_list;
+
+static void conn_mod_write_sendq(rb_fde_t *, void *data);
+static void conn_plain_write_sendq(rb_fde_t *, void *data);
+static void mod_write_ctl(rb_fde_t *, void *data);
+static void conn_plain_read_cb(rb_fde_t * fd, void *data);
+static void mod_cmd_write_queue(mod_ctl_t *ctl, const void *data, size_t len);
+static const char *remote_closed = "Remote host closed the connection";
+static int ssl_ok;
+#ifdef HAVE_ZLIB
+static int zlib_ok = 1;
+#else
+static int zlib_ok = 0;
+#endif
+static void *
+ssld_alloc(void *unused, size_t count, size_t size)
+{
+       return rb_malloc(count * size);
+}
+
+static void
+ssld_free(void *unused, void *ptr)
+{
+       rb_free(ptr);   
+}
+
+static conn_t *
+conn_find_by_id(rb_int32_t id)
+{
+       rb_dlink_node *ptr;
+       conn_t *conn;
+
+       RB_DLINK_FOREACH(ptr, (connid_hash(id))->head)
+       {
+               conn = ptr->data;
+               if(conn->id == id && !IsDead(conn))
+                       return conn;
+       }
+       return NULL;
+}
+
+static void
+conn_add_id_hash(conn_t * conn, rb_int32_t id)
+{
+       conn->id = id;
+       rb_dlinkAdd(conn, &conn->node, connid_hash(id));
+}
+
+static void
+free_conn(conn_t * conn)
+{
+       rb_free_rawbuffer(conn->modbuf_out);
+       rb_free_rawbuffer(conn->plainbuf_out);
+       if(IsZip(conn))
+       {
+               zlib_stream_t *stream = conn->stream;
+               inflateEnd(&stream->instream);
+               deflateEnd(&stream->outstream);         
+       }
+       rb_free(conn);
+}
+
+static void
+clean_dead_conns(void *unused)
+{
+       conn_t *conn;
+       rb_dlink_node *ptr, *next;
+       RB_DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
+       {
+               conn = ptr->data;
+               free_conn(conn);
+       }
+       dead_list.tail = dead_list.head = NULL;
+}
+
+
+static void
+close_conn(conn_t * conn, int wait_plain, const char *fmt, ...)
+{
+       va_list ap;
+       char reason[128]; /* must always be under 250 bytes */
+       char buf[256];
+       int len;
+       if(IsDead(conn))
+               return;
+       
+       rb_rawbuf_flush(conn->modbuf_out, conn->mod_fd);
+       rb_rawbuf_flush(conn->plainbuf_out, conn->plain_fd);
+       rb_close(conn->mod_fd);
+       SetDead(conn);
+
+       if(!wait_plain || fmt == NULL)
+       {
+               rb_close(conn->plain_fd);
+       
+               if(conn->id >= 0)
+                       rb_dlinkDelete(&conn->node, connid_hash(conn->id));
+               rb_dlinkAdd(conn, &conn->node, &dead_list);
+               return;
+       }
+       rb_setselect(conn->plain_fd, RB_SELECT_WRITE|RB_SELECT_READ, NULL, NULL);
+       va_start(ap, fmt);
+       rb_vsnprintf(reason, sizeof(reason), fmt, ap);
+       va_end(ap);
+
+       buf[0] = 'D';
+       int32_to_buf(&buf[1], conn->id);
+       strcpy(&buf[5], reason);
+       len = (strlen(reason) + 1) + 5;
+       mod_cmd_write_queue(conn->ctl, buf, len);
+}
+
+static conn_t *
+make_conn(mod_ctl_t *ctl, rb_fde_t * mod_fd, rb_fde_t * plain_fd)
+{
+       conn_t *conn = rb_malloc(sizeof(conn_t));
+       conn->ctl = ctl;
+       conn->modbuf_out = rb_new_rawbuffer();
+       conn->plainbuf_out = rb_new_rawbuffer();
+       conn->mod_fd = mod_fd;
+       conn->plain_fd = plain_fd;
+       conn->id = -1;
+       conn->stream = NULL;
+       rb_set_nb(mod_fd);
+       rb_set_nb(plain_fd);
+       return conn;
+}
+
+static void
+conn_mod_write_sendq(rb_fde_t * fd, void *data)
+{
+       conn_t *conn = data;
+       const char *err;
+       int retlen;
+       if(IsDead(conn))
+               return;
+
+       while ((retlen = rb_rawbuf_flush(conn->modbuf_out, fd)) > 0)
+               conn->mod_out += retlen;
+
+       if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
+       {
+               if(retlen == 0)
+                       close_conn(conn, WAIT_PLAIN, "%s", remote_closed);
+               if(IsSSL(conn) && retlen == RB_RW_SSL_ERROR)
+                       err = rb_get_ssl_strerror(conn->mod_fd);
+               else
+                       err = strerror(errno);
+               close_conn(conn, WAIT_PLAIN, "Write error: %s", err);
+               return;
+       }
+       if(rb_rawbuf_length(conn->modbuf_out) > 0)
+       {
+               int flags = RB_SELECT_WRITE;
+               if(retlen == RB_RW_SSL_NEED_READ)
+                       flags |= RB_SELECT_READ;
+
+               rb_setselect(conn->mod_fd, flags, conn_mod_write_sendq, conn);
+       }
+       else
+               rb_setselect(conn->mod_fd, RB_SELECT_WRITE, NULL, NULL);
+
+       if(IsCork(conn) && rb_rawbuf_length(conn->modbuf_out) == 0)
+       {
+               ClearCork(conn);
+               conn_plain_read_cb(conn->plain_fd, conn);
+       }
+
+}
+
+static void
+conn_mod_write(conn_t * conn, void *data, size_t len)
+{
+       if(IsDead(conn))        /* no point in queueing to a dead man */
+               return;
+       rb_rawbuf_append(conn->modbuf_out, data, len);
+}
+
+static void
+conn_plain_write(conn_t * conn, void *data, size_t len)
+{
+       if(IsDead(conn))        /* again no point in queueing to dead men */
+               return;
+       rb_rawbuf_append(conn->plainbuf_out, data, len);
+}
+
+static void
+mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len)
+{
+       mod_ctl_buf_t *ctl_buf;
+       ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
+       ctl_buf->buf = rb_malloc(len);
+       ctl_buf->buflen = len;
+       memcpy(ctl_buf->buf, data, len);
+       ctl_buf->nfds = 0;
+       rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq);
+       mod_write_ctl(ctl->F, ctl);
+}
+
+#ifdef HAVE_ZLIB
+static void
+common_zlib_deflate(conn_t * conn, void *buf, size_t len)
+{
+       int ret, have;
+       z_stream *outstream = &((zlib_stream_t *)conn->stream)->outstream;
+       outstream->next_in = buf;
+       outstream->avail_in = len;
+       outstream->next_out = (Bytef *) outbuf;
+       outstream->avail_out = sizeof(outbuf);
+
+       ret = deflate(outstream, Z_SYNC_FLUSH);
+       if(ret != Z_OK)
+       {
+               /* deflate error */
+               close_conn(conn, WAIT_PLAIN, "Deflate failed: %s", zError(ret));
+               return;
+       }
+       if(outstream->avail_out == 0)
+       {
+               /* avail_out empty */
+               close_conn(conn, WAIT_PLAIN, "error compressing data, avail_out == 0");
+               return;
+       }
+       if(outstream->avail_in != 0)
+       {
+               /* avail_in isn't empty...*/
+               close_conn(conn, WAIT_PLAIN, "error compressing data, avail_in != 0");
+               return;
+       }
+       have = sizeof(outbuf) - outstream->avail_out;
+       conn_mod_write(conn, outbuf, have);
+}
+
+static void
+common_zlib_inflate(conn_t * conn, void *buf, size_t len)
+{
+       int ret, have;
+       ((zlib_stream_t *)conn->stream)->instream.next_in = buf;
+       ((zlib_stream_t *)conn->stream)->instream.avail_in = len;
+       ((zlib_stream_t *)conn->stream)->instream.next_out = (Bytef *) outbuf;
+       ((zlib_stream_t *)conn->stream)->instream.avail_out = sizeof(outbuf);
+
+       while (((zlib_stream_t *)conn->stream)->instream.avail_in)
+       {
+               ret = inflate(&((zlib_stream_t *)conn->stream)->instream, Z_NO_FLUSH);
+               if(ret != Z_OK)
+               {
+                       if(!strncmp("ERROR ", buf, 6))
+                       {
+                               close_conn(conn, WAIT_PLAIN, "Received uncompressed ERROR");
+                               return;
+                       }
+                       close_conn(conn, WAIT_PLAIN, "Inflate failed: %s", zError(ret));
+                       return;
+               }
+               have = sizeof(outbuf) - ((zlib_stream_t *)conn->stream)->instream.avail_out;
+
+               if(((zlib_stream_t *)conn->stream)->instream.avail_in)
+               {
+                       conn_plain_write(conn, outbuf, have);
+                       have = 0;
+                       ((zlib_stream_t *)conn->stream)->instream.next_out = (Bytef *) outbuf;
+                       ((zlib_stream_t *)conn->stream)->instream.avail_out = sizeof(outbuf);
+               }
+       }
+       if(have == 0)
+               return;
+
+       conn_plain_write(conn, outbuf, have);
+}
+#endif
+
+static int
+plain_check_cork(conn_t * conn)
+{
+       if(rb_rawbuf_length(conn->modbuf_out) >= 4096)
+       {
+               /* if we have over 4k pending outbound, don't read until 
+                * we've cleared the queue */
+               SetCork(conn);
+               rb_setselect(conn->plain_fd, RB_SELECT_READ, NULL, NULL);
+               /* try to write */
+               conn_mod_write_sendq(conn->mod_fd, conn);
+               return 1;
+       }
+       return 0;
+}
+
+
+static void
+conn_plain_read_cb(rb_fde_t * fd, void *data)
+{
+       conn_t *conn = data;
+       int length = 0;
+       if(conn == NULL)
+               return;
+
+       if(IsDead(conn))
+               return;
+
+       if(plain_check_cork(conn))
+               return;
+
+       while (1)
+       {
+               if(IsDead(conn))
+                       return;
+
+               length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf));
+
+               if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
+               {
+                       close_conn(conn, NO_WAIT, NULL);
+                       return;
+               }
+
+               if(length < 0)
+               {
+                       rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_cb, conn);
+                       conn_mod_write_sendq(conn->mod_fd, conn);
+                       return;
+               }
+               conn->plain_in += length;
+
+#ifdef HAVE_ZLIB
+               if(IsZip(conn))
+                       common_zlib_deflate(conn, inbuf, length);
+               else
+#endif
+                       conn_mod_write(conn, inbuf, length);
+               if(IsDead(conn))
+                       return;
+               if(plain_check_cork(conn))
+                       return;
+       }
+}
+
+static void
+conn_mod_read_cb(rb_fde_t * fd, void *data)
+{
+       conn_t *conn = data;
+       const char *err = remote_closed;
+       int length;
+       if(conn == NULL)
+               return;
+       if(IsDead(conn))
+               return;
+
+       while (1)
+       {
+               if(IsDead(conn))
+                       return;
+
+               length = rb_read(conn->mod_fd, inbuf, sizeof(inbuf));
+
+               if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
+               {
+                       if(length == 0) {
+                               close_conn(conn, WAIT_PLAIN, "%s", remote_closed);
+                               return;
+                       }
+
+                       if(IsSSL(conn) && length == RB_RW_SSL_ERROR)
+                               err = rb_get_ssl_strerror(conn->mod_fd);
+                       else
+                               err = strerror(errno);
+                       close_conn(conn, WAIT_PLAIN, "Read error: %s", err);
+                       return;
+               }
+               if(length < 0)
+               {
+                       int flags = RB_SELECT_READ;
+                       if(length == RB_RW_SSL_NEED_WRITE)
+                               flags |= RB_SELECT_WRITE;
+                               
+                       rb_setselect(conn->mod_fd, flags, conn_mod_read_cb, conn);
+                       conn_plain_write_sendq(conn->plain_fd, conn);
+                       return;
+               }       
+               conn->mod_in += length;
+#ifdef HAVE_ZLIB
+               if(IsZip(conn))
+                       common_zlib_inflate(conn, inbuf, length);
+               else
+#endif
+                       conn_plain_write(conn, inbuf, length);
+       }
+}
+
+static void
+conn_plain_write_sendq(rb_fde_t * fd, void *data)
+{
+       conn_t *conn = data;
+       int retlen;
+
+       if(IsDead(conn))
+               return;
+
+       while ((retlen = rb_rawbuf_flush(conn->plainbuf_out, fd)) > 0)
+       {
+               conn->plain_out += retlen;
+       }
+       if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
+       {
+               close_conn(data, NO_WAIT, NULL);
+               return;
+       }
+       
+
+       if(rb_rawbuf_length(conn->plainbuf_out) > 0)
+               rb_setselect(conn->plain_fd, RB_SELECT_WRITE, conn_plain_write_sendq, conn);
+       else
+               rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL);
+}
+
+static int
+maxconn(void)
+{
+#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
+       struct rlimit limit;
+
+       if(!getrlimit(RLIMIT_NOFILE, &limit))
+       {
+               return limit.rlim_cur;
+       }
+#endif /* RLIMIT_FD_MAX */
+       return MAXCONNECTIONS;
+}
+
+static void
+ssl_process_accept_cb(rb_fde_t * F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
+{
+       conn_t *conn = data;
+       if(status == RB_OK)
+       {
+               conn_mod_read_cb(conn->mod_fd, conn);
+               conn_plain_read_cb(conn->plain_fd, conn);
+               return;
+       }
+       close_conn(conn, NO_WAIT, 0);
+       return;
+}
+
+static void
+ssl_process_connect_cb(rb_fde_t * F, int status, void *data)
+{
+       conn_t *conn = data;
+       if(status == RB_OK)
+       {
+               conn_mod_read_cb(conn->mod_fd, conn);
+               conn_plain_read_cb(conn->plain_fd, conn);
+               return;
+       }
+       close_conn(conn, NO_WAIT, 0);
+       return;
+}
+
+
+static void
+ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
+{
+       conn_t *conn;
+       rb_int32_t id;
+
+       conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
+
+       id = buf_to_int32(&ctlb->buf[1]);
+
+       if(id >= 0)
+               conn_add_id_hash(conn, id);
+       SetSSL(conn);
+
+       if(rb_get_type(conn->mod_fd) & RB_FD_UNKNOWN)
+       {
+               
+               rb_set_type(conn->mod_fd, RB_FD_SOCKET);
+       }
+       if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
+               rb_set_type(conn->plain_fd, RB_FD_SOCKET);
+
+       rb_ssl_start_accepted(ctlb->F[0], ssl_process_accept_cb, conn, 10);
+}
+
+static void
+ssl_process_connect(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
+{
+       conn_t *conn;
+       rb_int32_t id;
+       conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
+
+       id = buf_to_int32(&ctlb->buf[1]);
+
+       if(id >= 0)
+               conn_add_id_hash(conn, id);
+       SetSSL(conn);
+
+       if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
+               rb_set_type(conn->mod_fd, RB_FD_SOCKET);
+
+       if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
+               rb_set_type(conn->plain_fd, RB_FD_SOCKET);
+
+
+       rb_ssl_start_connected(ctlb->F[0], ssl_process_connect_cb, conn, 10);
+}
+
+static void
+process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
+{
+       char outstat[512];
+       conn_t *conn;
+       const char *odata;
+       rb_int32_t id;
+
+       id = buf_to_int32(&ctlb->buf[1]);
+
+       if(id < 0)
+               return;
+       
+       odata = &ctlb->buf[5];
+       conn = conn_find_by_id(id);
+
+       if(conn == NULL)
+               return;
+
+       rb_snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
+                   conn->plain_out, conn->mod_in, conn->plain_in, conn->mod_out);
+       conn->plain_out = 0;
+       conn->plain_in = 0;
+       conn->mod_in = 0;
+       conn->mod_out = 0;
+       mod_cmd_write_queue(ctl, outstat, strlen(outstat) + 1); /* +1 is so we send the \0 as well */
+}
+
+#ifdef HAVE_ZLIB
+static void
+zlib_send_zip_ready(mod_ctl_t *ctl, conn_t *conn)
+{
+       char buf[5];
+       
+       buf[0] = 'R';
+       int32_to_buf(&buf[1], conn->id);
+       mod_cmd_write_queue(conn->ctl, buf, sizeof(buf));
+}
+
+static void
+zlib_process(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
+{
+       rb_uint8_t level;
+       size_t recvqlen;
+       size_t hdr = (sizeof(rb_uint8_t) * 2) + sizeof(rb_int32_t);
+       void *recvq_start;
+       z_stream *instream, *outstream;
+       conn_t *conn;
+       rb_int32_t id;
+
+       conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
+       if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
+               rb_set_type(conn->mod_fd, RB_FD_SOCKET);
+
+       if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
+               rb_set_type(conn->plain_fd, RB_FD_SOCKET);
+
+       id = buf_to_int32(&ctlb->buf[1]);
+       conn_add_id_hash(conn, id);
+
+       level = (rb_uint8_t) ctlb->buf[5];
+
+       recvqlen = ctlb->buflen - hdr;
+       recvq_start = &ctlb->buf[6];
+
+       SetZip(conn);
+       conn->stream = rb_malloc(sizeof(zlib_stream_t));
+       instream = &((zlib_stream_t *)conn->stream)->instream;
+       outstream = &((zlib_stream_t *)conn->stream)->outstream;
+       
+       instream->total_in = 0;
+       instream->total_out = 0;
+       instream->zalloc = (alloc_func) ssld_alloc;
+       instream->zfree = (free_func) ssld_free;
+       instream->data_type = Z_ASCII;
+       inflateInit(&((zlib_stream_t *)conn->stream)->instream);
+
+       outstream->total_in = 0;
+       outstream->total_out = 0;
+       outstream->zalloc = (alloc_func) ssld_alloc;
+       outstream->zfree = (free_func) ssld_free;
+       outstream->data_type = Z_ASCII;
+
+       if(level > 9)
+               level = Z_DEFAULT_COMPRESSION;
+
+       deflateInit(&((zlib_stream_t *)conn->stream)->outstream, level);
+       if(recvqlen > 0)
+               common_zlib_inflate(conn, recvq_start, recvqlen);
+       zlib_send_zip_ready(ctl, conn);
+       conn_mod_read_cb(conn->mod_fd, conn);
+       conn_plain_read_cb(conn->plain_fd, conn);
+       return;
+
+}
+#endif
+
+static void
+init_prng(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
+{
+       char *path;
+       prng_seed_t seed_type;
+       
+       seed_type = (prng_seed_t)ctl_buf->buf[1];       
+       path = &ctl_buf->buf[2];
+       rb_init_prng(path, seed_type);
+}
+
+
+static void
+ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
+{
+       char *buf;
+       char *cert, *key, *dhparam;
+
+       buf = &ctl_buf->buf[2];
+       cert = buf;
+       buf += strlen(cert) + 1;
+       key = buf;
+       buf += strlen(key) + 1;
+       dhparam = buf;
+       if(strlen(dhparam) == 0)
+               dhparam = NULL;
+
+       if(!rb_setup_ssl_server(cert, key, dhparam))
+       {
+               const char *invalid = "I";
+               mod_cmd_write_queue(ctl, invalid, strlen(invalid));
+               return;
+       } 
+}
+
+static void
+send_nossl_support(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb)
+{
+       static const char *nossl_cmd = "N";
+       conn_t *conn;
+       rb_int32_t id;
+
+       if(ctlb != NULL)
+       {       
+               conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
+               id = buf_to_int32(&ctlb->buf[1]);
+
+               if(id >= 0)
+                       conn_add_id_hash(conn, id);
+               close_conn(conn, WAIT_PLAIN, "libratbox reports no SSL/TLS support");
+       } 
+       mod_cmd_write_queue(ctl, nossl_cmd, strlen(nossl_cmd)); 
+}
+
+static void
+send_i_am_useless(mod_ctl_t *ctl)
+{
+       static const char *useless = "U";
+       mod_cmd_write_queue(ctl, useless, strlen(useless));
+}
+
+static void
+send_nozlib_support(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb)
+{
+       static const char *nozlib_cmd = "z";
+       conn_t *conn;
+       rb_int32_t id;
+       if(ctlb != NULL)
+       {
+               conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
+               id = buf_to_int32(&ctlb->buf[1]);
+
+               if(id >= 0)
+                       conn_add_id_hash(conn, id);
+               close_conn(conn, WAIT_PLAIN, "libratbox reports no zlib support");
+       } 
+       mod_cmd_write_queue(ctl, nozlib_cmd, strlen(nozlib_cmd));
+}
+
+static void
+mod_process_cmd_recv(mod_ctl_t * ctl)
+{
+       rb_dlink_node *ptr, *next;
+       mod_ctl_buf_t *ctl_buf;
+
+       RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head)
+       {
+               ctl_buf = ptr->data;
+
+               switch (*ctl_buf->buf)
+               {
+               case 'A':
+                       {
+                               if(!ssl_ok)
+                               {
+                                       send_nossl_support(ctl, ctl_buf);
+                                       break;
+                               }
+                               ssl_process_accept(ctl, ctl_buf);
+                               break;
+                       }
+               case 'C':
+                       {
+                               if(!ssl_ok)
+                               {
+                                       send_nossl_support(ctl, ctl_buf);
+                                       break;
+                               }
+                               ssl_process_connect(ctl, ctl_buf);
+                               break;
+                       }
+
+               case 'K':
+                       {
+                               if(!ssl_ok)
+                               {
+                                       send_nossl_support(ctl, ctl_buf);
+                                       break;
+                               }
+                               ssl_new_keys(ctl, ctl_buf);
+                               break;
+                       }
+               case 'I':
+                               init_prng(ctl, ctl_buf);
+                               break;
+               case 'S':
+                       {
+                               process_stats(ctl, ctl_buf);
+                               break;
+                       }
+#ifdef HAVE_ZLIB
+               case 'Z':
+                       {
+                               /* just zlib only */
+                               zlib_process(ctl, ctl_buf);
+                               break;
+                       }
+#else
+               case 'Y':
+               case 'Z':
+                       send_nozlib_support(ctl);
+                       break;
+                       
+#endif
+               default:
+                       break;
+                       /* Log unknown commands */
+               }
+               rb_dlinkDelete(ptr, &ctl->readq);
+               rb_free(ctl_buf->buf);
+               rb_free(ctl_buf);
+       }
+
+}
+
+
+
+static void
+mod_read_ctl(rb_fde_t * F, void *data)
+{
+       mod_ctl_buf_t *ctl_buf;
+       mod_ctl_t *ctl = data;
+       int retlen;
+
+       do
+       {
+               ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
+               ctl_buf->buf = rb_malloc(READBUF_SIZE);
+               ctl_buf->buflen = READBUF_SIZE;
+               retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, ctl_buf->buflen, ctl_buf->F,
+                                       MAXPASSFD);
+               if(retlen <= 0)
+               {
+                       rb_free(ctl_buf->buf);
+                       rb_free(ctl_buf);
+               }
+               else
+               {
+                       ctl_buf->buflen = retlen;
+                       rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq);
+               }
+       }
+       while (retlen > 0);
+
+       if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
+               exit(0);
+
+       mod_process_cmd_recv(ctl);
+       rb_setselect(ctl->F, RB_SELECT_READ, mod_read_ctl, ctl);
+}
+
+static void
+mod_write_ctl(rb_fde_t * F, void *data)
+{
+       mod_ctl_t *ctl = data;
+       mod_ctl_buf_t *ctl_buf;
+       rb_dlink_node *ptr, *next;
+       int retlen, x;
+
+       RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head)
+       {
+               ctl_buf = ptr->data;
+               retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf,
+                                       ctl_buf->buflen);
+               if(retlen > 0)
+               {
+                       rb_dlinkDelete(ptr, &ctl->writeq);
+                       for (x = 0; x < ctl_buf->nfds; x++)
+                               rb_close(ctl_buf->F[x]);
+                       rb_free(ctl_buf->buf);
+                       rb_free(ctl_buf);
+
+               }
+               if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
+                       exit(0);                        
+               
+               rb_setselect(ctl->F, RB_SELECT_WRITE, mod_write_ctl, ctl);
+       }
+}
+
+
+static void
+read_pipe_ctl(rb_fde_t * F, void *data)
+{
+       int retlen;
+       while ((retlen = rb_read(F, inbuf, sizeof(inbuf))) > 0)
+       {
+               ;;              /* we don't do anything with the pipe really, just care if the other process dies.. */
+       }
+       if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
+               exit(0);
+       rb_setselect(F, RB_SELECT_READ, read_pipe_ctl, NULL);
+
+}
+
+int
+main(int argc, char **argv)
+{
+       const char *s_ctlfd, *s_pipe;
+       int ctlfd, pipefd, x, maxfd;
+       maxfd = maxconn();
+       s_ctlfd = getenv("CTL_FD");
+       s_pipe = getenv("CTL_PIPE");
+
+       if(s_ctlfd == NULL || s_pipe == NULL)
+       {
+               fprintf(stderr, "This is ircd-ratbox ssld.  You know you aren't supposed to run me directly?\n");
+               fprintf(stderr, "You get an Id tag for this: $Id: ssld.c 25179 2008-03-30 16:34:57Z androsyn $\n");
+               fprintf(stderr, "Have a nice life\n");
+               exit(1);
+       }
+
+       ctlfd = atoi(s_ctlfd);
+       pipefd = atoi(s_pipe);
+
+       for (x = 0; x < maxfd; x++)
+       {
+               if(x != ctlfd && x != pipefd && x > 2)
+                       close(x);
+       }
+
+#if 0
+       x = open("/dev/null", O_RDWR);
+       if(x >= 0)
+       {
+               if(ctlfd != 0 && pipefd != 0)
+                       dup2(x, 0);
+               if(ctlfd != 1 && pipefd != 1)
+                       dup2(x, 1);
+               if(ctlfd != 2 && pipefd != 2)
+                       dup2(x, 2);
+               if(x > 2)
+                       close(x);
+       }
+#endif
+       setup_signals();
+       rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
+       rb_init_rawbuffers(1024);
+       ssl_ok = rb_supports_ssl();             
+
+       mod_ctl = rb_malloc(sizeof(mod_ctl_t));
+       mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
+       mod_ctl->F_pipe = rb_open(pipefd, RB_FD_PIPE, "ircd pipe");
+       rb_set_nb(mod_ctl->F);
+       rb_set_nb(mod_ctl->F_pipe);
+       rb_event_addish("clean_dead_conns", clean_dead_conns, NULL, 10);
+       read_pipe_ctl(mod_ctl->F_pipe, NULL);
+       mod_read_ctl(mod_ctl->F, mod_ctl);
+       if(!zlib_ok && !ssl_ok)
+       {
+               /* this is really useless... */
+               send_i_am_useless(mod_ctl);
+               /* sleep until the ircd kills us */
+               rb_sleep(2<<30, 0);
+               exit(1);
+       }
+
+       if(!zlib_ok)
+               send_nozlib_support(mod_ctl, NULL);
+       if(!ssl_ok)
+               send_nossl_support(mod_ctl, NULL);
+       rb_lib_loop(0);
+       return 0;
+}
+
+
+
+static void
+dummy_handler(int sig)
+{
+       return;
+}
+
+static void
+setup_signals()
+{
+       struct sigaction act;
+
+       act.sa_flags = 0;
+       act.sa_handler = SIG_IGN;
+       sigemptyset(&act.sa_mask);
+       sigaddset(&act.sa_mask, SIGPIPE);
+       sigaddset(&act.sa_mask, SIGALRM);
+#ifdef SIGTRAP
+       sigaddset(&act.sa_mask, SIGTRAP);
+#endif
+
+#ifdef SIGWINCH
+       sigaddset(&act.sa_mask, SIGWINCH);
+       sigaction(SIGWINCH, &act, 0);
+#endif
+       sigaction(SIGPIPE, &act, 0);
+#ifdef SIGTRAP
+       sigaction(SIGTRAP, &act, 0);
+#endif
+
+       act.sa_handler = dummy_handler;
+       sigaction(SIGALRM, &act, 0);
+}
+