--- a/Makefile.global.in
+++ b/Makefile.global.in
@@ -199,6 +199,9 @@ KRB5_CPPFLAGS	= @KRB5_CPPFLAGS@
 KRB5_LDFLAGS	= @KRB5_LDFLAGS@
 KRB5_LIBS	= @KRB5_LIBS@
 
+## Systemd support.
+LIBSYSTEMD_LIBS	= @LIBSYSTEMD_LIBS@
+
 ##  Missing functions.	If non-empty, configure detected that your system
 ##  was missing some standard functions, and INN will be providing its own
 ##  replacements from the lib directory.
--- a/configure.ac
+++ b/configure.ac
@@ -434,6 +434,13 @@ AS_IF([test x"$inn_cv_lib_bdb_ndbm" != x
      AC_SUBST([DBM_LIBS])])
 AC_SUBST([DBM_CPPFLAGS])
 
+dnl Unconditionally link with libsystemd if it is available
+if pkg-config libsystemd 2> /dev/null; then
+   LIBSYSTEMD_LIBS=`pkg-config --libs libsystemd`
+   AC_SUBST([LIBSYSTEMD_LIBS])
+   AC_DEFINE([HAVE_LIBSYSTEMD], 1, [Define if libsystemd is available.])
+fi
+
 dnl If configuring with large file support, determine the right flags to
 dnl use based on the platform.
 if test x"$inn_enable_largefiles" = xyes ; then
--- a/innd/Makefile
+++ b/innd/Makefile
@@ -34,6 +34,7 @@ clean clobber distclean maintclean:
 ##  Compilation rules.
 
 INNDLIBS 	= $(LIBSTORAGE) $(LIBHIST) $(LIBINN) $(STORAGE_LIBS) \
+		  $(LIBSYSTEMD_LIBS) \
 		  $(PERL_LIBS) $(PYTHON_LIBS) $(REGEX_LIBS) $(LIBS)
 
 perl.o:		perl.c   ; $(CC) $(CFLAGS) $(PERL_CPPFLAGS) -c perl.c
--- a/innd/cc.c
+++ b/innd/cc.c
@@ -174,6 +174,50 @@ CCcurrmode(void)
 
 
 /*
+**  Notify systemd of the current operating modes.
+*/
+static void
+CCsdnotify(void)
+{
+#ifdef HAVE_LIBSYSTEMD
+    buffer_sprintf(&CCreply, "STATUS=Server ");
+
+    /* Server's mode. */
+    switch (Mode) {
+    default:
+	buffer_append_sprintf(&CCreply, "Unknown %d", Mode);
+	break;
+    case OMrunning:
+	buffer_append_sprintf(&CCreply, "running");
+	break;
+    case OMpaused:
+	buffer_append_sprintf(&CCreply, "paused %s", ModeReason);
+	break;
+    case OMthrottled:
+	buffer_append_sprintf(&CCreply, "throttled %s", ModeReason);
+	break;
+    }
+    if (RejectReason)
+	buffer_append_sprintf(&CCreply, ". Rejecting %s", RejectReason);
+
+    /* Newsreaders. */
+    buffer_append_sprintf(&CCreply, ". Readers ");
+    if (innconf->readerswhenstopped)
+	buffer_append_sprintf(&CCreply, "independent ");
+    else
+	buffer_append_sprintf(&CCreply, "follow ");
+    if (NNRPReason == NULL)
+	buffer_append_sprintf(&CCreply, "enabled.");
+    else
+	buffer_append_sprintf(&CCreply, "disabled %s.", NNRPReason);
+
+    buffer_append(&CCreply, "", 1);
+    sd_notify(0, CCreply.data);
+#endif
+}
+
+
+/*
 **  Add <> around Message-ID if needed.
 */
 static const char *
@@ -292,6 +336,7 @@ CCallow(char *av[])
 	return "1 Wrong reason";
     free(RejectReason);
     RejectReason = NULL;
+    CCsdnotify();
     return NULL;
 }
 
@@ -702,6 +747,7 @@ CCgo(char *av[])
 	ErrorCount = IO_ERROR_COUNT;
     InndHisOpen();
     syslog(L_NOTICE, "%s running", LogName);
+    CCsdnotify();
     if (ICDneedsetup)
 	ICDsetup(true);
     SCHANwakeup(&Mode);
@@ -1116,6 +1162,7 @@ CCparam(char *av[])
     case 'n':
 	if (!CCparsebool('n', (bool *)&innconf->readerswhenstopped, *p))
 	    return BADVAL;
+	CCsdnotify();
 	break;
     case 'o':
 	MaxOutgoing = atoi(p);
@@ -1198,6 +1245,7 @@ CCblock(OPERATINGMODE NewMode, char *rea
     }
     syslog(L_NOTICE, "%s %s %s",
 	LogName, NewMode == OMpaused ? "paused" : "throttled", reason);
+    CCsdnotify();
     return NULL;
 }
 
@@ -1255,6 +1303,7 @@ CCreaders(char *av[])
 	NNRPReason = xstrdup(p);
 	break;
     }
+    CCsdnotify();
     return NULL;
 }
 
@@ -2033,6 +2082,8 @@ CCsetup(void)
 #if     defined(SIGUSR1)
     xsignal(SIGUSR1, CCresetup);
 #endif  /* defined(SIGUSR1) */
+
+    CCsdnotify();
 }
 
 
--- a/innd/innd.c
+++ b/innd/innd.c
@@ -774,6 +774,9 @@ main(int ac, char *av[])
             die("SERVER cant renumber");
     }
     syslog(LOG_NOTICE, "SERVER starting");
+#ifdef HAVE_LIBSYSTEMD
+    sd_notify(0, "READY=1");
+#endif
     CHANreadloop();
 
     /* CHANreadloop should never return. */
--- a/innd/innd.h
+++ b/innd/innd.h
@@ -42,6 +42,10 @@
 #endif
 #include <time.h>
 
+#ifdef HAVE_LIBSYSTEMD
+# include <systemd/sd-daemon.h>
+#endif
+
 #include "inn/buffer.h"
 #include "inn/history.h"
 #include "inn/messages.h"
--- a/innd/rc.c
+++ b/innd/rc.c
@@ -1734,6 +1734,41 @@ RCsetup(void)
     int *fds;
     bool okay;
 
+#ifdef HAVE_LIBSYSTEMD
+    /* Ignore any configured ports if socket activation is being used. */
+    count = sd_listen_fds(1);
+    if (count > 0) {
+	/* Make sure that the RCchan array is of the appropriate size. */
+	if (chanlimit == 0) {
+	    chanlimit = count;
+	    RCchan = xmalloc(chanlimit * sizeof(CHANNEL *));
+	    start = 0;
+	} else {
+	    for (start = 0; start < chanlimit; start++)
+		if (RCchan[start] == NULL)
+		    break;
+	    if (chanlimit - start < count) {
+		chanlimit += count - (chanlimit - start);
+		RCchan = xrealloc(RCchan, chanlimit * sizeof(CHANNEL *));
+	    }
+	}
+
+	for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + count; i++) {
+	    if (sd_is_socket(i, AF_UNSPEC, SOCK_STREAM, 1) <= 0)
+		die("SERVER cant use socket-activated non-AF_INET socket %d.", i);
+	    rc = CHANcreate(i, CTremconn, CSwaiting, RCreader, RCwritedone);
+	    notice("%s rcsetup %s", LogName, CHANname(rc));
+	    RCHANadd(rc);
+	    RCchan[start + i - SD_LISTEN_FDS_START] = rc;
+	}
+
+	/* Get the list of hosts we handle. */
+	RCreadlist();
+
+	return;
+    }
+#endif
+
     /* If neither bindaddress or bindaddress6 are set, we have to do this the
        hard way.  Either way, allocate an fds array to hold the file
        descriptors.  Two is probably always sufficient, but we can't tell for
--- a/scripts/rc.news.in
+++ b/scripts/rc.news.in
@@ -157,8 +157,12 @@ if [ "$OVMETHOD" = "ovdb" ]; then
 fi
 
 ##  Start the show.
+##  When using systemd, the daemon must be started last with exec to keep
+##  the same PID of this script.
+if [ -z "$NOTIFY_SOCKET" -a -z "$LISTEN_PID" ]; then
 echo 'Starting innd.'
 eval ${WHAT} ${RFLAG} ${INNFLAGS}
+fi
 
 # Gee, looks like lisp, doesn't it?
 ${DOINNWATCH} && {
@@ -188,3 +192,9 @@ done &
 if [ -f ${PATHBIN}/rc.news.local ] ; then
     ${PATHBIN}/rc.news.local start
 fi
+
+if [ "$NOTIFY_SOCKET" -o "$LISTEN_PID" ]; then
+    echo 'Starting innd.'
+    eval exec ${WHAT} -f ${RFLAG} ${INNFLAGS}
+fi
+
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -67,6 +67,7 @@ INNOBJS		= ../innd/art.o ../innd/cc.o ..
 
 # The libraries innd needs to link.
 INNDLIBS        = $(LIBSTORAGE) $(LIBHIST) $(LIBINN) $(STORAGE_LIBS) \
+		$(LIBSYSTEMD_LIBS) \
 		$(PYTHON_LIBS) $(REGEX_LIBS) $(LIBS) $(PERL_LIBS)
 
 runtests: runtests.o
