[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