[upstart/f14/master] upstart-1.2-1.fc14 allow .override files

Petr Lautrbach plautrba at fedoraproject.org
Mon May 9 11:13:53 UTC 2011


commit de6022b81a1c2e8206d02de22646d125fffbad29
Author: Petr Lautrbach <plautrba at redhat.com>
Date:   Mon May 9 13:13:15 2011 +0200

    upstart-1.2-1.fc14
    allow .override files

 .gitignore                 |    1 +
 sources                    |    2 +-
 upstart-audit-events.patch |  605 +------
 upstart-override.patch     | 5145 ++++++++++++++++++++++++++++++++++++++++++++
 upstart-utmp.patch         |  265 +---
 upstart.spec               |   25 +-
 6 files changed, 5176 insertions(+), 867 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 6c1b28b..6e10577 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 upstart-0.6.5.tar.gz
+upstart-1.2.tar.gz
diff --git a/sources b/sources
index 46ac626..9ab49d9 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-f9466bba72b655c2408353b64105853f  upstart-0.6.5.tar.gz
+c1b1bab5c1c1ed2595081d8178542b37  upstart-1.2.tar.gz
diff --git a/upstart-audit-events.patch b/upstart-audit-events.patch
index 07df654..f0a2892 100644
--- a/upstart-audit-events.patch
+++ b/upstart-audit-events.patch
@@ -1,45 +1,3 @@
-diff --git a/Makefile.in b/Makefile.in
-index a9550df..bdd0def 100644
---- a/Makefile.in
-+++ b/Makefile.in
-@@ -49,17 +49,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
-@@ -132,6 +133,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
 diff --git a/aclocal.m4 b/aclocal.m4
 index 3d3673e..6e09291 100644
 --- a/aclocal.m4
@@ -52,48 +10,6 @@ index 3d3673e..6e09291 100644
  m4_include([m4/libnih.m4])
  m4_include([m4/libtool.m4])
  m4_include([m4/lock.m4])
-diff --git a/conf/Makefile.in b/conf/Makefile.in
-index 29fd9b7..82c3f99 100644
---- a/conf/Makefile.in
-+++ b/conf/Makefile.in
-@@ -46,17 +46,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- mkinstalldirs = $(install_sh) -d
-@@ -100,6 +101,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
 diff --git a/config.h.in b/config.h.in
 index 8a7d63f..8d000aa 100644
 --- a/config.h.in
@@ -108,212 +24,11 @@ index 8a7d63f..8d000aa 100644
  /* Define to 1 if you have the <limits.h> header file. */
  #undef HAVE_LIMITS_H
  
-diff --git a/configure b/configure
-index 9bad2db..2f93ef5 100755
---- a/configure
-+++ b/configure
-@@ -751,6 +751,7 @@ ac_subst_vars='am__EXEEXT_FALSE
- am__EXEEXT_TRUE
- LTLIBOBJS
- LIBOBJS
-+AUDIT_LDADD
- DBUS_LIBS
- DBUS_CFLAGS
- NIH_DBUS_LIBS
-@@ -938,6 +939,7 @@ with_included_gettext
- with_libintl_prefix
- with_local_libnih
- enable_threading
-+with_libaudit
- enable_compiler_warnings
- enable_compiler_optimisations
- enable_compiler_coverage
-@@ -1620,6 +1622,7 @@ Optional Packages:
-   --without-libintl-prefix     don't search for libintl in includedir and libdir
-   --with-local-libnih[=DIR]
-                           Use libnih from source tree DIR
-+  --with-libaudit=auto/yes/no  Add Linux audit support default=auto
- 
- Some influential environment variables:
-   CC          C compiler command
-@@ -5220,13 +5223,13 @@ if test "${lt_cv_nm_interface+set}" = set; then :
- else
-   lt_cv_nm_interface="BSD nm"
-   echo "int some_variable = 0;" > conftest.$ac_ext
--  (eval echo "\"\$as_me:5223: $ac_compile\"" >&5)
-+  (eval echo "\"\$as_me:5226: $ac_compile\"" >&5)
-   (eval "$ac_compile" 2>conftest.err)
-   cat conftest.err >&5
--  (eval echo "\"\$as_me:5226: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
-+  (eval echo "\"\$as_me:5229: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
-   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
-   cat conftest.err >&5
--  (eval echo "\"\$as_me:5229: output\"" >&5)
-+  (eval echo "\"\$as_me:5232: output\"" >&5)
-   cat conftest.out >&5
-   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
-     lt_cv_nm_interface="MS dumpbin"
-@@ -6431,7 +6434,7 @@ ia64-*-hpux*)
-   ;;
- *-*-irix6*)
-   # Find out which ABI we are using.
--  echo '#line 6434 "configure"' > conftest.$ac_ext
-+  echo '#line 6437 "configure"' > conftest.$ac_ext
-   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-   (eval $ac_compile) 2>&5
-   ac_status=$?
-@@ -7693,11 +7696,11 @@ else
-    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-    -e 's:$: $lt_compiler_flag:'`
--   (eval echo "\"\$as_me:7696: $lt_compile\"" >&5)
-+   (eval echo "\"\$as_me:7699: $lt_compile\"" >&5)
-    (eval "$lt_compile" 2>conftest.err)
-    ac_status=$?
-    cat conftest.err >&5
--   echo "$as_me:7700: \$? = $ac_status" >&5
-+   echo "$as_me:7703: \$? = $ac_status" >&5
-    if (exit $ac_status) && test -s "$ac_outfile"; then
-      # The compiler can only warn and ignore the option if not recognized
-      # So say no if there are warnings other than the usual output.
-@@ -8032,11 +8035,11 @@ else
-    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-    -e 's:$: $lt_compiler_flag:'`
--   (eval echo "\"\$as_me:8035: $lt_compile\"" >&5)
-+   (eval echo "\"\$as_me:8038: $lt_compile\"" >&5)
-    (eval "$lt_compile" 2>conftest.err)
-    ac_status=$?
-    cat conftest.err >&5
--   echo "$as_me:8039: \$? = $ac_status" >&5
-+   echo "$as_me:8042: \$? = $ac_status" >&5
-    if (exit $ac_status) && test -s "$ac_outfile"; then
-      # The compiler can only warn and ignore the option if not recognized
-      # So say no if there are warnings other than the usual output.
-@@ -8137,11 +8140,11 @@ else
-    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-    -e 's:$: $lt_compiler_flag:'`
--   (eval echo "\"\$as_me:8140: $lt_compile\"" >&5)
-+   (eval echo "\"\$as_me:8143: $lt_compile\"" >&5)
-    (eval "$lt_compile" 2>out/conftest.err)
-    ac_status=$?
-    cat out/conftest.err >&5
--   echo "$as_me:8144: \$? = $ac_status" >&5
-+   echo "$as_me:8147: \$? = $ac_status" >&5
-    if (exit $ac_status) && test -s out/conftest2.$ac_objext
-    then
-      # The compiler can only warn and ignore the option if not recognized
-@@ -8192,11 +8195,11 @@ else
-    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-    -e 's:$: $lt_compiler_flag:'`
--   (eval echo "\"\$as_me:8195: $lt_compile\"" >&5)
-+   (eval echo "\"\$as_me:8198: $lt_compile\"" >&5)
-    (eval "$lt_compile" 2>out/conftest.err)
-    ac_status=$?
-    cat out/conftest.err >&5
--   echo "$as_me:8199: \$? = $ac_status" >&5
-+   echo "$as_me:8202: \$? = $ac_status" >&5
-    if (exit $ac_status) && test -s out/conftest2.$ac_objext
-    then
-      # The compiler can only warn and ignore the option if not recognized
-@@ -10576,7 +10579,7 @@ else
-   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
-   lt_status=$lt_dlunknown
-   cat > conftest.$ac_ext <<_LT_EOF
--#line 10579 "configure"
-+#line 10582 "configure"
- #include "confdefs.h"
- 
- #if HAVE_DLFCN_H
-@@ -10672,7 +10675,7 @@ else
-   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
-   lt_status=$lt_dlunknown
-   cat > conftest.$ac_ext <<_LT_EOF
--#line 10675 "configure"
-+#line 10678 "configure"
- #include "confdefs.h"
- 
- #if HAVE_DLFCN_H
-@@ -17209,6 +17212,72 @@ fi
- 
- # Checks for library functions.
- 
-+
-+# Check whether --with-libaudit was given.
-+if test "${with_libaudit+set}" = set; then :
-+  withval=$with_libaudit;
-+else
-+  with_libaudit=auto
-+fi
-+
-+
-+  # Check for Linux auditing API
-+  #
-+  # libaudit detection
-+
-+  if test x$with_libaudit = xno ; then
-+      have_libaudit=no;
-+  else
-+      # See if we have audit daemon library
-+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for audit_log_user_message in -laudit" >&5
-+$as_echo_n "checking for audit_log_user_message in -laudit... " >&6; }
-+if test "${ac_cv_lib_audit_audit_log_user_message+set}" = set; then :
-+  $as_echo_n "(cached) " >&6
-+else
-+  ac_check_lib_save_LIBS=$LIBS
-+LIBS="-laudit  $LIBS"
-+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+/* end confdefs.h.  */
-+
-+/* Override any GCC internal prototype to avoid an error.
-+   Use char because int might match the return type of a GCC
-+   builtin and then its argument prototype would still apply.  */
-+#ifdef __cplusplus
-+extern "C"
-+#endif
-+char audit_log_user_message ();
-+int
-+main ()
-+{
-+return audit_log_user_message ();
-+  ;
-+  return 0;
-+}
-+_ACEOF
-+if ac_fn_c_try_link "$LINENO"; then :
-+  ac_cv_lib_audit_audit_log_user_message=yes
-+else
-+  ac_cv_lib_audit_audit_log_user_message=no
-+fi
-+rm -f core conftest.err conftest.$ac_objext \
-+    conftest$ac_exeext conftest.$ac_ext
-+LIBS=$ac_check_lib_save_LIBS
-+fi
-+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_audit_audit_log_user_message" >&5
-+$as_echo "$ac_cv_lib_audit_audit_log_user_message" >&6; }
-+if test "x$ac_cv_lib_audit_audit_log_user_message" = x""yes; then :
-+  AUDIT_LDADD=-laudit
-+fi
-+
-+  fi
-+
-+  if test x$AUDIT_LDADD != x ; then
-+
-+$as_echo "#define HAVE_LIBAUDIT 1" >>confdefs.h
-+
-+  fi
-+
-+
- # Other checks
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include sbindir in PATH" >&5
- $as_echo_n "checking whether to include sbindir in PATH... " >&6; }
 diff --git a/configure.ac b/configure.ac
-index fb79a13..3dc1550 100644
+index 49544e3..1513500 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -54,6 +54,7 @@ AM_PROG_CC_C_O
+@@ -40,6 +40,7 @@ AM_PROG_CC_C_O
  NIH_C_THREAD
  
  # Checks for library functions.
@@ -321,174 +36,6 @@ index fb79a13..3dc1550 100644
  
  # Other checks
  AC_MSG_CHECKING([whether to include sbindir in PATH])
-diff --git a/contrib/Makefile.in b/contrib/Makefile.in
-index dfe910b..32c7ebd 100644
---- a/contrib/Makefile.in
-+++ b/contrib/Makefile.in
-@@ -44,17 +44,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- mkinstalldirs = $(install_sh) -d
-@@ -75,6 +76,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
-diff --git a/dbus/Makefile.in b/dbus/Makefile.in
-index 8294845..38a55ad 100644
---- a/dbus/Makefile.in
-+++ b/dbus/Makefile.in
-@@ -46,17 +46,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- mkinstalldirs = $(install_sh) -d
-@@ -100,6 +101,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
-diff --git a/doc/Makefile.in b/doc/Makefile.in
-index b17181c..add3022 100644
---- a/doc/Makefile.in
-+++ b/doc/Makefile.in
-@@ -44,17 +44,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- mkinstalldirs = $(install_sh) -d
-@@ -75,6 +76,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
-diff --git a/init/Makefile.in b/init/Makefile.in
-index c677761..9ca3de6 100644
---- a/init/Makefile.in
-+++ b/init/Makefile.in
-@@ -55,17 +55,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- mkinstalldirs = $(install_sh) -d
-@@ -283,6 +284,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
 diff --git a/m4/libaudit.m4 b/m4/libaudit.m4
 new file mode 100644
 index 0000000..6865fb8
@@ -584,154 +131,6 @@ index 0b49c10..9a772d5 100644
  
  
  .PHONY: tests
-diff --git a/util/Makefile.in b/util/Makefile.in
-index 55e17e5..40776d5 100644
---- a/util/Makefile.in
-+++ b/util/Makefile.in
-@@ -51,17 +51,18 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
- 	$(top_srcdir)/m4/inttypes-pri.m4 \
- 	$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
- 	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
--	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnih.m4 \
--	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/lock.m4 \
--	$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/ltoptions.m4 \
--	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
--	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
--	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
--	$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
--	$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
--	$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \
--	$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
--	$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
-+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libaudit.m4 \
-+	$(top_srcdir)/m4/libnih.m4 $(top_srcdir)/m4/libtool.m4 \
-+	$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
-+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
-+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
-+	$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \
-+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
-+	$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \
-+	$(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \
-+	$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
-+	$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
-+	$(top_srcdir)/configure.ac
- am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- 	$(ACLOCAL_M4)
- mkinstalldirs = $(install_sh) -d
-@@ -88,20 +89,24 @@ am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
- am__v_lt_0 = --silent
- am_reboot_OBJECTS = reboot.$(OBJEXT) utmp.$(OBJEXT)
- reboot_OBJECTS = $(am_reboot_OBJECTS)
--reboot_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-+reboot_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-+	$(am__DEPENDENCIES_1)
- am_runlevel_OBJECTS = runlevel.$(OBJEXT) utmp.$(OBJEXT)
- runlevel_OBJECTS = $(am_runlevel_OBJECTS)
--runlevel_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-+runlevel_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-+	$(am__DEPENDENCIES_1)
- am_shutdown_OBJECTS = shutdown.$(OBJEXT) utmp.$(OBJEXT) sysv.$(OBJEXT)
- nodist_shutdown_OBJECTS = $(am__objects_1)
- shutdown_OBJECTS = $(am_shutdown_OBJECTS) $(nodist_shutdown_OBJECTS)
- shutdown_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
--	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-+	$(am__DEPENDENCIES_1)
- am_telinit_OBJECTS = telinit.$(OBJEXT) utmp.$(OBJEXT) sysv.$(OBJEXT)
- nodist_telinit_OBJECTS = $(am__objects_1)
- telinit_OBJECTS = $(am_telinit_OBJECTS) $(nodist_telinit_OBJECTS)
- telinit_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
--	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-+	$(am__DEPENDENCIES_1)
- am_test_initctl_OBJECTS = test_initctl-test_initctl.$(OBJEXT) \
- 	test_initctl-initctl.$(OBJEXT)
- test_initctl_OBJECTS = $(am_test_initctl_OBJECTS)
-@@ -118,14 +123,14 @@ test_sysv_OBJECTS = $(am_test_sysv_OBJECTS) \
- 	$(nodist_test_sysv_OBJECTS)
- test_sysv_DEPENDENCIES = sysv.o utmp.o $(am__DEPENDENCIES_1) \
- 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
--	$(am__DEPENDENCIES_1)
-+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
- am_test_telinit_OBJECTS = test_telinit-test_telinit.$(OBJEXT) \
- 	test_telinit-telinit.$(OBJEXT)
- test_telinit_OBJECTS = $(am_test_telinit_OBJECTS)
- test_telinit_DEPENDENCIES = sysv.o utmp.o com.ubuntu.Upstart.o \
- 	com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
- 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
--	$(am__DEPENDENCIES_1)
-+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
- test_telinit_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
- 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_telinit_CFLAGS) \
- 	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-@@ -216,6 +221,7 @@ ALLOCA = @ALLOCA@
- AMTAR = @AMTAR@
- AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
- AR = @AR@
-+AUDIT_LDADD = @AUDIT_LDADD@
- AUTOCONF = @AUTOCONF@
- AUTOHEADER = @AUTOHEADER@
- AUTOMAKE = @AUTOMAKE@
-@@ -419,7 +425,8 @@ reboot_SOURCES = \
- 
- reboot_LDADD = \
- 	$(LTLIBINTL) \
--	$(NIH_LIBS)
-+	$(NIH_LIBS) \
-+	$(AUDIT_LDADD)
- 
- runlevel_SOURCES = \
- 	runlevel.c \
-@@ -427,7 +434,8 @@ runlevel_SOURCES = \
- 
- runlevel_LDADD = \
- 	$(LTLIBINTL) \
--	$(NIH_LIBS)
-+	$(NIH_LIBS) \
-+	$(AUDIT_LDADD)
- 
- shutdown_SOURCES = \
- 	shutdown.c \
-@@ -441,7 +449,8 @@ shutdown_LDADD = \
- 	$(LTLIBINTL) \
- 	$(NIH_LIBS) \
- 	$(NIH_DBUS_LIBS) \
--	$(DBUS_LIBS)
-+	$(DBUS_LIBS) \
-+	$(AUDIT_LDADD)
- 
- telinit_SOURCES = \
- 	telinit.c \
-@@ -455,7 +464,8 @@ telinit_LDADD = \
- 	$(LTLIBINTL) \
- 	$(NIH_LIBS) \
- 	$(NIH_DBUS_LIBS) \
--	$(DBUS_LIBS)
-+	$(DBUS_LIBS) \
-+	$(AUDIT_LDADD)
- 
- com_ubuntu_Upstart_OUTPUTS = \
- 	com.ubuntu.Upstart.c \
-@@ -515,7 +525,8 @@ test_sysv_LDADD = \
- 	$(LTLIBINTL) \
- 	$(NIH_LIBS) \
- 	$(NIH_DBUS_LIBS) \
--	$(DBUS_LIBS)
-+	$(DBUS_LIBS) \
-+	$(AUDIT_LDADD)
- 
- test_telinit_SOURCES = tests/test_telinit.c telinit.c
- test_telinit_CFLAGS = $(AM_CFLAGS) -DTEST
-@@ -525,7 +536,8 @@ test_telinit_LDADD = \
- 	com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
- 	$(NIH_LIBS) \
- 	$(NIH_DBUS_LIBS) \
--	$(DBUS_LIBS)
-+	$(DBUS_LIBS) \
-+	$(AUDIT_LDADD)
- 
- all: $(BUILT_SOURCES)
- 	$(MAKE) $(AM_MAKEFLAGS) all-am
 diff --git a/util/reboot.c b/util/reboot.c
 index 7a9c071..15028eb 100644
 --- a/util/reboot.c
diff --git a/upstart-override.patch b/upstart-override.patch
new file mode 100644
index 0000000..7989d57
--- /dev/null
+++ b/upstart-override.patch
@@ -0,0 +1,5145 @@
+diff --git a/init/conf.c b/init/conf.c
+index 89d2cd3..a5a9b85 100644
+--- a/init/conf.c
++++ b/init/conf.c
+@@ -49,7 +49,7 @@
+ #include "parse_conf.h"
+ #include "conf.h"
+ #include "errors.h"
+-
++#include "paths.h"
+ 
+ /* Prototypes for static functions */
+ static int  conf_source_reload_file    (ConfSource *source)
+@@ -71,9 +71,19 @@ static int  conf_file_visitor          (ConfSource *source,
+ 					struct stat *statbuf)
+ 	__attribute__ ((warn_unused_result));
+ 
+-static int  conf_reload_path           (ConfSource *source, const char *path)
++static int  conf_reload_path           (ConfSource *source, const char *path,
++					const char *override_path)
++	__attribute__ ((warn_unused_result));
++
++static inline int  is_conf_file        (const char *path)
+ 	__attribute__ ((warn_unused_result));
+ 
++static inline int is_conf_file_std     (const char *path)
++	__attribute__ ((warn_unused_result));
++
++static inline int
++is_conf_file_override                  (const char *path)
++	__attribute__ ((warn_unused_result));
+ 
+ /**
+  * conf_sources:
+@@ -86,6 +96,115 @@ NihList *conf_sources = NULL;
+ 
+ 
+ /**
++ * is_conf_file_std:
++ * @path: path to check.
++ *
++ * Determine if specified path contains a legitimate
++ * configuration file name.
++ *
++ * Returns: TRUE if @path contains a valid configuration file name,
++ * else FALSE.
++ *
++ **/
++static inline int
++is_conf_file_std (const char *path)
++{
++	char *ptr = strrchr (path, '.');
++
++	if (ptr && IS_CONF_EXT_STD (ptr))
++		return TRUE;
++
++	return FALSE;
++}
++
++/**
++ * is_conf_file_override:
++ * @path: path to check.
++ *
++ * Determine if specified path contains a legitimate
++ * override file name.
++ *
++ * Returns: TRUE if @path contains a valid override file name,
++ * else FALSE.
++ *
++ **/
++static inline int
++is_conf_file_override (const char *path)
++{
++	char *ptr = strrchr (path, '.');
++
++	if (ptr && IS_CONF_EXT_OVERRIDE (ptr))
++		return TRUE;
++
++	return FALSE;
++}
++
++/**
++ * is_conf_file:
++ * @path: path to check.
++ *
++ * Determine if specified path contains a legitimate
++ * configuration file or override file name.
++ *
++ * Returns: TRUE if @path contains a valid configuration
++ * file or override file name, else FALSE.
++ *
++ **/
++static inline int
++is_conf_file (const char *path)
++{
++	char *ptr = strrchr (path, '.');
++
++	if (ptr && (ptr > path) && (ptr[-1] != '/') && IS_CONF_EXT (ptr))
++		return TRUE;
++
++	return FALSE;
++}
++
++/**
++ * Convert a configuration file name to an override file name and vice
++ * versa.
++ *
++ * For example, if @path is "foo.conf", this function will return
++ * "foo.override", whereas if @path is "foo.override", it will return
++ * "foo.conf".
++ *
++ * Note that this function should be static, but isn't to allow the
++ * tests to access it.
++ *
++ * @parent: parent of returned path,
++ * @path: path to a configuration file.
++ *
++ * Returns: newly allocated toggled path, or NULL on error.
++ **/
++char *
++toggle_conf_name (const void     *parent,
++		 const char     *path)
++{
++	char *new_path;
++	char *ext;
++	char *new_ext;
++	size_t len;
++
++	ext = strrchr (path, '.');
++	if (!ext)
++		return NULL;
++
++	new_ext = IS_CONF_EXT_STD (ext)
++		? CONF_EXT_OVERRIDE
++		: CONF_EXT_STD;
++
++	len = strlen (new_ext);
++
++	new_path = NIH_MUST (nih_strndup (parent, path, (ext - path) + len));
++
++	memcpy (new_path + (ext - path), new_ext, len);
++
++	return new_path;
++}
++
++
++/**
+  * conf_init:
+  *
+  * Initialise the conf_sources list.
+@@ -233,10 +352,9 @@ conf_reload (void)
+ 			NihError *err;
+ 
+ 			err = nih_error_get ();
+-			if (err->number != ENOENT)
+-				nih_error ("%s: %s: %s", source->path,
+-					   _("Unable to load configuration"),
+-					   err->message);
++			nih_error ("%s: %s: %s", source->path,
++					_("Unable to load configuration"),
++					err->message);
+ 			nih_free (err);
+ 		}
+ 	}
+@@ -329,10 +447,16 @@ static int
+ conf_source_reload_file (ConfSource *source)
+ {
+ 	NihError *err = NULL;
++	nih_local char *override_path = NULL;
++
++	struct stat statbuf;
+ 
+ 	nih_assert (source != NULL);
+ 	nih_assert (source->type == CONF_FILE);
+ 
++	/* this function should only be called for standard
++	 * configuration files.
++	 */
+ 	if (! source->watch) {
+ 		nih_local char *dpath = NULL;
+ 		char           *dname;
+@@ -361,7 +485,7 @@ conf_source_reload_file (ConfSource *source)
+ 	/* Parse the file itself.  If this fails, then we can discard the
+ 	 * inotify error, since this one will be better.
+ 	 */
+-	if (conf_reload_path (source, source->path) < 0) {
++	if (conf_reload_path (source, source->path, NULL) < 0) {
+ 		if (err)
+ 			nih_free (err);
+ 
+@@ -382,6 +506,26 @@ conf_source_reload_file (ConfSource *source)
+ 		nih_free (err);
+ 	}
+ 
++	if (! is_conf_file_std (source->path))
++		return 0;
++
++	override_path = toggle_conf_name (NULL, source->path);
++
++	if (stat (override_path, &statbuf) != 0)
++		return 0;
++
++	nih_debug ("Updating configuration for %s from %s",
++		  source->path, override_path);
++	if (conf_reload_path (source, source->path, override_path) < 0) {
++		NihError *err;
++
++		err = nih_error_get ();
++		nih_error ("%s: %s: %s", override_path,
++				_("Error while reloading configuration file"),
++				err->message);
++		nih_free (err);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -501,19 +645,18 @@ conf_file_filter (ConfSource *source,
+  * @is_dir: TRUE of @path is a directory.
+  *
+  * This is the file filter used for the jobs directory, we only care
+- * about paths with the ".conf" extension.  Directories that
+- * match the nih_file_ignore() function are also ignored.
++ * about paths with particular extensions (see IS_CONF_EXT).
++ *
++ * Directories that match the nih_file_ignore() function are also ignored.
+  *
+- * Returns: FALSE if @path ends in ".conf", or is the original source,
+- * TRUE otherwise.
++ * Returns: FALSE if @path ends in ".conf" or ".override",
++ * or is the original source, TRUE otherwise.
+  **/
+ static int
+ conf_dir_filter (ConfSource *source,
+ 		 const char *path,
+ 		 int         is_dir)
+ {
+-	char *ptr;
+-
+ 	nih_assert (source != NULL);
+ 	nih_assert (path != NULL);
+ 
+@@ -523,8 +666,7 @@ conf_dir_filter (ConfSource *source,
+ 	if (is_dir)
+ 		return nih_file_ignore (NULL, path);
+ 
+-	ptr = strrchr (path, '.');
+-	if (ptr && (ptr > path) && (ptr[-1] != '/') && (! strcmp (ptr, ".conf")))
++	if (is_conf_file (path))
+ 		return FALSE;
+ 
+ 	return TRUE;
+@@ -546,29 +688,92 @@ conf_dir_filter (ConfSource *source,
+  * After checking that it was a regular file that was changed, we reload it;
+  * we expect this to fail sometimes since the file may be only partially
+  * written.
+-  **/
++ **/
+ static void
+ conf_create_modify_handler (ConfSource  *source,
+ 			    NihWatch    *watch,
+ 			    const char  *path,
+ 			    struct stat *statbuf)
+ {
++	ConfFile *file = NULL;
++	const char *error_path = path;
++	nih_local char *new_path = NULL;
++	int ret;
++
+ 	nih_assert (source != NULL);
+ 	nih_assert (watch != NULL);
+ 	nih_assert (path != NULL);
+ 	nih_assert (statbuf != NULL);
+ 
++	/* note that symbolic links are ignored */
+ 	if (! S_ISREG (statbuf->st_mode))
+ 		return;
+ 
+-	if (conf_reload_path (source, path) < 0) {
++	new_path = toggle_conf_name (NULL, path);
++	file = (ConfFile *)nih_hash_lookup (source->files, new_path);
++
++	if (is_conf_file_override (path)) {
++		if (! file) {
++			/* override file has no corresponding conf file */
++			nih_debug ("Ignoring orphan override file %s", path);
++			return;
++		}
++
++		/* reload conf file */
++		nih_debug ("Loading configuration file %s", new_path);
++		ret = conf_reload_path (source, new_path, NULL);
++		if (ret < 0) {
++			error_path = new_path;
++			goto error;
++		}
++
++		/* overlay override settings */
++		nih_debug ("Loading override file %s for %s", path, new_path);
++		ret = conf_reload_path (source, new_path, path);
++		if (ret < 0) {
++			error_path = path;
++			goto error;
++		}
++	} else {
++		nih_debug ("Loading configuration and override files for %s", path);
++
++		/* load conf file */
++		nih_debug ("Loading configuration file %s", path);
++		ret = conf_reload_path (source, path, NULL);
++		if (ret < 0) {
++			error_path = path;
++			goto error;
++		}
++
++		/* ensure we ignore directory changes (which won't have overrides. */
++		if (is_conf_file_std (path)) {
++			struct stat st;
++			if (stat (new_path, &st) == 0) {
++				/* overlay override settings */
++				nih_debug ("Loading override file %s for %s", new_path, path);
++				ret = conf_reload_path (source, path, new_path);
++				if (ret < 0) {
++					error_path = new_path;
++					goto error;
++				}
++			}
++
++		}
++	}
++
++	return;
++
++error:
++	{
+ 		NihError *err;
+ 
+ 		err = nih_error_get ();
+-		nih_error ("%s: %s: %s", path,
+-			   _("Error while loading configuration file"),
+-			   err->message);
++		nih_error ("%s: %s: %s", error_path,
++				_("Error while loading configuration file"),
++				err->message);
+ 		nih_free (err);
++		if (file)
++			nih_unref (file, source);
+ 	}
+ }
+ 
+@@ -585,13 +790,14 @@ conf_create_modify_handler (ConfSource  *source,
+  *
+  * We lookup the file in our hash table, and if we can find it, perform
+  * the usual deletion of it.
+-  **/
++ **/
+ static void
+ conf_delete_handler (ConfSource *source,
+ 		     NihWatch   *watch,
+ 		     const char *path)
+ {
+ 	ConfFile *file;
++	nih_local char *new_path = NULL;
+ 
+ 	nih_assert (source != NULL);
+ 	nih_assert (watch != NULL);
+@@ -603,7 +809,11 @@ conf_delete_handler (ConfSource *source,
+ 	 * it's probably a directory or something, so just ignore it.
+ 	 */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, path);
+-	if (! file) {
++	/* Note we have to be careful to consider deletion of directories too.
++	 * This is handled implicitly by the override check which will return
++	 * false if passed a directory in this case.
++	 */
++	if (! file && ! is_conf_file_override (path)) {
+ 		if (! strcmp (watch->path, path)) {
+ 			nih_warn ("%s: %s", source->path,
+ 				  _("Configuration directory deleted"));
+@@ -614,7 +824,30 @@ conf_delete_handler (ConfSource *source,
+ 		return;
+ 	}
+ 
+-	nih_unref (file, source);
++	/* non-override files (and directories) are the simple case, so handle
++	 * them and leave.
++	 */ 
++	if (! is_conf_file_override (path)) {
++		nih_unref (file, source);
++		return;
++	}
++
++	/* if an override file is deleted for which there is a corresponding
++	 * conf file, reload the conf file to remove any modifications
++	 * introduced by the override file.
++	 */
++	new_path = toggle_conf_name (NULL, path);
++	file = (ConfFile *)nih_hash_lookup (source->files, new_path);
++
++	if (file) {
++		nih_debug ("Reloading configuration for %s on deletion of overide (%s)",
++				new_path, path);
++
++		if ( conf_reload_path (source, new_path, NULL) < 0 ) {
++			nih_warn ("%s: %s", new_path,
++					_("Unable to reload configuration after override deletion"));
++		}
++	}
+ }
+ 
+ /**
+@@ -637,22 +870,61 @@ conf_file_visitor (ConfSource  *source,
+ 		   const char  *path,
+ 		   struct stat *statbuf)
+ {
++	ConfFile *file = NULL;
++	nih_local char *new_path = NULL;
++
+ 	nih_assert (source != NULL);
+ 	nih_assert (dirname != NULL);
+ 	nih_assert (path != NULL);
+ 	nih_assert (statbuf != NULL);
+ 
++	/* We assume that CONF_EXT_STD files are visited before
++	 * CONF_EXT_OVERRIDE files. Happily, this assumption is currently
++	 * valid since CONF_EXT_STD comes before CONF_EXT_OVERRIDE if ordered
++	 * alphabetically.
++	 *
++	 * If this were ever to change (for example if we decided to
++	 * rename the CONF_EXT_OVERRIDE files to end in ".abc", say), the logic
++	 * in this function would be erroneous since it would never be possible when
++	 * visiting an override file (before a conf file) to lookup a conf file
++	 * in the hash, since the conf file would not yet have been seen and thus would
++	 * not exist in the hash (yet).
++	 */
++	nih_assert (CONF_EXT_STD[1] < CONF_EXT_OVERRIDE[1]);
++
+ 	if (! S_ISREG (statbuf->st_mode))
+ 		return 0;
+ 
+-	if (conf_reload_path (source, path) < 0) {
+-		NihError *err;
++	if (is_conf_file_std (path)) {
++		if (conf_reload_path (source, path, NULL) < 0) {
++			NihError *err;
+ 
+-		err = nih_error_get ();
+-		nih_error ("%s: %s: %s", path,
+-			   _("Error while loading configuration file"),
+-			   err->message);
+-		nih_free (err);
++			err = nih_error_get ();
++			nih_error ("%s: %s: %s", path,
++					_("Error while loading configuration file"),
++					err->message);
++			nih_free (err);
++		}
++		return 0;
++	}
++
++	new_path = toggle_conf_name (NULL, path);
++	file = (ConfFile *)nih_hash_lookup (source->files, new_path);
++
++	if (file) {
++		/* we're visiting an override file with an associated conf file that
++		 * has already been loaded, so just overlay the override file. If
++		 * there is no corresponding conf file, we ignore the override file.
++		 */
++		if (conf_reload_path (source, new_path, path) < 0) {
++			NihError *err;
++
++			err = nih_error_get ();
++			nih_error ("%s: %s: %s", new_path,
++					_("Error while reloading configuration file"),
++					err->message);
++			nih_free (err);
++		}
+ 	}
+ 
+ 	return 0;
+@@ -662,12 +934,15 @@ conf_file_visitor (ConfSource  *source,
+ /**
+  * conf_reload_path:
+  * @source: configuration source,
+- * @path: path of file to be reloaded.
++ * @path: path of conf file to be reloaded.
++ * @override_path: if TRUE and @path refers to a path associated with @source,
++ * overlay the contents of @path into the existing @source entry for
++ * @path. If FALSE, discard any existing knowledge of @path.
+  *
+- * This function is used to parse the file at @path in the context of the
+- * given configuration @source.  Necessary ConfFile structures are allocated
+- * and attached to @source as appropriate.  CONF_FILE sources always have
+- * a single ConfFile when the file exists.
++ * This function is used to parse the file at @path (or @override_path) in the
++ * context of the given configuration @source.  Necessary ConfFile structures
++ * are allocated and attached to @source as appropriate.  CONF_FILE sources
++ * always have a single ConfFile when the file exists.
+  *
+  * If the file has been parsed before, then the existing item is deleted and
+  * freed if the file fails to load, or after the new item has been parsed.
+@@ -679,36 +954,43 @@ conf_file_visitor (ConfSource  *source,
+  **/
+ static int
+ conf_reload_path (ConfSource *source,
+-		  const char *path)
++	  const char *path,
++	  const char *override_path)
+ {
+-	ConfFile       *file;
++	ConfFile       *file = NULL;
+ 	nih_local char *buf = NULL;
+ 	const char     *start, *end;
+ 	nih_local char *name = NULL;
+ 	size_t          len, pos, lineno;
+ 	NihError       *err = NULL;
++	const char     *path_to_load;
+ 
+ 	nih_assert (source != NULL);
+ 	nih_assert (path != NULL);
+ 
+-	/* Look up the old file in memory, and then free it.  In cases
+-	 * of failure, we discard it anyway, so there's no particular reason
++	path_to_load = ( override_path ? override_path : path);
++
++	/* If there is no corresponding override file, look up the old
++	 * conf file in memory, and then free it.  In cases of failure,
++	 * we discard it anyway, so there's no particular reason
+ 	 * to keep it around anymore.
+ 	 */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, path);
+-	if (file)
++	if (! override_path && file)
+ 		nih_unref (file, source);
+ 
+ 	/* Read the file into memory for parsing, if this fails we don't
+ 	 * bother creating a new ConfFile structure for it and bail out
+ 	 * now.
+ 	 */
+-	buf = nih_file_read (NULL, path, &len);
++	buf = nih_file_read (NULL, path_to_load, &len);
+ 	if (! buf)
+ 		return -1;
+ 
+-	/* Parse the file, storing the item in a new ConfFile structure. */
+-	file = NIH_MUST (conf_file_new (source, path));
++	/* Create a new ConfFile structure (if no override_path was specified) */
++	file = (ConfFile *)nih_hash_lookup (source->files, path);
++	if (! file)
++		file = NIH_MUST (conf_file_new (source, path));
+ 
+ 	pos = 0;
+ 	lineno = 1;
+@@ -717,7 +999,14 @@ conf_reload_path (ConfSource *source,
+ 	case CONF_FILE:
+ 	case CONF_DIR:
+ 		/* Simple file of options; usually no item attached to it. */
+-		nih_debug ("Loading configuration from %s", path);
++		if (override_path) {
++			nih_debug ("Updating configuration for %s from %s",
++					path, override_path);
++		} else {
++			nih_debug ("Loading configuration from %s %s",
++					(source->type == CONF_DIR ? "directory" : "file"), path);
++		}
++
+ 		if (parse_conf (file, buf, len, &pos, &lineno) < 0)
+ 			err = nih_error_get ();
+ 
+@@ -735,7 +1024,7 @@ conf_reload_path (ConfSource *source,
+ 			start++;
+ 
+ 		end = strrchr (start, '.');
+-		if (end && (! strcmp (end, ".conf"))) {
++		if (end && IS_CONF_EXT (end)) {
+ 			name = NIH_MUST (nih_strndup (NULL, start, end - start));
+ 		} else {
+ 			name = NIH_MUST (nih_strdup (NULL, start));
+@@ -744,8 +1033,14 @@ conf_reload_path (ConfSource *source,
+ 		/* Create a new job item and parse the buffer to produce
+ 		 * the job definition.
+ 		 */
+-		nih_debug ("Loading %s from %s", name, path);
+-		file->job = parse_job (NULL, name, buf, len, &pos, &lineno);
++		if (override_path) {
++			nih_debug ("Updating %s (%s) with %s",
++					name, path, override_path);
++		} else {
++			nih_debug ("Loading %s from %s", name, path);
++		}
++		file->job = parse_job (NULL, file->job,
++			name, buf, len, &pos, &lineno);
+ 		if (file->job) {
+ 			job_class_consider (file->job);
+ 		} else {
+@@ -779,7 +1074,7 @@ conf_reload_path (ConfSource *source,
+ 		case PARSE_EXPECTED_OPERATOR:
+ 		case PARSE_EXPECTED_VARIABLE:
+ 		case PARSE_MISMATCHED_PARENS:
+-			nih_error ("%s:%zi: %s", path, lineno, err->message);
++			nih_error ("%s:%zi: %s", path_to_load, lineno, err->message);
+ 			nih_free (err);
+ 			err = NULL;
+ 			break;
+@@ -882,3 +1177,149 @@ conf_select_job (const char *name)
+ 
+ 	return NULL;
+ }
++
++#ifdef DEBUG
++
++size_t
++debug_count_list_entries (const NihList *list)
++{
++	size_t i = 0;
++	NIH_LIST_FOREACH (list, iter) {
++		i++;
++	}
++	return i;
++}
++
++size_t
++debug_count_hash_entries (const NihHash *hash)
++{
++	size_t i = 0;
++	NIH_HASH_FOREACH_SAFE (hash, iter) {
++		i++;
++	}
++	return i;
++}
++
++void
++debug_show_job_class (const JobClass *job)
++{
++	int i;
++	char **env    = (char **)job->env;
++	char **export = (char **)job->export;
++
++	nih_assert (job);
++
++	nih_debug ("JobClass %p: name='%s', path='%s', task=%d, "
++			"respawn=%d, console=%x, deleted=%d, debug=%d",
++			job, job->name, job->path, job->task,
++			job->respawn, job->console, job->deleted, job->debug);
++
++	nih_debug ("\tstart_on=%p, stop_on=%p, emits=%p, process=%p",
++			job->start_on, job->stop_on, job->emits, job->process);
++
++	nih_debug ("\tauthor='%s', description='%s'",
++			job->author, job->description);
++
++	if (env && *env) {
++		nih_debug ("\tenv:");
++		i = 0;
++		while ( *env ) {
++			nih_debug ("\t\tenv[%d]='%s' (len=%u+1)",
++					i, *env, strlen (*env));
++			env++;
++			++i;
++		}
++	} else {
++		nih_debug ("\tenv: none.");
++	}
++
++
++	if (export && *export) {
++		nih_debug ("\texport:");
++		i = 0;
++		while ( *export ) {
++			nih_debug ("\t\tenv[%d]='%s' (len=%u+1)",
++					i, *export, strlen (*export));
++			export++;
++			++i;
++		}
++	}
++	else {
++		nih_debug ("\texport: none");
++	}
++}
++
++void
++debug_show_job_classes (void)
++{
++	nih_debug ("job_classes:");
++
++	NIH_HASH_FOREACH_SAFE (job_classes, iter) {
++		JobClass *job = (JobClass *)iter;
++		debug_show_job_class (job);
++	}
++}
++
++void
++debug_show_event (const Event *event)
++{
++	nih_assert (event);
++
++	nih_debug ("Event %p: name='%s', progress=%x, failed=%d, "
++			"blockers=%d, blocking=%p",
++			event, event->name, event->progress, event->failed,
++			event->blockers, (void *)&event->blocking);
++}
++
++void
++debug_show_conf_file (const ConfFile *file)
++{
++	nih_assert (file);
++
++	nih_debug ("ConfFile %p: path='%s', source=%p, flag=%x, job=%p",
++			file, file->path, file->source, file->flag, file->job);
++
++	/* Some ConfFile objects won't have any JobClass details, for example,
++	 * the ConfFile object associated with "/etc/init.conf".
++	 */
++	if (! file->job) {
++		nih_debug ("ConfFile %p: job: no JobClass object.", file);
++		return;
++	}
++
++	nih_debug ("ConfFile %p: job:", file);
++	debug_show_job_class (file->job);
++}
++
++void
++debug_show_conf_source (const ConfSource *source)
++{
++	nih_assert (source);
++
++	nih_debug ("ConfSource %p: path='%s', type=%x, flag=%x",
++			source, source->path, source->type, source->flag);
++
++	nih_debug ("ConfSource %p files (%d):", source,
++			debug_count_hash_entries (source->files));
++
++	NIH_HASH_FOREACH (source->files, file_iter) {
++		ConfFile *file = (ConfFile *)file_iter;
++		debug_show_conf_file (file);
++	}
++}
++
++void
++debug_show_conf_sources (void)
++{
++	nih_assert (conf_sources);
++
++	nih_debug ("conf_sources:");
++
++	NIH_LIST_FOREACH (conf_sources, iter) {
++		ConfSource *source = (ConfSource *)iter;
++		debug_show_conf_source (source);
++	}
++}
++
++#endif /* DEBUG */
++
+diff --git a/init/conf.h b/init/conf.h
+index d6915f3..bac02ac 100644
+--- a/init/conf.h
++++ b/init/conf.h
+@@ -124,6 +124,46 @@ int         conf_file_destroy  (ConfFile *file);
+ 
+ JobClass *  conf_select_job    (const char *name);
+ 
++char *toggle_conf_name         (const void *parent, const char *path)
++	__attribute__ ((warn_unused_result, malloc));
++
++#ifdef DEBUG
++
++/* used for debugging only */
++
++size_t
++debug_count_hash_entries       (const NihHash *hash);
++
++size_t
++debug_count_list_entries       (const NihList *list)
++	__attribute__ ((unused));
++
++void
++debug_show_job_class           (const JobClass *job)
++	__attribute__ ((unused));
++
++void
++debug_show_job_classes         (void)
++	__attribute__ ((unused));
++
++void
++debug_show_event               (const Event *event)
++	__attribute__ ((unused));
++
++void
++debug_show_conf_file(const ConfFile *file)
++	__attribute__ ((unused));
++
++void
++debug_show_conf_source(const ConfSource *source)
++	__attribute__ ((unused));
++
++void
++debug_show_conf_sources(void)
++	__attribute__ ((unused));
++
++#endif
++
+ NIH_END_EXTERN
+ 
+ #endif /* INIT_CONF_H */
+diff --git a/init/man/init.5 b/init/man/init.5
+index 73fff91..56a4d0e 100644
+--- a/init/man/init.5
++++ b/init/man/init.5
+@@ -1,42 +1,79 @@
+-.TH init 5 2010-12-14 "Upstart"
++.TH init 5 2011-01-12 "Upstart"
+ .\"
+ .SH NAME
+ init \- Upstart init daemon job configuration
+ .\"
+ .SH SYNOPSIS
+-.B /etc/init
++.B /etc/init/
+ .\"
+ .SH DESCRIPTION
+ On startup, the Upstart
+ .BR init (8)
+-daemon reads its job configuration from the
+-.I /etc/init
+-directory, and watches for future changes using
++daemon reads its job configuration from files in the
++.I /etc/init/
++directory, and watches for future changes to these files using
+ .BR inotify (7).
+ 
+-Files in this directory must end in
+-.I .conf
+-and may also be present in sub-directories.
++To be considered by Upstart, files in this directory must have a
++recognized suffix and may also be present in sub-directories.  There are
++two recognized suffixes:
+ 
+-Each file defines a single service or task, with the name taken from its
+-relative path within the directory without the extension.  For example a
+-job defined in
++.IP \(bu 4 
++Files ending in
++.I .conf
++are called configuration files, or simply "conf files" for short.
++These are the primary vehicle for specifying a job.
++.IP \(bu 4 
++Files ending in
++.I .override
++are called override files.  If an override file is present, the stanzas
++it contains take precedence over those equivalently named stanzas in the
++corresponding configuration file contents for a particular job.
++The main use for override files is to modify how a job will run without
++having to modify its configuration file directly.  See the section
++\fBOverride File Handling\fP below for further details.
++.P
++A job can thus be defined by either:
++.IP \[bu] 2
++A single configuration file.
++.IP \[bu]
++A single configuration file \fBand\fP a single override file.
++.P
++Unless explicitly stated otherwise, any reference to a jobs
++configuration can refer both to a configuration file or an override
++file.
++
++Each configuration file defines the template for a single \fIservice\fP
++(long-running process or daemon) or \fItask\fP (short-lived process).
++
++Note that a configuration file is not itself a job: it is a description
++of an environmenta job could be run in.  A job is the runtime embodiment
++of a configuration file.
++
++The configuration file name as displayed by Upstart and associated
++tooling is taken from its relative path within the directory without the
++extension.  For example a configuration file
+ .I /etc/init/rc-sysinit.conf
+ is named
+ .IR rc-sysinit ,
+-while a job defined in
++while a configuration file
+ .I /etc/init/net/apache.conf
+ is named
+ .IR net/apache .
++Since override files only modify the way a configuration file is
++interpreted, they are not named.
+ 
+-These files are plain text and should not be executable.
++Configuration files are plain text and should not be executable.
+ .\"
+-.SS Format
++.SS Configuration File Format
+ Each line begins with a configuration stanza and continues until either
+ the end of the line or a line containing a closing stanza.  Line breaks
+ within a stanza are permitted within single or double quotes, or if
+ preceeded by a blackslash.
+ 
++If a stanza is duplicated, the last occurence will be used. Unrecognized
++stanzas will generate parse errors, which will stop a job from running.
++
+ Stanzas and their arguments are delimited by whitespace, which consists
+ of one or more space or tab characters which are otherwise ignored unless
+ placed within single or double quotes.
+@@ -144,10 +181,10 @@ event is emitted.  It is typically used to clean up the environment,
+ such as removing temporary directories.
+ 
+ .PP
+-All of these processes, including the main process, are optional.  Services
+-without a main process will appear to be running until they are stopped,
+-this is commonly used to define states such as runlevels.  It's quite
+-permissable to have no main process, but to have
++All of these processes, including the main process, are optional.
++Services without a main process will appear to be running until they are
++stopped: this is commonly used to define states such as runlevels.  It
++is permissable to have no main process, but to have
+ .B pre-start
+ and
+ .B post-stop
+@@ -249,7 +286,7 @@ The
+ .B stop on
+ stanza defines the set of events that will cause the job to be automatically
+ stopped.  It has the same syntax as
+-.B start on
++\fBstart on\fP.
+ 
+ .I VALUE
+ may additionally expand the value of any variable that came from the
+@@ -306,7 +343,8 @@ utility to default to acting on the job the commands are called from.
+ .B env \fIKEY\fR[=\fIVALUE\fR]
+ Defines a default environment variable, the value of which may be overriden
+ by the event or command that starts the job.
+-If no value is given, then the value is taken from the
++If \'KEY=VALUE\' is specified, the variable KEY is given the value VALUE.
++If only \'KEY\' is given, then the value is taken from the
+ .BR init (8)
+ daemon's own environment.
+ .\"
+@@ -366,7 +404,7 @@ Respawning is subject to a limit, if the job is respawned more than
+ times in
+ .I INTERVAL
+ seconds, it will be considered to be having deeper problems and will
+-be stopped.
++be stopped. Default COUNT is 10. Default INTERVAL is 5 seconds.
+ 
+ This only applies to automatic respawns and not the
+ .BR restart (8)
+@@ -385,7 +423,8 @@ normal exit 0 1 TERM HUP
+ .SS Instances
+ By default, only one instance of any job is permitted to exist at one
+ time.  Attempting to start a job when it's already starting or running
+-results in an error.
++results in an error. Note that a job is considered to be running if its
++pre-start process is running.
+ 
+ Multiple instances may be permitted by defining the names of those
+ instances.  If an instance with the same name is not already starting
+@@ -561,6 +600,46 @@ value, both of which are integers.  The special value
+ .B unlimited
+ may be specified for either.
+ .\"
++.SS Override File Handling
++Override files allow a jobs environment to be changed without modifying
++the jobs configuration file. Rules governing override files:
++
++.IP \[bu] 2
++If a job is embodied with only a configuration file, the contents of
++this file define the job.
++.IP \[bu]
++If an override files exists where there is no existing cofiguration
++file, the override file is ignored.
++.IP \[bu]
++If both a configuration file \fBand\fP an override file exist for a job
++and both files are syntactically correct:
++.RS
++.IP \[bu] 2
++stanzas in the override file will take precedence over stanzas present
++in the corresponding configuration file.
++.IP \[bu]
++stanzas in the override file which are not present in the corresponding
++configuration file will be honoured when the job runs.
++.RE
++.IP \[bu]
++If both a configuration file and an override file exist for a job and
++subsequently the override file is deleted, the configuration file is
++automatically reloaded with the effect that any changes introduced by
++the override file are undone and the configuration file alone now defines
++the job.
++.IP \[bu]
++If both a configuration file and an override file exist for a job and
++subsequently the configuration file is deleted, a new instance of the
++job can no longer be started (since without a corresponding
++configuration file an override file is ignored).
++.IP \[bu]
++If both a configuration file and an override file exist for a job and
++any of the contents of the override file are invalid, the override file
++is ignored and only the contents of the configuration file are
++considered.
++.P
++
++.\"
+ .SS Miscellaneous
+ .TP
+ .B kill timeout \fIINTERVAL
+@@ -568,7 +647,7 @@ Specifies the interval between sending the job's main process the
+ .I SIGTERM
+ and
+ .I SIGKILL
+-signals when stopping the running job.
++signals when stopping the running job. Default is 5 seconds.
+ .\"
+ .TP
+ .B expect stop
+@@ -609,6 +688,48 @@ Without this stanza
+ is unable to supervise forking processes and will believe them to have
+ stopped as soon as they fork on startup.
+ .\"
++.SH BUGS
++The 
++.B and
++and 
++.B or
++operators allowed with
++.B start on
++and
++.B stop on
++do not work intuitively: operands to the right of either operator are
++only evaluated once and state information is then discarded. This can
++lead to jobs with complex \fBstart on\fP or \fPstop on\fP conditions
++not behaving as expected \fIwhen restarted\fP. For example, if a job
++encodes the following condition:
++.ti +4
++.sp 1
++.nf
++start on A and (B or C)
++.fi
++
++When 'A' and 'B' become true, the condition is satisfied so the job will
++be run. However, if the job ends and subsequently 'A' and 'C' become true,
++the job will \fInot\fP be re-run even though the condtion is satisfied.
++Avoid using complex conditions with jobs which need to be restarted.
++.\"
++.SH AUTHOR
++Manual page written by Scott James Remnant
++.RB < scott at netsplit.com >
++and James Hunt
++.RB < james.hunt at canonical.com > .
++.\"
++.SH REPORTING BUGS
++Report bugs at
++.RB < https://launchpad.net/upstart/+bugs >
++.\"
++.SH COPYRIGHT
++Copyright \(co 2010 Canonical Ltd.
++.br
++This is free software; see the source for copying conditions.  There is NO
++warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++
++.\"
+ .SH SEE ALSO
+ .BR init (8)
+ .BR sh (1)
+diff --git a/init/parse_job.c b/init/parse_job.c
+index 4e05454..76d3145 100644
+--- a/init/parse_job.c
++++ b/init/parse_job.c
+@@ -263,6 +263,7 @@ static NihConfigStanza stanzas[] = {
+ /**
+  * parse_job:
+  * @parent: parent object for new job,
++ * @update: If not NULL, update the existing specified JobClass,
+  * @name: name of new job,
+  * @file: file or string to parse,
+  * @len: length of @file,
+@@ -278,10 +279,12 @@ static NihConfigStanza stanzas[] = {
+  * of the returned job are freed, the returned job will also be
+  * freed.
+  *
+- * Returns: new JobClass structure on success, NULL on raised error.
++ * Returns: if @update is NULL, returns new JobClass structure on success, NULL on raised error.
++ * If @update is not NULL, returns @update or NULL on error.
+  **/
+ JobClass *
+ parse_job (const void *parent,
++	   JobClass   *update,	
+ 	   const char *name,
+ 	   const char *file,
+ 	   size_t      len,
+@@ -294,13 +297,22 @@ parse_job (const void *parent,
+ 	nih_assert (file != NULL);
+ 	nih_assert (pos != NULL);
+ 
+-	class = job_class_new (parent, name);
++	if (update) {
++		class = update;
++		nih_debug ("Reusing JobClass %s (%s)",
++				class->name, class->path);
++	} else {
++		nih_debug ("Creating new JobClass %s",
++				name);
++		class = job_class_new (parent, name);
++	}
+ 	if (! class)
+ 		nih_return_system_error (NULL);
+ 
+ 	if (nih_config_parse_file (file, len, pos, lineno,
+ 				   stanzas, class) < 0) {
+-		nih_free (class);
++		if (!update)
++			nih_free (class);
+ 		return NULL;
+ 	}
+ 
+diff --git a/init/parse_job.h b/init/parse_job.h
+index f98f70c..65a205f 100644
+--- a/init/parse_job.h
++++ b/init/parse_job.h
+@@ -27,8 +27,8 @@
+ 
+ NIH_BEGIN_EXTERN
+ 
+-JobClass *parse_job (const void *parent, const char *name,
+-		     const char *file, size_t len,
++JobClass *parse_job (const void *parent, JobClass *update,
++		     const char *name, const char *file, size_t len,
+ 		     size_t *pos, size_t *lineno)
+ 	__attribute__ ((warn_unused_result, malloc));
+ 
+diff --git a/init/paths.h b/init/paths.h
+index d7c6fa4..c7ddec1 100644
+--- a/init/paths.h
++++ b/init/paths.h
+@@ -103,5 +103,55 @@
+ #define TELINIT SBINDIR "/telinit"
+ #endif
+ 
++/**
++ * File extension for standard configuration files.
++ **/
++#define CONF_EXT_STD ".conf"
++
++/**
++ * File extension for override files.
++ *
++ * Note that override files are not stored in the ConfSource 'files' hash:
++ * all JobClass information from override files is added to the JobClass for
++ * the corresponding (CONF_EXT_STD) object.
++ **/
++#define CONF_EXT_OVERRIDE ".override"
++
++/**
++ * Determine if specified path extension representes a standard
++ * configuration file.
++ *
++ * @period: pointer to last period in path to check.
++ *
++ * Returns 1 if specified path extension matches that for a
++ * standard configuration file, else return 0.
++ **/
++#define IS_CONF_EXT_STD(period) \
++	(!strcmp (period, CONF_EXT_STD))
++
++/**
++ * Determine if specified path extension representes an
++ * override file.
++ *
++ * @period: pointer to last period in path to check.
++ *
++ * Returns 1 if specified path extension matches that for
++ * an override file, else return 0.
++ **/
++#define IS_CONF_EXT_OVERRIDE(period) \
++	(!strcmp (period, CONF_EXT_OVERRIDE))
++
++/**
++ * Determine if specified filename has a valid configuration
++ * file name extension.
++ *
++ * @period: pointer to last period in filename.
++ *
++ * Returns: TRUE if extension beyond @period is one of the
++ * recognized types, else FALSE.
++ **/
++#define IS_CONF_EXT(period) \
++	(IS_CONF_EXT_STD(period) || \
++	 IS_CONF_EXT_OVERRIDE(period))
+ 
+ #endif /* INIT_PATHS_H */
+diff --git a/init/tests/test_conf.c b/init/tests/test_conf.c
+index 35730b7..9a504de 100644
+--- a/init/tests/test_conf.c
++++ b/init/tests/test_conf.c
+@@ -47,6 +47,50 @@
+ #include "job.h"
+ #include "conf.h"
+ 
++/* macro to try and ensure the environment is as pristine as possible
++ * (to avoid follow-on errors caused by not freeing objects in a
++ * previous test, say)
++ */
++#define TEST_ENSURE_CLEAN_ENV()                                      \
++{                                                                    \
++	setvbuf(stdout, NULL, _IONBF, 0);                            \
++                                                                     \
++	if (job_classes) {                                           \
++		TEST_HASH_EMPTY (job_classes);                       \
++	}                                                            \
++                                                                     \
++	if (conf_sources) {                                          \
++		TEST_LIST_EMPTY (conf_sources);                      \
++	}                                                            \
++                                                                     \
++	if (nih_io_watches) {                                        \
++		TEST_LIST_EMPTY (nih_io_watches);                    \
++	}                                                            \
++                                                                     \
++	if (nih_timers) {                                            \
++		TEST_LIST_EMPTY (nih_timers);                        \
++	}                                                            \
++                                                                     \
++	if (events) {                                                \
++		TEST_LIST_EMPTY (events);                            \
++	}                                                            \
++}
++
++/* Force an inotify watch update */
++#define TEST_FORCE_WATCH_UPDATE()                                    \
++{                                                                    \
++	int         nfds = 0;                                        \
++	fd_set      readfds, writefds, exceptfds;                    \
++	                                                             \
++	FD_ZERO (&readfds);                                          \
++	FD_ZERO (&writefds);                                         \
++	FD_ZERO (&exceptfds);                                        \
++	                                                             \
++	nih_debug("calling nih_io_select_fds");                      \
++	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);  \
++	nih_debug("calling nih_io_handle_fds");                      \
++	nih_io_handle_fds (&readfds, &writefds, &exceptfds);         \
++}
+ 
+ void
+ test_source_new (void)
+@@ -2417,40 +2461,70 @@ no_inotify:
+ 	}
+ }
+ 
+-
+ void
+-test_source_reload_file (void)
++test_toggle_conf_name (void)
+ {
+-	ConfSource *source;
+-	ConfFile   *file, *old_file;
+-	FILE       *f;
+-	int         ret, fd[4096], i = 0, nfds;
+-	char        dirname[PATH_MAX];
+-	char        tmpname[PATH_MAX], filename[PATH_MAX];
+-	fd_set      readfds, writefds, exceptfds;
+-	NihError   *err;
++	char override_ext[] = ".override";
++	char dirname[PATH_MAX];
++	char filename[PATH_MAX];
++	JobClass *job;
++	char *f;
++	char *p;
+ 
+-	TEST_FUNCTION_FEATURE ("conf_source_reload",
+-			       "with configuration file");
+-	program_name = "test";
+-	nih_log_set_priority (NIH_LOG_FATAL);
++	TEST_FUNCTION_FEATURE ("toggle_conf_name",
++			"changing conf to override");
+ 
+ 	TEST_FILENAME (dirname);
+-	mkdir (dirname, 0755);
+-
+ 	strcpy (filename, dirname);
+ 	strcat (filename, "/foo.conf");
++	f = toggle_conf_name (NULL, filename);
++	TEST_NE_P (f, NULL);
+ 
+-	f = fopen (filename, "w");
+-	fprintf (f, "#nothing to test\n");
+-	fclose (f);
++	p = strstr (f, ".override");
++	TEST_NE_P (p, NULL);
++	TEST_EQ_P (p, f+strlen (f) - strlen (override_ext));
++	nih_free (f);
+ 
++	TEST_FEATURE ("changing override to conf");
+ 	strcpy (filename, dirname);
+-	strcat (filename, "/bar.conf");
++	strcat (filename, "/bar.override");
++	f = toggle_conf_name (NULL, filename);
++	TEST_NE_P (f, NULL);
+ 
+-	f = fopen (filename, "w");
+-	fprintf (f, "#nothing to test\n");
+-	fclose (f);
++	p = strstr (f, ".conf");
++	TEST_NE_P (p, NULL);
++	TEST_EQ_P (p, f+strlen (f) - strlen (".conf"));
++	nih_free (f);
++
++	/* test parent param */
++	job = job_class_new (NULL, "foo");
++	TEST_NE_P (job, NULL);
++
++	f = toggle_conf_name (job, filename);
++	TEST_NE_P (f, NULL);
++
++	TEST_EQ (TRUE, nih_alloc_parent (f, job));
++
++	nih_free (job);
++}
++
++void
++test_override (void)
++{
++	ConfSource *source;
++	ConfFile   *file;
++	FILE       *f;
++	int         ret, fd[4096], i = 0;
++	char        dirname[PATH_MAX];
++	char        filename[PATH_MAX], override[PATH_MAX];
++	JobClass   *job;
++	NihError   *err;
++
++	program_name = "test";
++	nih_log_set_priority (NIH_LOG_FATAL);
++
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_GROUP ("override files");
+ 
+ 	/* Make sure that we have inotify before performing some tests... */
+ 	if ((fd[0] = inotify_init ()) < 0) {
+@@ -2460,207 +2534,1426 @@ test_source_reload_file (void)
+ 	close (fd[0]);
+ 
+ 
+-	/* Check that we can load a file source for the first time.  An
+-	 * inotify watch should be established on the parent directory,
+-	 * the descriptor set to be closed-on-exec, but only that single
+-	 * file parsed.
++	/* Explicit test of behaviour prior to introduction of override files.
++	 * 
++	 * conf with no override before watch:
++	 *   create conf
++	 *   create watch
++	 *   ensure conf loaded
++	 *   update conf
++	 *   ensure conf updated
++	 *   delete conf
++	 *   ensure conf deleted
+ 	 */
+-	TEST_FEATURE ("with new conf file");
++	TEST_FEATURE ("with pre-override environment (conf with no override before watch)");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create conf */
+ 	strcpy (filename, dirname);
+ 	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
+ 
+-	source = conf_source_new (NULL, filename, CONF_FILE);
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
+ 	ret = conf_source_reload (source);
+-
+ 	TEST_EQ (ret, 0);
+-	TEST_ALLOC_SIZE (source->watch, sizeof (NihWatch));
+-	TEST_EQ_STR (source->watch->path, dirname);
+-	TEST_EQ_P (source->watch->data, source);
+-
+-	TEST_TRUE (fcntl (source->watch->fd, F_GETFD) & FD_CLOEXEC);
+-
+-	TEST_EQ (source->flag, TRUE);
+ 
+-	strcpy (filename, dirname);
+-	strcat (filename, "/foo.conf");
++	/* ensure conf loaded */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_NE_P (job->start_on, NULL);
+ 
+-	TEST_ALLOC_SIZE (file, sizeof (ConfFile));
+-	TEST_ALLOC_PARENT (file, source);
+-	TEST_EQ (file->flag, source->flag);
+-	TEST_EQ_P (file->data, NULL);
+-
+-	nih_free (file);
++	/* update conf */
++	f = fopen (filename, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fclose (f);
+ 
++	TEST_FORCE_WATCH_UPDATE();
+ 
+-	strcpy (filename, dirname);
+-	strcat (filename, "/bar.conf");
++	/* ensure conf updated */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (job->start_on, NULL);
+ 
+-	TEST_EQ_P (file, NULL);
++	/* delete conf */
++	unlink (filename);
++
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++	TEST_HASH_EMPTY (job_classes);
+ 	TEST_HASH_EMPTY (source->files);
+ 
+-	nih_free (source);
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure conf deleted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
+ 
+-	/* Check that if we create a new file in the directory, alongside
+-	 * the one we are watching, it is ignored.
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	/* Explicit test of behaviour prior to introduction of override files.
++	 * 
++	 * conf with no override after watch:
++	 *   create watch
++	 *   create conf
++	 *   ensure conf loaded
++	 *   update conf
++	 *   ensure conf updated
++	 *   delete conf
++	 *   ensure conf deleted
+ 	 */
+-	TEST_FEATURE ("with new file alongside conf file");
+-	strcpy (filename, dirname);
+-	strcat (filename, "/foo.conf");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FEATURE ("with pre-override environment (conf with no override after watch)");
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
+ 
+-	source = conf_source_new (NULL, filename, CONF_FILE);
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
+ 	ret = conf_source_reload (source);
+-
+ 	TEST_EQ (ret, 0);
+ 
++	/* create conf */
+ 	strcpy (filename, dirname);
+-	strcat (filename, "/baz.conf");
+-
++	strcat (filename, "/foo.conf");
+ 	f = fopen (filename, "w");
+-	fprintf (f, "#nothing to test\n");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
+ 	fclose (f);
+ 
+-	nfds = 0;
+-	FD_ZERO (&readfds);
+-	FD_ZERO (&writefds);
+-	FD_ZERO (&exceptfds);
+-
+-	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
+-	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure conf loaded */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
+ 
+-	TEST_EQ_P (file, NULL);
+-
++	/* update conf */
++	f = fopen (filename, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fclose (f);
+ 
+-	/* Check that if we modify a file in the directory, alongside
+-	 * the one we are watching, it is ignored.
+-	 */
+-	TEST_FEATURE ("with modification to file alongside conf file");
+-	strcpy (filename, dirname);
+-	strcat (filename, "/bar.conf");
++	TEST_FORCE_WATCH_UPDATE();
+ 
+-	f = fopen (filename, "w");
+-	fprintf (f, "#nothing to test\n");
+-	fclose (f);
++	/* ensure conf updated */
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (job->start_on, NULL);
+ 
+-	nfds = 0;
+-	FD_ZERO (&readfds);
+-	FD_ZERO (&writefds);
+-	FD_ZERO (&exceptfds);
++	/* delete conf */
++	unlink (filename);
+ 
+-	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
+-	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure conf deleted */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
+-
+ 	TEST_EQ_P (file, NULL);
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
+ 
+ 
+-	/* Check that the configuration file we're watching can be modified
+-	 * using the direct writing technique.
+-	 */
+-	TEST_FEATURE ("with modification (direct write)");
+-	strcpy (filename, dirname);
+-	strcat (filename, "/foo.conf");
+-
+-	old_file = (ConfFile *)nih_hash_lookup (source->files, filename);
+-	TEST_FREE_TAG (old_file);
++	TEST_FEATURE ("ensure lone override ignored before watch");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
+ 
++	/* create override */
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.override");
+ 	f = fopen (filename, "w");
+-	fprintf (f, "#still nothing to test\n");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
+ 	fclose (f);
+ 
+-	nfds = 0;
+-	FD_ZERO (&readfds);
+-	FD_ZERO (&writefds);
+-	FD_ZERO (&exceptfds);
+-
+-	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
+-	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
+ 
+-	TEST_FREE (old_file);
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure no conf object created */
++	TEST_HASH_EMPTY (source->files);
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
+ 
+-	TEST_ALLOC_SIZE (file, sizeof (ConfFile));
+-	TEST_ALLOC_PARENT (file, source);
+-	TEST_EQ (file->flag, source->flag);
+-	TEST_EQ_P (file->data, NULL);
++	/* update override */
++	f = fopen (filename, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "author \"me\"\n");
++	fclose (f);
+ 
+-	old_file = file;
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure no conf object created */
++	TEST_HASH_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
+ 
+-	/* Check that the configuration file we're watching can be modified
+-	 * using the write and then rename technique; it should be parsed
+-	 * and the previous file marked for deletion.
+-	 */
+-	TEST_FEATURE ("with modification (atomic rename)");
+-	strcpy (tmpname, dirname);
+-	strcat (tmpname, "/.foo.tmp");
++	/* delete override */
++	unlink (filename);
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
+ 
+-	f = fopen (tmpname, "w");
+-	fprintf (f, "#nothing to test\n");
+-	fclose (f);
+ 
+-	strcpy (filename, dirname);
+-	strcat (filename, "/foo.conf");
++	TEST_FEATURE ("ensure lone override ignored after watch");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
+ 
+-	rename (tmpname, filename);
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
+ 
+-	TEST_FREE_TAG (old_file);
++	strcpy (filename, dirname);
++	strcat (filename, "/bar.override");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fclose (f);
+ 
+-	nfds = 0;
+-	FD_ZERO (&readfds);
+-	FD_ZERO (&writefds);
+-	FD_ZERO (&exceptfds);
++	TEST_FORCE_WATCH_UPDATE();
+ 
+-	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
+-	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++	/* ensure no conf object created */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "bar");
++	TEST_EQ_P (job, NULL);
+ 
+-	TEST_FREE (old_file);
++	/* delete override */
++	unlink (filename);
++
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure override still not present */
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "bar");
++	TEST_EQ_P (job, NULL);
+ 
+-	TEST_ALLOC_SIZE (file, sizeof (ConfFile));
+-	TEST_ALLOC_PARENT (file, source);
+-	TEST_EQ (file->flag, source->flag);
+-	TEST_EQ_P (file->data, NULL);
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
+ 
+-	old_file = file;
+ 
++	TEST_FEATURE ("create conf, watch, then create/modify/delete override");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
+ 
+-	/* Check that we can delete the configuration file that we're
+-	 * watching, the metadata for it should be lost.
+-	 */
+-	TEST_FEATURE ("with deletion");
++	/* create conf */
+ 	strcpy (filename, dirname);
+ 	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
+ 
+-	unlink (filename);
+-
+-	TEST_FREE_TAG (old_file);
+-
+-	nfds = 0;
+-	FD_ZERO (&readfds);
+-	FD_ZERO (&writefds);
+-	FD_ZERO (&exceptfds);
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
+ 
+-	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
+-	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++	/* ensure conf loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_P ((job->emits)[1], NULL);
++	TEST_NE_P (job->start_on, NULL);
++
++	/* create override */
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fclose (f);
+ 
+-	TEST_FREE (old_file);
++	TEST_HASH_NOT_EMPTY (source->files);
++	TEST_FORCE_WATCH_UPDATE();
+ 
++	/* ensure conf updated */
++	TEST_HASH_NOT_EMPTY (source->files);
+ 	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (job->start_on, NULL);
+ 
++	/* ensure no override in hash */
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
+ 	TEST_EQ_P (file, NULL);
+ 
++	/* modify override */
++	f = fopen (override, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "emits world\n");
++	fclose (f);
+ 
+-	/* Check that the watch allows us to see if the file we want is
+-	 * created using the direct writing technique, and thus parsed.
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf updated */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_STR ((job->emits)[1], "world");
++
++	/* delete override */
++	unlink (override);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf reverted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_NE_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_P ((job->emits)[1], NULL);
++
++	nih_free (source);
++	unlink (filename);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create watch, conf, then create/modify/delete override");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	/* create conf */
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_P ((job->emits)[1], NULL);
++	TEST_NE_P (job->start_on, NULL);
++
++	/* create override */
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fclose (f);
++
++	TEST_HASH_NOT_EMPTY (source->files);
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf updated */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (job->start_on, NULL);
++
++	/* ensure no override in hash */
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
++	TEST_EQ_P (file, NULL);
++
++	/* modify override */
++	f = fopen (override, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "emits world\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf updated */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_STR ((job->emits)[1], "world");
++
++	/* delete override */
++	unlink (override);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf reverted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_NE_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_P ((job->emits)[1], NULL);
++
++	nih_free (source);
++	unlink (filename);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create override, watch, then create/modify/delete conf");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++
++	/* create override */
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"bar\"\n");
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure no conf object created */
++	TEST_HASH_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++
++	/* create conf */
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fprintf (f, "author \"foo\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "bar");
++
++	/* modify conf */
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on wibble\n");
++	fprintf (f, "emits moo\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf reloaded and updated with override */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "moo");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "bar");
++
++	/* delete conf */
++	unlink (filename);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf object deleted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	TEST_HASH_EMPTY (source->files);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
++	TEST_EQ_P (file, NULL);
++
++	unlink (override);
++
++	/* ensure no conf object still */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	TEST_HASH_EMPTY (source->files);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
++	TEST_EQ_P (file, NULL);
++
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create watch, override, then create/modify/delete conf");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++
++	/* create override */
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"bar\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure no conf object created */
++	TEST_HASH_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++
++	/* create conf */
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fprintf (f, "author \"foo\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "bar");
++
++	/* modify conf */
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on wibble\n");
++	fprintf (f, "emits moo\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf reloaded and updated with override */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "moo");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "bar");
++
++	/* delete conf */
++	unlink (filename);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf object deleted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	TEST_HASH_EMPTY (source->files);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
++	TEST_EQ_P (file, NULL);
++
++	unlink (override);
++
++	/* ensure no conf object still */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	TEST_HASH_EMPTY (source->files);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
++	TEST_EQ_P (file, NULL);
++
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create override, watch, conf, then modify/delete override");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++
++	/* create override */
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"bar\"\n");
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure no conf object created */
++	TEST_HASH_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++
++	/* create conf */
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fprintf (f, "author \"foo\"\n");
++	fclose (f);
++
++	/* FIXME: crashes here */
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "bar");
++
++	/* modify override */
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "author \"meh\"\n");
++	fprintf (f, "env wibble=wobble\n");
++	fprintf (f, "manual\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf reloaded and updated with override */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "meh");
++	TEST_EQ_STR ((job->env)[0], "wibble=wobble");
++
++	/* delete override */
++	unlink (override);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf object reverted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_NE_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "foo");
++	TEST_EQ_P (job->env, NULL);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	unlink (filename);
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create watch, override, conf, then modify/delete override");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* create override */
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"bar\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* create conf */
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "emits hello\n");
++	fprintf (f, "author \"foo\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "bar");
++
++	/* update override */
++	f = fopen (override, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "author \"me\"\n");
++	fprintf (f, "env wibble=wobble\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf reloaded and updated with override */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++
++	/* should pick up override, *NOT* conf */
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "me");
++	TEST_EQ_STR ((job->env)[0], "wibble=wobble");
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* delete override */
++	unlink (override);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR (job->author, "foo");
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_NE_P (job->start_on, NULL);
++	TEST_EQ_P (job->env, NULL);
++
++	unlink (filename);
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create both conf+override files, watch, then modify/delete conf");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create conf */
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "author \"me\"\n");
++	fprintf (f, "env foo=bar\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
++
++	/* create override */
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"you\"\n");
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_STR (job->author, "you");
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->env)[0], "foo=bar");
++	TEST_EQ_P (job->export, NULL);
++
++	/* modify conf */
++	f = fopen (filename, "a");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "export foo\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf updated */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_STR ((job->env)[0], "foo=bar");
++	TEST_NE_P (job->export, NULL);
++	TEST_EQ_STR ((job->export)[0], "foo");
++
++	/* delete conf */
++	unlink (filename);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf object deleted */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_EQ_P (file, NULL);
++	TEST_HASH_EMPTY (source->files);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_EQ_P (job, NULL);
++	file = (ConfFile *)nih_hash_lookup (source->files, override);
++	TEST_EQ_P (file, NULL);
++
++	unlink (override);
++	nih_free (source);
++	TEST_EQ (rmdir (dirname), 0);
++
++	TEST_FEATURE ("create both conf+override files, watch, then modify/delete override");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create conf */
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "author \"me\"\n");
++	fprintf (f, "env foo=bar\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
++
++	/* create override */
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"you\"\n");
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_STR (job->author, "you");
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->env)[0], "foo=bar");
++	TEST_EQ_P (job->export, NULL);
++
++	/* modify override */
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "description \"hello world\"\n");
++	fprintf (f, "author \"ubuntu\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf updated */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR (job->author, "ubuntu");
++	TEST_NE_P (job->description, NULL);
++	TEST_EQ_STR (job->description, "hello world");
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_NE_P (job->start_on, NULL);
++
++	/* delete override */
++	unlink (override);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf updated */
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_NE_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->env)[0], "foo=bar");
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_STR (job->author, "me");
++	TEST_EQ_P (job->description, NULL);
++
++	nih_free (source);
++	unlink (filename);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	TEST_FEATURE ("create conf, watch, then create invalid override, delete override");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create conf */
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "author \"wibble\"\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_NE_P (job->start_on, NULL);
++
++	/* create (partially) invalid override (which should be
++	 * fully ignored)
++	 */
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "bleaugh!\n");
++	fprintf (f, "wha...?\n");
++	fprintf (f, "author \"moo\"\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	unlink (override);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf still loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_NE_P (job->start_on, NULL);
++	TEST_EQ_STR (job->author, "wibble");
++
++	nih_free (source);
++	unlink (filename);
++	TEST_EQ (rmdir (dirname), 0);
++
++	TEST_FEATURE ("ensure override ignored for CONF_FILE");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create empty conf */
++	strcpy (filename, dirname);
++	strcat (filename, "/init.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_FILE);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++
++	/* We expect conf_source_reload to fail in this situation since
++	 * although "init.conf" is a supported config file, it is not
++	 * allowed to contain any stanzas, implying that it can only
++	 * contain comments. In fact, if the file exists but is zero
++	 * size that is currently an error since upstart blindly calls
++	 * nih_file_read(), which will fail since there are no bytes to
++	 * read.
++	 */
++	TEST_NE (ret, 0);
++	err = nih_error_steal ();
++	TEST_EQ (err->number, EILSEQ);
++	nih_free (err);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf NOT loaded */
++	TEST_HASH_EMPTY (source->files);
++
++	/* create override */
++	strcpy (override, dirname);
++	strcat (override, "/init.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fclose (f);
++
++	TEST_FORCE_WATCH_UPDATE();
++
++	/* ensure conf still NOT loaded */
++	TEST_HASH_EMPTY (source->files);
++
++	nih_free (source);
++	unlink (filename);
++	unlink (override);
++	TEST_EQ (rmdir (dirname), 0);
++
++	/* Consume all available inotify instances so that the following
++	 * tests run without inotify.
++	 */
++	for (i = 0; i < 4096; i++)
++		if ((fd[i] = inotify_init ()) < 0)
++			break;
++
++no_inotify:
++	/* If you don't have inotify, any override file must exist
++	 * before the system boots.
++	 */ 
++
++	TEST_FEATURE ("both conf+override files with no inotify support");
++	TEST_ENSURE_CLEAN_ENV ();
++	TEST_FILENAME (dirname);
++	TEST_EQ (mkdir (dirname, 0755), 0);
++
++	/* create conf */
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	f = fopen (filename, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "start on started\n");
++	fprintf (f, "author \"me\"\n");
++	fprintf (f, "env foo=bar\n");
++	fprintf (f, "emits hello\n");
++	fclose (f);
++
++	/* create override */
++	strcpy (override, dirname);
++	strcat (override, "/foo.override");
++	f = fopen (override, "w");
++	TEST_NE_P (f, NULL);
++	fprintf (f, "manual\n");
++	fprintf (f, "author \"you\"\n");
++	fclose (f);
++
++	/* create watch */
++	source = conf_source_new (NULL, dirname, CONF_JOB_DIR);
++	TEST_NE_P (source, NULL);
++	ret = conf_source_reload (source);
++	TEST_EQ (ret, 0);
++
++	/* ensure conf loaded */
++	TEST_HASH_NOT_EMPTY (source->files);
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_NE_P (file, NULL);
++	job = (JobClass *)nih_hash_lookup (job_classes, "foo");
++	TEST_NE_P (job, NULL);
++	TEST_EQ_P (file->job, job);
++	TEST_EQ_STR ((job->emits)[0], "hello");
++	TEST_EQ_STR (job->author, "you");
++	TEST_EQ_P (job->start_on, NULL);
++	TEST_EQ_STR ((job->env)[0], "foo=bar");
++	TEST_EQ_P (job->export, NULL);
++
++	nih_free (source);
++	unlink (filename);
++	unlink (override);
++	TEST_EQ (rmdir (dirname), 0);
++
++
++	nih_log_set_priority (NIH_LOG_MESSAGE);
++
++	/* Release consumed instances */
++	for (i = 0; i < 4096; i++) {
++		if (fd[i] < 0)
++			break;
++
++		close (fd[i]);
++	}
++}
++
++void
++test_source_reload_file (void)
++{
++	ConfSource *source;
++	ConfFile   *file, *old_file;
++	FILE       *f;
++	int         ret, fd[4096], i = 0, nfds;
++	char        dirname[PATH_MAX];
++	char        tmpname[PATH_MAX], filename[PATH_MAX];
++	fd_set      readfds, writefds, exceptfds;
++	NihError   *err;
++
++	TEST_FUNCTION_FEATURE ("conf_source_reload",
++			       "with configuration file");
++	program_name = "test";
++	nih_log_set_priority (NIH_LOG_FATAL);
++
++	TEST_FILENAME (dirname);
++	mkdir (dirname, 0755);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++
++	f = fopen (filename, "w");
++	fprintf (f, "#nothing to test\n");
++	fclose (f);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/bar.conf");
++
++	f = fopen (filename, "w");
++	fprintf (f, "#nothing to test\n");
++	fclose (f);
++
++	/* Make sure that we have inotify before performing some tests... */
++	if ((fd[0] = inotify_init ()) < 0) {
++		printf ("SKIP: inotify not available\n");
++		goto no_inotify;
++	}
++	close (fd[0]);
++
++
++	/* Check that we can load a file source for the first time.  An
++	 * inotify watch should be established on the parent directory,
++	 * the descriptor set to be closed-on-exec, but only that single
++	 * file parsed.
++	 */
++	TEST_FEATURE ("with new conf file");
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++
++	source = conf_source_new (NULL, filename, CONF_FILE);
++	ret = conf_source_reload (source);
++
++	TEST_EQ (ret, 0);
++	TEST_ALLOC_SIZE (source->watch, sizeof (NihWatch));
++	TEST_EQ_STR (source->watch->path, dirname);
++	TEST_EQ_P (source->watch->data, source);
++
++	TEST_TRUE (fcntl (source->watch->fd, F_GETFD) & FD_CLOEXEC);
++
++	TEST_EQ (source->flag, TRUE);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_ALLOC_SIZE (file, sizeof (ConfFile));
++	TEST_ALLOC_PARENT (file, source);
++	TEST_EQ (file->flag, source->flag);
++	TEST_EQ_P (file->data, NULL);
++
++	nih_free (file);
++
++
++	strcpy (filename, dirname);
++	strcat (filename, "/bar.conf");
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_EQ_P (file, NULL);
++
++	TEST_HASH_EMPTY (source->files);
++
++	nih_free (source);
++
++
++	/* Check that if we create a new file in the directory, alongside
++	 * the one we are watching, it is ignored.
++	 */
++	TEST_FEATURE ("with new file alongside conf file");
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++
++	source = conf_source_new (NULL, filename, CONF_FILE);
++	ret = conf_source_reload (source);
++
++	TEST_EQ (ret, 0);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/baz.conf");
++
++	f = fopen (filename, "w");
++	fprintf (f, "#nothing to test\n");
++	fclose (f);
++
++	nfds = 0;
++	FD_ZERO (&readfds);
++	FD_ZERO (&writefds);
++	FD_ZERO (&exceptfds);
++
++	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
++	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_EQ_P (file, NULL);
++
++
++	/* Check that if we modify a file in the directory, alongside
++	 * the one we are watching, it is ignored.
++	 */
++	TEST_FEATURE ("with modification to file alongside conf file");
++	strcpy (filename, dirname);
++	strcat (filename, "/bar.conf");
++
++	f = fopen (filename, "w");
++	fprintf (f, "#nothing to test\n");
++	fclose (f);
++
++	nfds = 0;
++	FD_ZERO (&readfds);
++	FD_ZERO (&writefds);
++	FD_ZERO (&exceptfds);
++
++	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
++	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_EQ_P (file, NULL);
++
++
++	/* Check that the configuration file we're watching can be modified
++	 * using the direct writing technique.
++	 */
++	TEST_FEATURE ("with modification (direct write)");
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++
++	old_file = (ConfFile *)nih_hash_lookup (source->files, filename);
++	TEST_FREE_TAG (old_file);
++
++	f = fopen (filename, "w");
++	fprintf (f, "#still nothing to test\n");
++	fclose (f);
++
++	nfds = 0;
++	FD_ZERO (&readfds);
++	FD_ZERO (&writefds);
++	FD_ZERO (&exceptfds);
++
++	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
++	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++
++	TEST_FREE (old_file);
++
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_ALLOC_SIZE (file, sizeof (ConfFile));
++	TEST_ALLOC_PARENT (file, source);
++	TEST_EQ (file->flag, source->flag);
++	TEST_EQ_P (file->data, NULL);
++
++	old_file = file;
++
++
++	/* Check that the configuration file we're watching can be modified
++	 * using the write and then rename technique; it should be parsed
++	 * and the previous file marked for deletion.
++	 */
++	TEST_FEATURE ("with modification (atomic rename)");
++	strcpy (tmpname, dirname);
++	strcat (tmpname, "/.foo.tmp");
++
++	f = fopen (tmpname, "w");
++	fprintf (f, "#nothing to test\n");
++	fclose (f);
++
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++
++	rename (tmpname, filename);
++
++	TEST_FREE_TAG (old_file);
++
++	nfds = 0;
++	FD_ZERO (&readfds);
++	FD_ZERO (&writefds);
++	FD_ZERO (&exceptfds);
++
++	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
++	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++
++	TEST_FREE (old_file);
++
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_ALLOC_SIZE (file, sizeof (ConfFile));
++	TEST_ALLOC_PARENT (file, source);
++	TEST_EQ (file->flag, source->flag);
++	TEST_EQ_P (file->data, NULL);
++
++	old_file = file;
++
++
++	/* Check that we can delete the configuration file that we're
++	 * watching, the metadata for it should be lost.
++	 */
++	TEST_FEATURE ("with deletion");
++	strcpy (filename, dirname);
++	strcat (filename, "/foo.conf");
++
++	unlink (filename);
++
++	TEST_FREE_TAG (old_file);
++
++	nfds = 0;
++	FD_ZERO (&readfds);
++	FD_ZERO (&writefds);
++	FD_ZERO (&exceptfds);
++
++	nih_io_select_fds (&nfds, &readfds, &writefds, &exceptfds);
++	nih_io_handle_fds (&readfds, &writefds, &exceptfds);
++
++	TEST_FREE (old_file);
++
++	file = (ConfFile *)nih_hash_lookup (source->files, filename);
++
++	TEST_EQ_P (file, NULL);
++
++
++	/* Check that the watch allows us to see if the file we want is
++	 * created using the direct writing technique, and thus parsed.
+ 	 */
+ 	TEST_FEATURE ("with creation (direct write)");
+ 	strcpy (filename, dirname);
+@@ -2969,8 +4262,6 @@ test_source_reload_file (void)
+ 	TEST_HASH_EMPTY (source->files);
+ 
+ 	nih_free (source);
+-
+-
+ 	/* Consume all available inotify instances so that the following
+ 	 * tests run without inotify.
+ 	 */
+@@ -3456,6 +4747,8 @@ main (int   argc,
+ 	test_source_reload_conf_dir ();
+ 	test_source_reload_file ();
+ 	test_source_reload ();
++	test_toggle_conf_name ();
++	test_override ();
+ 	test_file_destroy ();
+ 	test_select_job ();
+ 
+diff --git a/init/tests/test_parse_job.c b/init/tests/test_parse_job.c
+index 73218f4..07a99c1 100644
+--- a/init/tests/test_parse_job.c
++++ b/init/tests/test_parse_job.c
+@@ -64,7 +64,7 @@ test_parse_job (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -110,7 +110,7 @@ test_parse_job (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -131,6 +131,45 @@ test_parse_job (void)
+ 
+ 		nih_free (job);
+ 	}
++
++	TEST_FEATURE ("with non-NULL update parameter (override)");
++	{
++		JobClass *tmp = NULL;
++
++		strcpy (buf, "start on starting\n");
++		strcat (buf, "author \"me\"\n");
++
++		pos = 0;
++		lineno = 1;
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
++				&pos, &lineno);
++
++		TEST_NE_P (job, NULL);
++		TEST_EQ_STR (job->author, "me");
++		TEST_NE_P (job->start_on, NULL);
++
++		strcat (buf, "author \"you\"\n");
++		strcat (buf, "manual\n");
++		strcat (buf, "description \"my description\"\n");
++
++		pos = 0;
++		lineno = 1;
++  		tmp = parse_job (NULL, job, "test", buf, strlen (buf),
++				&pos, &lineno);
++		TEST_NE_P (tmp, NULL);
++
++		/* if passed a job, the same object should be returned.
++		 */
++		TEST_EQ_P (tmp, job);
++
++		TEST_EQ_STR (tmp->author, "you");
++		TEST_EQ_P (tmp->start_on, NULL);
++		TEST_NE_P (tmp->description, NULL);
++
++		TEST_EQ_STR (tmp->description, "my description");
++
++		nih_free (job);
++	}
+ }
+ 
+ void
+@@ -153,7 +192,7 @@ test_stanza_exec (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -190,7 +229,7 @@ test_stanza_exec (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -229,7 +268,7 @@ test_stanza_exec (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -266,7 +305,7 @@ test_stanza_exec (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -299,7 +338,7 @@ test_stanza_script (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -340,7 +379,7 @@ test_stanza_script (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -379,7 +418,7 @@ test_stanza_script (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -416,7 +455,7 @@ test_stanza_script (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -447,7 +486,7 @@ test_stanza_pre_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -484,7 +523,7 @@ test_stanza_pre_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -524,7 +563,7 @@ test_stanza_pre_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -565,7 +604,7 @@ test_stanza_pre_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -604,7 +643,7 @@ test_stanza_pre_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -643,7 +682,7 @@ test_stanza_pre_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -680,7 +719,7 @@ test_stanza_pre_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -699,7 +738,7 @@ test_stanza_pre_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -718,7 +757,7 @@ test_stanza_pre_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -737,7 +776,7 @@ test_stanza_pre_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -768,7 +807,7 @@ test_stanza_post_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -805,7 +844,7 @@ test_stanza_post_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -845,7 +884,7 @@ test_stanza_post_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -886,7 +925,7 @@ test_stanza_post_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -925,7 +964,7 @@ test_stanza_post_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -964,7 +1003,7 @@ test_stanza_post_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1001,7 +1040,7 @@ test_stanza_post_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1020,7 +1059,7 @@ test_stanza_post_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1039,7 +1078,7 @@ test_stanza_post_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1058,7 +1097,7 @@ test_stanza_post_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1089,7 +1128,7 @@ test_stanza_pre_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1126,7 +1165,7 @@ test_stanza_pre_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1166,7 +1205,7 @@ test_stanza_pre_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1207,7 +1246,7 @@ test_stanza_pre_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1246,7 +1285,7 @@ test_stanza_pre_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1285,7 +1324,7 @@ test_stanza_pre_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1322,7 +1361,7 @@ test_stanza_pre_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1341,7 +1380,7 @@ test_stanza_pre_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1360,7 +1399,7 @@ test_stanza_pre_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1379,7 +1418,7 @@ test_stanza_pre_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1410,7 +1449,7 @@ test_stanza_post_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1447,7 +1486,7 @@ test_stanza_post_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1487,7 +1526,7 @@ test_stanza_post_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1528,7 +1567,7 @@ test_stanza_post_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1567,7 +1606,7 @@ test_stanza_post_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1606,7 +1645,7 @@ test_stanza_post_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1643,7 +1682,7 @@ test_stanza_post_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1662,7 +1701,7 @@ test_stanza_post_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1681,7 +1720,7 @@ test_stanza_post_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1700,7 +1739,7 @@ test_stanza_post_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -1731,7 +1770,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1776,7 +1815,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1828,7 +1867,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1879,7 +1918,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -1942,7 +1981,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2012,7 +2051,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2090,7 +2129,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2170,7 +2209,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2249,7 +2288,7 @@ test_stanza_start (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2291,7 +2330,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2310,7 +2349,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2329,7 +2368,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2348,7 +2387,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2367,7 +2406,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2384,7 +2423,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2403,7 +2442,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2422,7 +2461,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2441,7 +2480,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2460,7 +2499,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2479,7 +2518,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2498,7 +2537,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2517,7 +2556,7 @@ test_stanza_start (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -2551,7 +2590,7 @@ test_stanza_manual (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2586,7 +2625,7 @@ test_stanza_manual (void)
+ 	TEST_FEATURE ("manual stanza after start on");
+ 	strcpy (buf, "start on wibble\nmanual\n");
+ 
+-	job = parse_job (NULL, "test", buf, strlen (buf),
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 			&pos, &lineno);
+ 
+ 	TEST_NE_P (job, NULL);
+@@ -2616,7 +2655,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2661,7 +2700,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2713,7 +2752,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2764,7 +2803,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2827,7 +2866,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2897,7 +2936,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -2975,7 +3014,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3055,7 +3094,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3134,7 +3173,7 @@ test_stanza_stop (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3176,7 +3215,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3195,7 +3234,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3214,7 +3253,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3233,7 +3272,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3252,7 +3291,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3269,7 +3308,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3288,7 +3327,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3307,7 +3346,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3326,7 +3365,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3345,7 +3384,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3364,7 +3403,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3383,7 +3422,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3402,7 +3441,7 @@ test_stanza_stop (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3432,7 +3471,7 @@ test_stanza_description (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3465,7 +3504,7 @@ test_stanza_description (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3498,7 +3537,7 @@ test_stanza_description (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3517,7 +3556,7 @@ test_stanza_description (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3547,7 +3586,7 @@ test_stanza_author (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3580,7 +3619,7 @@ test_stanza_author (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3613,7 +3652,7 @@ test_stanza_author (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3632,7 +3671,7 @@ test_stanza_author (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3662,7 +3701,7 @@ test_stanza_version (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3695,7 +3734,7 @@ test_stanza_version (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3728,7 +3767,7 @@ test_stanza_version (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3747,7 +3786,7 @@ test_stanza_version (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3777,7 +3816,7 @@ test_stanza_emits (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3814,7 +3853,7 @@ test_stanza_emits (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3857,7 +3896,7 @@ test_stanza_emits (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3899,7 +3938,7 @@ test_stanza_emits (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -3929,7 +3968,7 @@ test_stanza_expect (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3962,7 +4001,7 @@ test_stanza_expect (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -3995,7 +4034,7 @@ test_stanza_expect (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4028,7 +4067,7 @@ test_stanza_expect (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4061,7 +4100,7 @@ test_stanza_expect (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4093,7 +4132,7 @@ test_stanza_expect (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4112,7 +4151,7 @@ test_stanza_expect (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4131,7 +4170,7 @@ test_stanza_expect (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4159,7 +4198,7 @@ test_stanza_respawn (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4193,7 +4232,7 @@ test_stanza_respawn (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4226,7 +4265,7 @@ test_stanza_respawn (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4260,7 +4299,7 @@ test_stanza_respawn (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4293,7 +4332,7 @@ test_stanza_respawn (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4326,7 +4365,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4345,7 +4384,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4364,7 +4403,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4383,7 +4422,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4402,7 +4441,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4421,7 +4460,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4440,7 +4479,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4459,7 +4498,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4478,7 +4517,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4497,7 +4536,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4516,7 +4555,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4535,7 +4574,7 @@ test_stanza_respawn (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4565,7 +4604,7 @@ test_stanza_task (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4597,7 +4636,7 @@ test_stanza_task (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4629,7 +4668,7 @@ test_stanza_task (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4659,7 +4698,7 @@ test_stanza_instance (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4693,7 +4732,7 @@ test_stanza_instance (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4726,7 +4765,7 @@ test_stanza_instance (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4745,7 +4784,7 @@ test_stanza_instance (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4775,7 +4814,7 @@ test_stanza_kill (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4808,7 +4847,7 @@ test_stanza_kill (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -4840,7 +4879,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4859,7 +4898,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4878,7 +4917,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4897,7 +4936,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4916,7 +4955,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4935,7 +4974,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4954,7 +4993,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -4974,7 +5013,7 @@ test_stanza_kill (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5005,7 +5044,7 @@ test_stanza_normal (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5044,7 +5083,7 @@ test_stanza_normal (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5083,7 +5122,7 @@ test_stanza_normal (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5127,7 +5166,7 @@ test_stanza_normal (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5168,7 +5207,7 @@ test_stanza_normal (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5187,7 +5226,7 @@ test_stanza_normal (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5206,7 +5245,7 @@ test_stanza_normal (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5225,7 +5264,7 @@ test_stanza_normal (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5244,7 +5283,7 @@ test_stanza_normal (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5263,7 +5302,7 @@ test_stanza_normal (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5293,7 +5332,7 @@ test_stanza_console (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5326,7 +5365,7 @@ test_stanza_console (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5359,7 +5398,7 @@ test_stanza_console (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5392,7 +5431,7 @@ test_stanza_console (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5423,7 +5462,7 @@ test_stanza_console (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5442,7 +5481,7 @@ test_stanza_console (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5460,7 +5499,7 @@ test_stanza_console (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5490,7 +5529,7 @@ test_stanza_env (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5528,7 +5567,7 @@ test_stanza_env (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5565,7 +5604,7 @@ test_stanza_env (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5584,7 +5623,7 @@ test_stanza_env (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5614,7 +5653,7 @@ test_stanza_export (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5651,7 +5690,7 @@ test_stanza_export (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5694,7 +5733,7 @@ test_stanza_export (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5736,7 +5775,7 @@ test_stanza_export (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5766,7 +5805,7 @@ test_stanza_umask (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5799,7 +5838,7 @@ test_stanza_umask (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5831,7 +5870,7 @@ test_stanza_umask (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5850,7 +5889,7 @@ test_stanza_umask (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5869,7 +5908,7 @@ test_stanza_umask (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5888,7 +5927,7 @@ test_stanza_umask (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5907,7 +5946,7 @@ test_stanza_umask (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5927,7 +5966,7 @@ test_stanza_umask (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -5957,7 +5996,7 @@ test_stanza_nice (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -5990,7 +6029,7 @@ test_stanza_nice (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6023,7 +6062,7 @@ test_stanza_nice (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6055,7 +6094,7 @@ test_stanza_nice (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6074,7 +6113,7 @@ test_stanza_nice (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6093,7 +6132,7 @@ test_stanza_nice (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6112,7 +6151,7 @@ test_stanza_nice (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6131,7 +6170,7 @@ test_stanza_nice (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6150,7 +6189,7 @@ test_stanza_nice (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6180,7 +6219,7 @@ test_stanza_oom (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6213,7 +6252,7 @@ test_stanza_oom (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6246,7 +6285,7 @@ test_stanza_oom (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6279,7 +6318,7 @@ test_stanza_oom (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6311,7 +6350,7 @@ test_stanza_oom (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6330,7 +6369,7 @@ test_stanza_oom (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6349,7 +6388,7 @@ test_stanza_oom (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6368,7 +6407,7 @@ test_stanza_oom (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6387,7 +6426,7 @@ test_stanza_oom (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6406,7 +6445,7 @@ test_stanza_oom (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -6435,7 +6474,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6469,7 +6508,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6503,7 +6542,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6537,7 +6576,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6571,7 +6610,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6606,7 +6645,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6641,7 +6680,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6675,7 +6714,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6710,7 +6749,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6744,7 +6783,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6778,7 +6817,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6812,7 +6851,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6847,7 +6886,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6881,7 +6920,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6917,7 +6956,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6956,7 +6995,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -6991,7 +7030,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -7026,7 +7065,7 @@ test_stanza_limit (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -7060,7 +7099,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7079,7 +7118,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7098,7 +7137,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7117,7 +7156,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7136,7 +7175,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7155,7 +7194,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7174,7 +7213,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7193,7 +7232,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7212,7 +7251,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7231,7 +7270,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7250,7 +7289,7 @@ test_stanza_limit (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7280,7 +7319,7 @@ test_stanza_chroot (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -7314,7 +7353,7 @@ test_stanza_chroot (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -7347,7 +7386,7 @@ test_stanza_chroot (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7366,7 +7405,7 @@ test_stanza_chroot (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7396,7 +7435,7 @@ test_stanza_chdir (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -7430,7 +7469,7 @@ test_stanza_chdir (void)
+ 	TEST_ALLOC_FAIL {
+ 		pos = 0;
+ 		lineno = 1;
+-		job = parse_job (NULL, "test", buf, strlen (buf),
++		job = parse_job (NULL, NULL, "test", buf, strlen (buf),
+ 				 &pos, &lineno);
+ 
+ 		if (test_alloc_failed) {
+@@ -7463,7 +7502,7 @@ test_stanza_chdir (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
+@@ -7482,7 +7521,7 @@ test_stanza_chdir (void)
+ 
+ 	pos = 0;
+ 	lineno = 1;
+-	job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
++	job = parse_job (NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+ 
+ 	TEST_EQ_P (job, NULL);
+ 
diff --git a/upstart-utmp.patch b/upstart-utmp.patch
index 255bc50..ccda548 100644
--- a/upstart-utmp.patch
+++ b/upstart-utmp.patch
@@ -1,18 +1,18 @@
 diff --git a/init/job_class.c b/init/job_class.c
-index b521cf4..1b8d1cf 100644
+index eeec83d..00eb13d 100644
 --- a/init/job_class.c
 +++ b/init/job_class.c
-@@ -218,6 +218,8 @@ job_class_new (const void *parent,
+@@ -219,6 +219,8 @@ job_class_new (const void *parent,
  	class->chroot = NULL;
  	class->chdir = NULL;
  
 +	class->utmp_id = NULL;
 +
  	class->deleted = FALSE;
+ 	class->debug   = FALSE;
  
- 	return class;
 diff --git a/init/job_class.h b/init/job_class.h
-index b7d4eed..1d29c59 100644
+index d40e750..e5b5190 100644
 --- a/init/job_class.h
 +++ b/init/job_class.h
 @@ -145,6 +145,7 @@ typedef struct job_class {
@@ -22,21 +22,12 @@ index b7d4eed..1d29c59 100644
 +	char           *utmp_id;
  
  	int             deleted;
- } JobClass;
+ 	int             debug;
 diff --git a/init/job_process.c b/init/job_process.c
-index e3080d8..8ce2f72 100644
+index 70fa2bf..544f5e3 100644
 --- a/init/job_process.c
 +++ b/init/job_process.c
-@@ -38,6 +38,8 @@
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-+#include <utmp.h>
-+#include <utmpx.h>
- 
- #include <nih/macros.h>
- #include <nih/alloc.h>
-@@ -361,11 +363,13 @@ job_process_spawn (JobClass     *class,
+@@ -361,11 +361,13 @@ job_process_spawn (JobClass     *class,
  		   char * const *env,
  		   int           trace)
  {
@@ -55,7 +46,7 @@ index e3080d8..8ce2f72 100644
  
  	nih_assert (class != NULL);
  
-@@ -524,6 +528,20 @@ job_process_spawn (JobClass     *class,
+@@ -558,6 +560,20 @@ job_process_spawn (JobClass     *class,
  		}
  	}
  
@@ -76,242 +67,14 @@ index e3080d8..8ce2f72 100644
  	/* Execute the process, if we escape from here it failed */
  	if (execvp (argv[0], argv) < 0) {
  		nih_error_raise_system ();
-@@ -967,6 +985,8 @@ job_process_terminated (Job         *job,
- 			int          status)
- {
- 	int failed = FALSE, stop = FALSE, state = TRUE;
-+	struct utmpx *utmptr;
-+	struct timeval tv;
- 
- 	nih_assert (job != NULL);
- 
-@@ -1129,6 +1149,36 @@ job_process_terminated (Job         *job,
- 		job->kill_process = -1;
- 	}
- 
-+	/* Find existing utmp entry for the process pid */
-+	setutxent();
-+	while ((utmptr = getutxent()) != NULL) {
-+		if (utmptr->ut_pid == job->pid[process]) {
-+			/* set type and clean ut_user, ut_host,
-+			 * ut_time as described in utmp(5)
-+			 */
-+			utmptr->ut_type = DEAD_PROCESS;
-+			memset(utmptr->ut_user, 0, UT_NAMESIZE);
-+			memset(utmptr->ut_host, 0, UT_HOSTSIZE);
-+			utmptr->ut_time = 0;
+@@ -1176,6 +1192,10 @@ job_process_terminated (Job         *job,
+ 			memset(utmptr->ut_user, 0, UT_NAMESIZE);
+ 			memset(utmptr->ut_host, 0, UT_HOSTSIZE);
+ 			utmptr->ut_time = 0;
 +
 +			/* Set class utmp_id for next spawn */
 +			job->class->utmp_id = nih_strdup (job->class, utmptr->ut_id);
 +
-+			/* Update existing utmp file. */
-+			pututxline(utmptr);
-+
-+			/* set ut_time for log */
-+			gettimeofday(&tv, NULL);
-+			utmptr->ut_tv.tv_sec = tv.tv_sec;
-+			utmptr->ut_tv.tv_usec = tv.tv_usec;
-+			/* Write wtmp entry */
-+			updwtmpx (_PATH_WTMP, utmptr);
-+
-+			break;
-+		}
-+	}
-+	endutxent();
-+
- 	/* Clear the process pid field */
- 	job->pid[process] = 0;
- 
-diff --git a/init/tests/test_job_process.c b/init/tests/test_job_process.c
-index d43fa6e..b4f94e4 100644
---- a/init/tests/test_job_process.c
-+++ b/init/tests/test_job_process.c
-@@ -36,6 +36,8 @@
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-+#include <utmp.h>
-+#include <utmpx.h>
- 
- #include <nih/macros.h>
- #include <nih/string.h>
-@@ -4474,6 +4476,171 @@ test_find (void)
- }
- 
- 
-+void
-+test_utmp (void)
-+{
-+	JobClass *      class;
-+	Job *           job = NULL;
-+	Blocked *       blocked = NULL;
-+	Event *         event;
-+	FILE *          output;
-+	char            utmpname[PATH_MAX];
-+	struct utmpx    utmp, *utmptr;
-+	struct timeval  tv;
-+
-+	TEST_FUNCTION ("job_process_handler");
-+	program_name = "test";
-+
-+	class = job_class_new (NULL, "test");
-+	class->process[PROCESS_MAIN] = process_new (class);
-+	class->process[PROCESS_MAIN]->command = "echo";
-+
-+	class->start_on = event_operator_new (class, EVENT_MATCH,
-+					       "foo", NULL);
-+	class->stop_on = event_operator_new (class, EVENT_MATCH,
-+					      "foo", NULL);
-+	nih_hash_add (job_classes, &class->entry);
-+
-+	event = event_new (NULL, "foo", NULL);
-+
-+	TEST_FILENAME(utmpname);
-+
-+	/* Check that utmp record for the running task of the job terminating
-+	 * is properly changed to DEAD_PROCESS
-+	 */
-+	TEST_FEATURE ("with LOGIN_PROCESS utmp entry");
-+	TEST_ALLOC_FAIL {
-+		TEST_ALLOC_SAFE {
-+			job = job_new (class, "");
-+
-+			blocked = blocked_new (job, BLOCKED_EVENT, event);
-+			event_block (event);
-+			nih_list_add (&job->blocking, &blocked->entry);
-+		}
-+
-+		job->goal = JOB_START;
-+		job->state = JOB_RUNNING;
-+		job->pid[PROCESS_MAIN] = 1;
-+
-+		TEST_FREE_TAG (blocked);
-+
-+		job->blocker = NULL;
-+		event->failed = FALSE;
-+
-+		job->failed = FALSE;
-+		job->failed_process = -1;
-+		job->exit_status = 0;
-+
-+		output = fopen (utmpname, "w");
-+		fclose (output);
-+
-+		/* set utmp file */
-+		utmpxname(utmpname);
-+
-+		/* set up utmp entries */
-+		memset (&utmp, 0, sizeof utmp);
-+
-+		strcpy(utmp.ut_id, "2");
-+		utmp.ut_type = LOGIN_PROCESS;
-+		utmp.ut_pid = 2;
-+
-+		gettimeofday(&tv, NULL);
-+		utmp.ut_tv.tv_sec = tv.tv_sec;
-+		utmp.ut_tv.tv_usec = tv.tv_usec;
-+
-+		setutxent();
-+		pututxline(&utmp);
-+
-+		strcpy(utmp.ut_id, "1");
-+		utmp.ut_pid = 1;
-+		pututxline(&utmp);
-+
-+		endutxent();
-+
-+		job_process_handler (NULL, 1, NIH_CHILD_EXITED, 0);
-+
-+		setutxent();
-+
-+		utmptr = getutxent();
-+		TEST_NE_P(utmptr, NULL);
-+		TEST_EQ(utmptr->ut_pid, 2);
-+		TEST_EQ(utmptr->ut_type, LOGIN_PROCESS);
-+
-+		utmptr = getutxent();
-+		TEST_NE_P(utmptr, NULL);
-+		TEST_EQ(utmptr->ut_pid, 1);
-+		TEST_EQ(utmptr->ut_type, DEAD_PROCESS);
-+
-+		nih_free (job);
-+	}
-+	TEST_FEATURE ("with USER_PROCESS utmp entry");
-+	TEST_ALLOC_FAIL {
-+		TEST_ALLOC_SAFE {
-+			job = job_new (class, "");
-+
-+			blocked = blocked_new (job, BLOCKED_EVENT, event);
-+			event_block (event);
-+			nih_list_add (&job->blocking, &blocked->entry);
-+		}
-+
-+		job->goal = JOB_START;
-+		job->state = JOB_RUNNING;
-+		job->pid[PROCESS_MAIN] = 1;
-+
-+		TEST_FREE_TAG (blocked);
-+
-+		job->blocker = NULL;
-+		event->failed = FALSE;
-+
-+		job->failed = FALSE;
-+		job->failed_process = -1;
-+		job->exit_status = 0;
-+
-+		output = fopen (utmpname, "w");
-+		fclose (output);
-+
-+		/* set utmp file */
-+		utmpxname(utmpname);
-+
-+		/* set up utmp entries */
-+		memset (&utmp, 0, sizeof utmp);
-+
-+		strcpy(utmp.ut_id, "2");
-+		utmp.ut_type = USER_PROCESS;
-+		utmp.ut_pid = 2;
-+
-+		gettimeofday(&tv, NULL);
-+		utmp.ut_tv.tv_sec = tv.tv_sec;
-+		utmp.ut_tv.tv_usec = tv.tv_usec;
-+
-+		setutxent();
-+		pututxline(&utmp);
-+
-+		strcpy(utmp.ut_id, "1");
-+		utmp.ut_pid = 1;
-+		pututxline(&utmp);
-+
-+		endutxent();
-+
-+		job_process_handler (NULL, 1, NIH_CHILD_EXITED, 0);
-+
-+		setutxent();
-+
-+		utmptr = getutxent();
-+		TEST_NE_P(utmptr, NULL);
-+		TEST_EQ(utmptr->ut_pid, 2);
-+		TEST_EQ(utmptr->ut_type, USER_PROCESS);
-+
-+		utmptr = getutxent();
-+		TEST_NE_P(utmptr, NULL);
-+		TEST_EQ(utmptr->ut_pid, 1);
-+		TEST_EQ(utmptr->ut_type, DEAD_PROCESS);
-+
-+		nih_free (job);
-+	}
-+}
-+
-+
- int
- main (int   argc,
-       char *argv[])
-@@ -4505,6 +4672,7 @@ main (int   argc,
- 	test_spawn ();
- 	test_kill ();
- 	test_handler ();
-+	test_utmp ();
- 
- 	test_find ();
+ 			/* Update existing utmp file. */
+ 			pututxline(utmptr);
  
diff --git a/upstart.spec b/upstart.spec
index dcae3d7..6100c3e 100644
--- a/upstart.spec
+++ b/upstart.spec
@@ -1,26 +1,24 @@
 Name:           upstart
-Version:        0.6.5
-Release:        11%{?dist}
+Version:        1.2
+Release:        1%{?dist}
 Summary:        An event-driven init system
 
 Group:          System Environment/Base
 License:        GPLv2 and LGPLv2+
-URL:            http://upstart.ubuntu.com
-Source0:        http://upstart.ubuntu.com/download/0.6/upstart-%{version}.tar.gz
+URL:            https://launchpad.net/upstart
+Source0:        http://launchpad.net/upstart/1.x/%{version}/+download/upstart-%{version}.tar.gz
 Source1:        init-system-dbus.conf
 Patch1:         upstart-telinit.patch
 Patch2:         upstart-audit-events.patch
 # set DEAD_PROCESS for dead process with pid in utmp table (#572199, #632568)
 Patch3:         upstart-utmp.patch
 Patch4:         upstart-reexec.patch
-# shutdown exits with nonzero exitcode when fails
-Patch5:         upstart-shutdown-exitcode.patch
-# send close fd command to shell first (#646894)
-Patch6:         upstart-close-fd.patch
+# allow job override files
+Patch7:         upstart-override.patch
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildRequires:  gettext, audit-libs-devel, expat-devel
+BuildRequires:  autoconf, automake, gettext, audit-libs-devel, expat-devel
 BuildRequires:  dbus-devel >= 1:1.2.16, libnih-devel >= 1.0.1
-Conflicts:	initscripts < 9.12
+Conflicts:      initscripts < 9.12
 Requires:       sysvinit-userspace
 
 %description
@@ -46,8 +44,7 @@ Drop-in replacement for the System V init tools, provided by Upstart.
 %patch2 -p1 -b .audit
 %patch3 -p1 -b .utmp
 %patch4 -p1 -b .reexec
-%patch5 -p1 -b .exitcode
-%patch6 -p1 -b .closefd
+%patch7 -p1 -b .override
 
 %build
 %configure --sbindir=/sbin --libdir=/%{_lib}
@@ -159,6 +156,10 @@ rm -rf %{buildroot}
 %{_mandir}/man8/telinit.8.gz
 
 %changelog
+* Mon May 09 2011 Petr Lautrbach <plautrba at redhat.com> 1.2-1
+- upgrade to 1.2
+- allow job override files
+
 * Thu Nov 04 2010 Petr Lautrbach <plautrba at redhat.com> 0.6.5-11
 - drop systemd-sysvinit obsoletes (#649510)
 


More information about the scm-commits mailing list