Compare commits

...
Sign in to create a new pull request.

8 commits

Author SHA1 Message Date
Fedora Release Engineering
03fd48fc95 dist-git conversion 2010-07-29 14:46:20 +00:00
Bill Nottingham
a751f3a3fd Fix typo that causes a failure to update the common directory. (releng
#2781)
2009-11-26 01:15:33 +00:00
Casey Dahlin
18c0e1345d Fix Bug #450488 2009-01-24 00:59:44 +00:00
Bill Nottingham
73d3b8cced add changelog 2009-01-13 00:48:29 +00:00
Casey Dahlin
53b736801b Rev bumps for previous change 2009-01-10 21:48:21 +00:00
Casey Dahlin
0cad0eb635 Remove telinit u support since its broken 2009-01-10 21:45:51 +00:00
Casey Dahlin
4f4341f7bb revert the 0.5.0 changes. Get back to where we once belonged. 2009-01-10 21:34:52 +00:00
Jesse Keating
ead2d1bd75 Initialize branch F-10 for upstart 2008-11-07 04:03:49 +00:00
6 changed files with 486 additions and 79 deletions

View file

@ -1 +0,0 @@
upstart-0.5.0.tar.bz2

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
upstart-0.3.9.tar.bz2

View file

@ -1,21 +0,0 @@
# Makefile for source rpm: upstart
# $Id$
NAME := upstart
SPECFILE = $(firstword $(wildcard *.spec))
define find-makefile-common
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
endef
MAKEFILE_COMMON := $(shell $(find-makefile-common))
ifeq ($(MAKEFILE_COMMON),)
# attept a checkout
define checkout-makefile-common
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
endef
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
endif
include $(MAKEFILE_COMMON)

View file

@ -1 +1 @@
c040227c746d22f87c0cd20cd1ca865b upstart-0.5.0.tar.bz2
794208083d405ece123ad59a02f3e233 upstart-0.3.9.tar.bz2

View file

@ -0,0 +1,442 @@
diff -uNr upstart-0.3.9.orig/init/main.c upstart-0.3.9/init/main.c
--- upstart-0.3.9.orig/init/main.c 2009-01-23 13:44:32.000000000 -0500
+++ upstart-0.3.9/init/main.c 2009-01-23 13:44:54.000000000 -0500
@@ -59,6 +59,7 @@
#include "cfgfile.h"
#include "paths.h"
#include "tty.h"
+#include "restore.h"
/* Prototypes for static functions */
@@ -278,6 +279,10 @@
exit (1);
}
+ /* Restore the state of previously active jobs, if re-exec'd by
+ * a previously running init. */
+
+ if (restart) restore_configuration(args);
/* Generate and run the startup event or read the state from the
* init daemon that exec'd us
@@ -534,6 +539,8 @@
NihError *err;
const char *loglevel;
sigset_t mask, oldmask;
+ char **args;
+ size_t len;
nih_assert (argv0 != NULL);
nih_assert (signal != NULL);
@@ -559,7 +566,20 @@
} else {
loglevel = NULL;
}
- execl (argv0, argv0, "--restart", loglevel, NULL);
+ args = nih_str_array_new(NULL);
+ len = 0;
+ if (args) args = nih_str_array_add(&args, NULL, &len, argv0);
+ if (args) args = nih_str_array_add(&args, NULL, &len, "--restart");
+ if (args && loglevel)
+ args = nih_str_array_add(&args, NULL, &len, loglevel);
+ if (args) save_current_configuration(&args, NULL, &len);
+ if (args) {
+ execv (argv0, args);
+ nih_free(args);
+ } else {
+ nih_warn (_("Unable to save list of currently running jobs"));
+ execl(argv0, argv0, "--restart", loglevel, NULL);
+ }
nih_error_raise_system ();
err = nih_error_get ();
diff -uNr upstart-0.3.9.orig/init/Makefile.am upstart-0.3.9/init/Makefile.am
--- upstart-0.3.9.orig/init/Makefile.am 2009-01-23 13:44:32.000000000 -0500
+++ upstart-0.3.9/init/Makefile.am 2009-01-23 13:44:54.000000000 -0500
@@ -23,7 +23,8 @@
event.c event.h \
control.c control.h \
notify.c notify.h \
- cfgfile.c cfgfile.h
+ cfgfile.c cfgfile.h \
+ restore.c restore.h
init_LDFLAGS = -static
init_LDADD = \
diff -uNr upstart-0.3.9.orig/init/Makefile.in upstart-0.3.9/init/Makefile.in
--- upstart-0.3.9.orig/init/Makefile.in 2009-01-23 13:44:32.000000000 -0500
+++ upstart-0.3.9/init/Makefile.in 2009-01-23 13:44:54.000000000 -0500
@@ -72,7 +72,7 @@
PROGRAMS = $(sbin_PROGRAMS)
am_init_OBJECTS = main.$(OBJEXT) tty.$(OBJEXT) process.$(OBJEXT) \
job.$(OBJEXT) event.$(OBJEXT) control.$(OBJEXT) \
- notify.$(OBJEXT) cfgfile.$(OBJEXT)
+ notify.$(OBJEXT) cfgfile.$(OBJEXT) restore.$(OBJEXT)
init_OBJECTS = $(am_init_OBJECTS)
am__DEPENDENCIES_1 =
init_DEPENDENCIES = ../upstart/libupstart.la ../nih/libnih.la \
@@ -315,7 +315,8 @@
event.c event.h \
control.c control.h \
notify.c notify.h \
- cfgfile.c cfgfile.h
+ cfgfile.c cfgfile.h \
+ restore.c restore.h
init_LDFLAGS = -static
init_LDADD = \
diff -uNr upstart-0.3.9.orig/init/restore.c upstart-0.3.9/init/restore.c
--- upstart-0.3.9.orig/init/restore.c 1969-12-31 19:00:00.000000000 -0500
+++ upstart-0.3.9/init/restore.c 2009-01-23 13:44:54.000000000 -0500
@@ -0,0 +1,333 @@
+/* Modifications to upstart to allow passing of the state of currently
+ * running jobs when upstart re-execs itself.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+
+#include <sys/types.h>
+#include <string.h>
+#include <nih/string.h>
+#include <nih/logging.h>
+#include <nih/alloc.h>
+#include "job.h"
+#include "restore.h"
+
+
+/**
+ * store_pid:
+ * @proc: pointer to a JobProcess structure or NULL
+ * @args: array of arguments
+ * @parent: parent of @args
+ * @len: current length of @args
+ *
+ * Does nothing if @args is null.
+ * Pushes "X" onto @args if @args is non-null but @process is null.
+ * Otherwise: extracts the pid from @process, creates a hexadecimal string
+ * form of it, pushes a copy onto the array @args, then frees the original.
+ */
+
+void store_pid(JobProcess *proc, char ***args, const void *parent, size_t *len)
+{
+ char *pidstr;
+ if (! *args) return;
+ pidstr = (proc ? nih_sprintf(NULL, "%x", proc->pid) : "X");
+
+ if (! pidstr) {
+ nih_error("Unable to allocate storage to save process id");
+ *args = NULL;
+ return;
+ }
+ if (! nih_str_array_add(args, parent, len, pidstr)) {
+ nih_error("Unable to add process id to argument list");
+ *args = NULL;
+ }
+
+ if (proc) nih_free(pidstr);
+}
+
+/**
+ * unpack_pid:
+ * @pidstr: hexadecimal string created by pack_pid
+ * @err: pointer to flag to set if error occurs
+ *
+ * Returns the process id corresponding to the string passed in pidstr.
+ * If an error occurs, returns 0 and sets the flag pointed to by @err.
+ **/
+
+pid_t unpack_pid(char *pidstr, int *err) {
+ pid_t result = 0;
+ while (*pidstr) {
+ unsigned char c = *pidstr++;
+ result <<= 4;
+ if (c >= '0' && c <= '9') result += (c-'0');
+ else if (c >= 'a' && c <= 'f') result += 10 + (c-'a');
+ else {
+ *err = 1;
+ return 0;
+ }
+ }
+ return result;
+}
+
+/**
+ * retrieve_pid:
+ * @arg: pointer to array of arguments from which to read pid string
+ * @jobname: name of job whose pids are being retrieved
+ * @err: pointer to flag to set if error occurs
+ * @pid: pointer to location to hold the retrieved process id
+ * @present: pointer to a location to hold 1 if the process id was present
+ *
+ * Reads a process id or no-process-present indicator from the hexadecimal
+ * string pointed to by @arg, increments @arg to point to the next string in
+ * the array unless it already points to a null string, and stores into
+ * @present a value of 0 or 1 indicating whether or not a process id is
+ * present, and stores into @pid the unpacked process id (or zero if there
+ * is no process present or an error occurred). If an error occured, sets
+ * the flag pointed to by @err and printes an error message.
+ **/
+
+void retrieve_pid(char ***arg, char *jobname, int *err,
+ pid_t *pid, int *present)
+{
+ *pid = 0;
+ *present = 0;
+ char *str;
+ if (! arg || ! *arg || ! **arg) {
+ nih_error("Ran out of arguments when restoring job %s",
+ jobname);
+ *err = 1;
+ return;
+ }
+ str = **arg;
+ if (str) ++(*arg);
+ if (strcmp(str, "X")==0) return;
+ *present = 1;
+ *pid = unpack_pid(str, err);
+ if (*err) nih_error("Cannot parse pid %s for job %s", str, jobname);
+}
+
+/**
+ * restore_pid:
+ * @proc: pointer to a JobProcess structure, or NULL
+ * @pid: process id
+ * @present: integer which is 1 if process id is applicable
+ * @jobname: name of job whose process ids are being restored
+ *
+ * Checks that the non-null status of @proc matches the true/false
+ * status of @present. If there is a mismatch, prints an error message.
+ * If @present is true and @proc is non-null, stores the process id from
+ * @pid into the JobProcess structure pointed to by @proc.
+ */
+
+void restore_pid(JobProcess *proc, pid_t pid, int present, char *jobname)
+{
+ if (proc == NULL && ! present) return;
+ if (proc != NULL && present) {
+ proc->pid = pid;
+ return;
+ }
+ nih_error("Unable to restore process id for job %s", jobname);
+}
+
+/**
+ * save_current_configuration:
+ * @args: array of arguments to pass to new init
+ * @parent: parent of @args
+ * @len: current length of @args
+ *
+ * Pushes, onto the array @args, information about currently running
+ * jobs. Each job consists of seven arguments:
+ * (1) The job name
+ * (2) A 3-character state/goal string:
+ * First character for the goal: 0=goal JOB_STOP, 1=goal JOB_START
+ * Second character for the current state:
+ * W=JOB_WAITING,
+ * S=JOB_STARTING, A=JOB_PRE_START, B=JOB_SPAWNED, C=JOB_POST_START,
+ * R=JOB_RUNNING,
+ * T=JOB_STOPPING, X=JOB_PRE_STOP, Y=JOB_KILLED, Z=JOB_POST_STOP
+ * Third character: N=normal job, I=instance job
+ * (3) The associated PROCESS_MAIN process id
+ * (4) The associated PROCESS_PRE_START process id
+ * (5) The associated PROCESS_POST_START process id
+ * (6) The associated PROCESS_PRE_STOP process id
+ * (7) The associated PROCESS_POST_STOP process id
+ * Process ids are in hexadecimal using lower-case letters (0-9,a-f),
+ * or 0 if there is a JobProcess structure but no running process, or
+ * "X" if there is no JobProcess structure.
+ *
+ */
+
+void save_current_configuration(char ***args, const void *parent, size_t *len)
+{
+ NIH_HASH_FOREACH(jobs, iter) {
+ Job *job = (Job *) iter;
+ char goal_state[4];
+ JobProcess **pids;
+
+
+ if (job->replacement_for != NULL) continue;
+ if (job->state == JOB_DELETED) continue;
+ if (job->instance && ! job->instance_of) continue;
+
+ if (! nih_str_array_add(args, parent, len, job->name))
+ return;
+
+ if (job->goal == JOB_START) goal_state[0] = '1';
+ else goal_state[0] = '0';
+
+ switch (job->state)
+ {
+ case JOB_WAITING: goal_state[1] = 'W'; break;
+ case JOB_STARTING: goal_state[1] = 'S'; break;
+ case JOB_PRE_START: goal_state[1] = 'A'; break;
+ case JOB_SPAWNED: goal_state[1] = 'B'; break;
+ case JOB_POST_START: goal_state[1] = 'C'; break;
+ case JOB_RUNNING: goal_state[1] = 'R'; break;
+ case JOB_STOPPING: goal_state[1] = 'T'; break;
+ case JOB_PRE_STOP: goal_state[1] = 'X'; break;
+ case JOB_KILLED: goal_state[1] = 'Y'; break;
+ case JOB_POST_STOP: goal_state[1] = 'Z'; break;
+ default: goal_state[1] = '?';
+ }
+ if (job->instance_of) goal_state[2] = 'I';
+ else goal_state[2] = 'N';
+ goal_state[3] = 0;
+
+ if (! nih_str_array_add(args, parent, len, goal_state))
+ return;
+
+ pids = job->process;
+ store_pid(pids[PROCESS_MAIN], args, parent, len);
+ store_pid(pids[PROCESS_PRE_START], args, parent, len);
+ store_pid(pids[PROCESS_POST_START], args, parent, len);
+ store_pid(pids[PROCESS_PRE_STOP], args, parent, len);
+ store_pid(pids[PROCESS_POST_STOP], args, parent, len);
+ }
+}
+
+/**
+ * restore_job_state:
+ * @jobname: name of job whose state we are to restore
+ * @goal_state: the goal/state string generated by save_current_configuration
+ * @pids: array of five process ids
+ * @presents: array of five integers indicating which process ids are applicable
+ */
+
+void restore_job_state (char *jobname, char *goal_state,
+ pid_t *pids, int *presents)
+{
+ Job *job;
+ JobGoal goal = JOB_STOP;
+ JobState state = JOB_WAITING;
+ int is_instance = 0;
+ int is_invalid = 0;
+ JobProcess **procs;
+
+ if (jobname == NULL) {
+ nih_error("Missing name for restored job");
+ return;
+ }
+
+ if (goal_state == NULL) {
+ nih_error("Missing goal/state for restored job %s", jobname);
+ return;
+ }
+
+ if (strlen(goal_state) != 3) {
+ nih_error("Invalid length goal/state %s for restored job %s",
+ goal_state, jobname);
+ return;
+ }
+
+ switch (goal_state[0])
+ {
+ case '0': goal = JOB_STOP; break;
+ case '1': goal = JOB_START; break;
+ default: is_invalid = 1; break;
+ }
+
+ switch (goal_state[1])
+ {
+ case 'W': state = JOB_WAITING; break;
+ case 'S': state = JOB_STARTING; break;
+ case 'A': state = JOB_PRE_START; break;
+ case 'B': state = JOB_SPAWNED; break;
+ case 'C': state = JOB_POST_START; break;
+ case 'R': state = JOB_RUNNING; break;
+ case 'T': state = JOB_STOPPING; break;
+ case 'X': state = JOB_PRE_STOP; break;
+ case 'Y': state = JOB_KILLED; break;
+ case 'Z': state = JOB_POST_STOP; break;
+ default: is_invalid = 1;
+ }
+
+ switch (goal_state[2])
+ {
+ case 'N': break;
+ case 'I': is_instance = 1; break;
+ default: is_invalid = 1;
+ }
+
+ if (is_invalid) {
+ nih_error("Invalid goal/state %s for restored job %s",
+ goal_state, jobname);
+ return;
+ }
+ job = job_find_by_name(jobname);
+ if (! job) {
+ nih_error("Unknown job %s passed to re-exec", jobname);
+ return;
+ }
+ if (is_instance) {
+ if (! job->instance) {
+ nih_error("Can not restore job %s as instance job",
+ jobname);
+ return;
+ }
+ job = job_instance(job);
+ } else {
+ if (job->instance) {
+ nih_error("Can not restore job %s as non-instance job",
+ jobname);
+ return;
+ }
+ }
+ job->goal = goal;
+ job->state = state;
+ procs=job->process;
+ restore_pid(procs[PROCESS_MAIN], pids[0], presents[0], jobname);
+ restore_pid(procs[PROCESS_PRE_START], pids[1], presents[1], jobname);
+ restore_pid(procs[PROCESS_POST_START], pids[2], presents[2], jobname);
+ restore_pid(procs[PROCESS_PRE_STOP], pids[3], presents[3], jobname);
+ restore_pid(procs[PROCESS_POST_STOP], pids[4], presents[4], jobname);
+}
+
+/**
+ * restore_current_configuration:
+ * @args: non-option arguments that were passed to the new init
+ */
+
+void restore_configuration(char **args)
+{
+ if (! args) return;
+
+ char **arg = args;
+ while (arg && *arg) {
+ char *jobname = *(arg++);
+ char *goal_state = *arg;
+ pid_t pids[5];
+ int presents[5];
+ int is_invalid = 0;
+
+ if (*arg) ++arg;
+ for (int i = 0; i < 5; i++)
+ retrieve_pid(&arg, jobname, &is_invalid,
+ &pids[i], &presents[i]);
+
+ if (! is_invalid)
+ restore_job_state (jobname, goal_state, pids, presents);
+ }
+}
diff -uNr upstart-0.3.9.orig/init/restore.h upstart-0.3.9/init/restore.h
--- upstart-0.3.9.orig/init/restore.h 1969-12-31 19:00:00.000000000 -0500
+++ upstart-0.3.9/init/restore.h 2009-01-23 13:44:54.000000000 -0500
@@ -0,0 +1,13 @@
+#ifndef INIT_RESTORE_H
+#define INIT_RESTORE_H
+
+#include <nih/string.h>
+
+NIH_BEGIN_EXTERN
+
+void save_current_configuration(char ***args, const void *parent, size_t *len);
+void restore_configuration(char **args);
+
+NIH_END_EXTERN
+
+#endif /* INIT_RESTORE_H */

View file

@ -1,26 +1,24 @@
#%define build_str 20080730bzr_dbus_userspace_1046
%define build_str 0
%if %build_str
%define build_rel 0.%{build_str}_
%define build_pkg -%{build_str}
%else
%define build_rel %{nil}
%define build_pkg %{nil}
%endif
Name: upstart
Version: 0.5.0
Release: %{build_rel}1%{?dist}
Version: 0.3.9
Release: 22%{?dist}
Summary: An event-driven init system
Group: System Environment/Base
License: GPLv2+
URL: http://upstart.ubuntu.com
Source0: http://upstart.ubuntu.com/download/0.3/upstart-%{version}%{build_pkg}.tar.bz2
Source1: events.5
Source0: http://upstart.ubuntu.com/download/0.3/upstart-%{version}.tar.bz2
Source1: events.5
Patch0: upstart-gcc43.patch
Patch1: upstart-force-on-shutdown-reboot.patch
Patch2: upstart-tty-stack.patch
Patch3: upstart-rpm.patch
Patch4: upstart-fedora-buglist.patch
Patch5: upstart-telinit-u.patch
Patch6: upstart-initctl-man.patch
Patch7: upstart-save-state-across-reexec.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Obsoletes: SysVinit < 2.86-24, sysvinit < 2.86-24
Provides: SysVinit = 2.86-24, sysvinit = 2.86-24
Requires: dbus >= 1.2.1-4
BuildRequires: gettext
%description
@ -28,11 +26,16 @@ Upstart is an event-based replacement for the /sbin/init daemon which
handles starting of tasks and services during boot, stopping them
during shutdown and supervising them while the system is running.
%post
kill -TERM 1
%prep
%setup -q -n upstart-%{version}%{build_pkg}
%setup -q
%patch0 -p1
%patch1 -p1
%patch2
%patch3
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%build
%configure --enable-compat=sysv --sbindir=/sbin --libdir=/%{_lib}
@ -42,11 +45,20 @@ make %{?_smp_mflags}
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}
mkdir -p %{buildroot}/%{_sysconfdir}/init/jobs.d/
mkdir -p %{buildroot}/%{_mandir}/man5
install -m 644 %{SOURCE1} %{buildroot}/%{_mandir}/man5/events.5
# libupstart and libnih aren't shipped
rm -f %{buildroot}/%{_lib}/libupstart.*
rm -f %{buildroot}/%{_lib}/libnih.*
rm -f %{buildroot}/%{_includedir}/libnih.h
rm -f %{buildroot}/%{_includedir}/libupstart.h
rm -rf %{buildroot}/%{_includedir}/nih
rm -rf %{buildroot}/%{_includedir}/upstart
rm -rf %{buildroot}/%{_datadir}/aclocal/compiler.m4
rm -rf %{buildroot}/%{_datadir}/aclocal/linker.m4
rm -rf %{buildroot}/%{_datadir}/aclocal/misc.m4
%find_lang %{name}
%clean
@ -60,11 +72,12 @@ rm -rf %{buildroot}
%doc README
%doc TODO
%doc HACKING
%{_sysconfdir}/init/
%{_sysconfdir}/dbus-1/system.d/Upstart.conf
%{_sysconfdir}/event.d/
%config(noreplace) %{_sysconfdir}/event.d/logd
/sbin/halt
/sbin/init
/sbin/initctl
/sbin/logd
/sbin/poweroff
/sbin/reboot
/sbin/runlevel
@ -77,6 +90,7 @@ rm -rf %{buildroot}
%{_mandir}/man8/halt.8.gz
%{_mandir}/man8/init.8.gz
%{_mandir}/man8/initctl.8.gz
%{_mandir}/man8/logd.8.gz
%{_mandir}/man8/poweroff.8.gz
%{_mandir}/man8/reboot.8.gz
%{_mandir}/man8/runlevel.8.gz
@ -87,40 +101,12 @@ rm -rf %{buildroot}
%{_mandir}/man8/telinit.8.gz
%changelog
* Tue Aug 12 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0
- New upstream release
* Fri Jan 23 2009 Casey Dahlin <cdahlin@redhat.com> - 0.3.9-22
- Re-add 'telinit u' support along with patch to fix it (#450488). Patch due to
<pspencer@fields.utoronto.ca>
* Thu Jul 31 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-20080730bzr_dbus_userspace_1046_2
- Rebase to upstream
- To retrieve source:
bzr clone lp:upstart/0.5 -r 1046
bzr branch lp:~cjdahlin/libnih/event-loop-async-fix -r 596
* Wed Jul 23 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-20080723bzr_dbus_userspace_1045_1
- More reflective tarball name
- Retrieve source with `bzr clone lp:~cjdahlin/upstart/trunk -r 1045`
* Tue Jul 22 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.7
- Fix bug in environment substitution
* Tue Jul 22 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.6
- Fix reboot issue
* Mon Jul 21 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.5
- Propagate runlevel calculation glitch fix to /sbin/shutdown
* Fri Jul 18 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.4
- Fix runlevel calculation glitch
- Remove some loose comments from spec
* Wed Jul 16 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.3
- Bump dbus timeout to INT_MAX
* Wed Jul 16 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.2
- Fix mishandling of multiline scripts
* Wed Jul 16 2008 Casey Dahlin <cdahlin@redhat.com - 0.5.0-0.0.1
- Upstream to lp:upstart/dbus-userspace
* Mon Jan 12 2009 Bill Nottingham <notting@redhat.com> - 0.3.9-21
- Remove 'telinit u' support as it is broken (#450488, <cjdahlin@ncsu.edu>)
* Fri Apr 25 2008 Bill Nottingham <notting@redhat.com> - 0.3.9-19
- with the merge of event-compat-sysv, move the sysvinit obsoletes/provides here