Index: main/waeup.kofa/trunk/CHANGES.txt
===================================================================
--- main/waeup.kofa/trunk/CHANGES.txt	(revision 17313)
+++ main/waeup.kofa/trunk/CHANGES.txt	(revision 17327)
@@ -5,4 +5,9 @@
 =======================
 
+* Move call to interactive debugger from `grokcore.startup` to `waeup.kofa`.
+  Support for this was dropped long ago in `grokcore.startup`. This way we keep
+  the possibility to provide a `kofactl` script w/o loosing the possibility to
+  upgrade to newer `grokcore.startup` versions.
+
 * Allow beds to be blocked so that no student can be allocated to such a bed space 
   (in contrast to reserved beds)
@@ -14,5 +19,4 @@
 1.8.1 (2023-01-16)
 ==================
-
 
 * Upgrade `dolmen.beaker` dependency. Removes other outdated crypto
@@ -30,7 +34,7 @@
 
 * Allow students to book accommodation also if they are in previous
-  sessions (not activated in base package). 
-
-* Add Javascript which automatically submits a form on select change 
+  sessions (not activated in base package).
+
+* Add Javascript which automatically submits a form on select change
   (not used in base but in lpng custom package).
 
@@ -66,5 +70,5 @@
 * Enable import of student history.
 
-* Don't complain but remove leading and trailing whitespaces 
+* Don't complain but remove leading and trailing whitespaces
   while converting values during import.
 
@@ -89,6 +93,6 @@
 * Prefill login form after applicant registration.
 
-* Show local roles on faculty, department, course and certificate pages 
-  and provide 'Contact' button so that authenticated users can contact 
+* Show local roles on faculty, department, course and certificate pages
+  and provide 'Contact' button so that authenticated users can contact
   officers via Kofa.
 
@@ -257,5 +261,5 @@
 * Make max file size customizable.
 
-* Add `score_editing_disabled` switch at course level. 
+* Add `score_editing_disabled` switch at course level.
 
 * Take `DELETION_MARKER` into consideration when updating passwords.
@@ -275,5 +279,5 @@
   in container code.
 
-* Add semester filter to Fix `CourseTicketExporter`. 
+* Add semester filter to Fix `CourseTicketExporter`.
 
 * Add `FacultiesExportJobContainerSelectStudents` view to allow
Index: main/waeup.kofa/trunk/setup.py
===================================================================
--- main/waeup.kofa/trunk/setup.py	(revision 17313)
+++ main/waeup.kofa/trunk/setup.py	(revision 17327)
@@ -132,5 +132,5 @@
       [console_scripts]
       kofa-debug = grokcore.startup:interactive_debug_prompt
-      kofactl = grokcore.startup:zdaemon_controller
+      kofactl = waeup.kofa.startup:zdaemon_controller
       analyze = waeup.kofa.maintenance:db_analyze
       fsdiff = waeup.kofa.maintenance:db_diff
Index: main/waeup.kofa/trunk/src/waeup/kofa/startup.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/startup.py	(revision 17313)
+++ main/waeup.kofa/trunk/src/waeup/kofa/startup.py	(revision 17327)
@@ -49,6 +49,11 @@
 """
 import os
+import sys
+import zdaemon.zdctl
 from ConfigParser import RawConfigParser
-from grokcore.startup import application_factory, debug_application_factory
+from grokcore.startup import (
+        application_factory, debug_application_factory,
+        interactive_debug_prompt)
+
 
 def _set_env_vars(global_conf):
@@ -62,4 +67,5 @@
         os.environ[key] = val
     return
+
 
 def env_app_factory(global_conf, **local_conf):
@@ -94,4 +100,5 @@
     return application_factory(global_conf, **local_conf)
 
+
 def env_debug_app_factory(global_conf, **local_conf):
     """A debugger application factory.
@@ -104,2 +111,20 @@
     _set_env_vars(global_conf)
     return debug_application_factory(global_conf, **local_conf)
+
+
+class ControllerCommands(zdaemon.zdctl.ZDCmd):
+
+    def do_debug(self, rest):
+        zope_conf = os.path.join('parts', 'etc', 'zope.conf')
+        del sys.argv[0]
+        interactive_debug_prompt(zope_conf=zope_conf)
+
+    def help_debug(self):
+        print("debug -- Initialize the application, providing a debugger")
+        print("         object at an interactive Python prompt.")
+
+
+def zdaemon_controller(zdaemon_conf=os.path.join('parts', 'etc',
+                                                 'zdaemon.conf')):
+    args = ['-C', zdaemon_conf] + sys.argv[1:]
+    zdaemon.zdctl.main(args, options=None, cmdclass=ControllerCommands)
Index: main/waeup.kofa/trunk/src/waeup/kofa/tests/test_startup.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/tests/test_startup.py	(revision 17313)
+++ main/waeup.kofa/trunk/src/waeup/kofa/tests/test_startup.py	(revision 17327)
@@ -1,9 +1,22 @@
 # Tests for local startup functions.
+import mock
 import os
 import shutil
+import sys
 import tempfile
 import unittest
+# from zdaemon.zdctl import 
+import zdaemon.zdctl
 from zope.app.wsgi import WSGIPublisherApplication
-from waeup.kofa.startup import env_app_factory, env_debug_app_factory
+# from zdaemon.tests.testzdctl import run as run_zdctl
+from waeup.kofa.startup import (
+        env_app_factory, env_debug_app_factory, zdaemon_controller,
+        )
+try:
+    from StringIO import StringIO  # py2
+except ImportError:
+    from io import StringIO        # py3
+
+
 
 ZOPE_CONF_TEMPL = '''
@@ -21,4 +34,12 @@
 '''
 
+
+ZDAEMON_CONF_TEMPL = '''
+<runner>
+  program echo "zdaemon started"
+</runner>
+'''
+
+
 class StartUpTests(unittest.TestCase):
 
@@ -29,4 +50,6 @@
         self.zope_conf = os.path.join(self.workdir, 'zope.conf')
         open(self.zope_conf, 'wb').write(ZOPE_CONF_TEMPL % self.site_zcml)
+        self.zdaemon_conf = os.path.join(self.workdir, 'zdaemon.conf')
+        open(self.zdaemon_conf, 'wb').write(ZDAEMON_CONF_TEMPL)
         return
 
@@ -75,2 +98,18 @@
         self.assertEqual(os.environ.get('TEST_FOO', None), 'value1')
         return
+
+    @mock.patch("sys.stdout", new_callable=StringIO)
+    def test_zdaemon_has_debug_help(self, mock_out):
+        # We provide a `debug` help text for `kofactl`
+        with mock.patch.object(sys, "argv", ["kofactl",  "help", "debug"]):
+            with self.assertRaises(SystemExit):
+                zdaemon_controller(zdaemon_conf=self.zdaemon_conf)
+        self.assertTrue("providing a debugger" in mock_out.getvalue())
+
+    @mock.patch("waeup.kofa.startup.interactive_debug_prompt")
+    def test_zdaemon_can_start_debug(self, mock_prompt):
+        # We can actually run the debugger...
+        with mock.patch.object(sys, "argv", ["kofactl", "debug"]):
+            with self.assertRaises(SystemExit):
+                zdaemon_controller(zdaemon_conf=self.zdaemon_conf)
+        self.assertTrue(mock_prompt.called)
Index: main/waeup.kofa/trunk/versions.cfg
===================================================================
--- main/waeup.kofa/trunk/versions.cfg	(revision 17313)
+++ main/waeup.kofa/trunk/versions.cfg	(revision 17327)
@@ -84,5 +84,5 @@
 zc.z3monitor = 0.8.0
 zc.zodbrecipes = 0.6.2
-zdaemon = 2.0.7
+zdaemon = 4.4
 ZODB3 = 3.10.5
 zope.app.apidoc = 3.7.5
@@ -160,4 +160,5 @@
 
 # Packages already at newest version (supporting py2 and py3)
+grokcore.startup = 3.0.1
 Paste = 3.5.2
 PasteScript = 3.3.0
