A small xinetd howto

xinet is an enhanced inetd. It comes with access controls, resource controls, possibilities to pass environment settings over to a server, and so on. Unfortunately courier-imap and qmail depend on their own "internet super servers". So you have the same code three times (xinetd, tcpserver, couriertcpd). tcpserver and couriertcpd do not support udp, couriertcpd also performs very badly (I tried to spwan qmail-smtp from couriertcp and opened one hundred connections: couriertcpd did not kill about 80 connections after smtp conversation was done). So I was looking for how to use qmail-smtp and courier-imap with xinetd.
Both servers expect that information about the client like the ip address or the port number is available in environment variables like $TCPREMOTEIP or $TCPREMOTEPORT. You could use tcp-env from the qmail package to do that.
courier-imap reads its configuration from several environment settings which are defined in /etc/imap/imapd (or whereever you put those configuration files). You can source them in your xinetd startup script and pass them to courier-imap by using xinetd's passenv-feature.
qmail-smtp acts as a smtprelay if there is an environment variable called $RELAYHOST. Normally this is set up by tcpserver if the ip address of the remote client matches a predefined address range which is allowed to relay mails. xinetd lacks this feature. So I wrote a small programm called relaycheck, which is meant to be started from tcp-env. If $TCPREMOTEIP matches any ip addresses you specified as first argument for relaycheck, then the program you specified as second argument will be called with the desired environment variable $RELAYHOST.

examples

Let's have a look at my configuration files and startup scripts. I am running qmail and courier-imap on a dual-homed machine. Access to the imapd should be granted only to the 192.168.0.0/24 subnet. qmail-smtp should be accessible by any host, but should act as a mailrelay for localhost (127.0.0.1) and the 192.168.0.0/24 subnet.

xinetd startup script:

#!/bin/sh
# /sbin/rc.d/init.d/xinetd

PATH=/bin:/sbin:/usr/bin:/usr/sbin
PROG=/usr/sbin/xinetd
MYPIDFILE=/var/run/xinetd.pid

if [ ! -x $PROG ]; then
  exit 0
fi

case "$1" in
  start)
    set -a
    . /etc/imap/imapd
    $PROG -filelog /var/log/xinetd.log -pidfile $MYPIDFILE
  ;;
  stop)
    if [ -f $MYPIDFILE ]; then
      if kill -0 `cat $MYPIDFILE`; then
        kill `cat $MYPIDFILE`
      fi
      rm -f $MYPIDFILE
    fi
  ;;
  reload)
    if [ -f $MYPIDFILE ]; then
      if kill -0 `cat $MYPIDFILE`; then
        kill -HUP `cat $MYPIDFILE`
      else
        rm -f $MYPIDFILE
        $0 start
      fi
    else
      $0 start
    fi
  ;;
  restart)
    $0 stop && $0 start
  ;;
  *)
    echo "usage: $0 (start|stop|reload|restart)"
esac

xinetd configuration file:

# /etc/xinetd.conf
service smtp
{
  flags = NODELAY
  socket_type = stream
  wait = no
  user = qmaild
  server = /var/qmail/bin/tcp-env
  server_args = -R /usr/bin/relaycheck 127.0.0.1,192.168.0. /var/qmail/bin/qmail-smtpd
  log_type = FILE /var/log/smtpd.log
  log_on_success = PID HOST EXIT DURATION
  log_on_failure = HOST ATTEMPT
  passenv =
}

service imap
{
  flags = NODELAY
  socket_type = stream
  wait = no
  user = root
  server = /var/qmail/bin/tcp-env
  server_args = -R /usr/sbin/imaplogin /usr/libexec/authlib/authshadow /usr/bin/imapd Maildir
  only_from = 192.168.0.0/24
  bind = 192.168.0.1
  log_type = FILE /var/log/imapd.log
  log_on_success = PID HOST EXIT DURATION
  log_on_failure = HOST ATTEMPT
}

downloads

relaycheck.c (compile with diet -Os gcc -W -Wall -s -nostdinc -o relaycheck relaycheck.c)