Git init
authorKibum Kim <kb0929.kim@samsung.com>
Fri, 6 Jan 2012 15:47:31 +0000 (00:47 +0900)
committerKibum Kim <kb0929.kim@samsung.com>
Fri, 6 Jan 2012 15:47:31 +0000 (00:47 +0900)
111 files changed:
CHANGES [new file with mode: 0644]
COPYING [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
debian/README.Debian [new file with mode: 0644]
debian/README.source [new file with mode: 0644]
debian/bash-completion [new file with mode: 0644]
debian/bts-lefttoreport [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/check-archive-initd-scripts [new file with mode: 0644]
debian/check-initd-order [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/dirs [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/lintian-overrides [new file with mode: 0644]
debian/make-testsuite [new file with mode: 0644]
debian/manpages [new file with mode: 0644]
debian/overrides/devfsd [new file with mode: 0644]
debian/overrides/hotplug [new file with mode: 0644]
debian/overrides/hotplug-net [new file with mode: 0644]
debian/overrides/initrd-tools.sh [new file with mode: 0644]
debian/overrides/modutils [new file with mode: 0644]
debian/patches/10_nosuse.patch [new file with mode: 0644]
debian/patches/11_debian_conf.patch [new file with mode: 0644]
debian/patches/20_install_perms_fixup.patch [new file with mode: 0644]
debian/patches/21_tests_suite_new_functions.patch [new file with mode: 0644]
debian/patches/30_deterministic_order.patch [new file with mode: 0644]
debian/patches/40_badboy_segfault.patch [new file with mode: 0644]
debian/patches/50_symlink_in_initddir.patch [new file with mode: 0644]
debian/patches/60_all_keyword_start_only.patch [new file with mode: 0644]
debian/patches/61_interactive_keyword.patch [new file with mode: 0644]
debian/patches/62_upstart_job.patch [new file with mode: 0644]
debian/patches/70_req_start_all_depends.patch [new file with mode: 0644]
debian/patches/71_complete_makefile.patch [new file with mode: 0644]
debian/patches/80_manual_warnings.patch [new file with mode: 0644]
debian/patches/81_lessverbose.patch [new file with mode: 0644]
debian/patches/82_loop_exit_msg.patch [new file with mode: 0644]
debian/patches/90_no_runlevel_spec_for_debian.patch [new file with mode: 0644]
debian/patches/91_kfreebsd_nofadvice.patch [new file with mode: 0644]
debian/patches/92_m68k_alignment.patch [new file with mode: 0644]
debian/patches/93_hurd_no_path_max.patch [new file with mode: 0644]
debian/patches/94_v1_12_2.patch [new file with mode: 0644]
debian/patches/95_stop_all.patch [new file with mode: 0644]
debian/patches/96_hurd_no_at_funcs.patch [new file with mode: 0644]
debian/patches/series [new file with mode: 0644]
debian/po/POTFILES.in [new file with mode: 0644]
debian/po/cs.po [new file with mode: 0644]
debian/po/de.po [new file with mode: 0644]
debian/po/es.po [new file with mode: 0644]
debian/po/fi.po [new file with mode: 0644]
debian/po/fr.po [new file with mode: 0644]
debian/po/gl.po [new file with mode: 0644]
debian/po/it.po [new file with mode: 0644]
debian/po/ja.po [new file with mode: 0644]
debian/po/nl.po [new file with mode: 0644]
debian/po/pt.po [new file with mode: 0644]
debian/po/ru.po [new file with mode: 0644]
debian/po/sv.po [new file with mode: 0644]
debian/po/templates.pot [new file with mode: 0644]
debian/po/vi.po [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/run-testsuite [new file with mode: 0644]
debian/seq-changes [new file with mode: 0644]
debian/update-bootsystem-insserv [new file with mode: 0644]
debian/update-rc.d-insserv [new file with mode: 0644]
debian/update-rc.d-insserv.8 [new file with mode: 0644]
debian/watch [new file with mode: 0644]
init-functions [new file with mode: 0644]
insserv-1.12.0.lsm [new file with mode: 0644]
insserv.8.in [new file with mode: 0644]
insserv.c [new file with mode: 0644]
insserv.conf [new file with mode: 0644]
install_initd [new file with mode: 0755]
listing.c [new file with mode: 0644]
listing.h [new file with mode: 0644]
packaging/10_nosuse.patch [new file with mode: 0644]
packaging/11_debian_conf.patch [new file with mode: 0644]
packaging/20_install_perms_fixup.patch [new file with mode: 0644]
packaging/21_tests_suite_new_functions.patch [new file with mode: 0644]
packaging/30_deterministic_order.patch [new file with mode: 0644]
packaging/40_badboy_segfault.patch [new file with mode: 0644]
packaging/50_symlink_in_initddir.patch [new file with mode: 0644]
packaging/61_interactive_keyword.patch [new file with mode: 0644]
packaging/62_upstart_job.patch [new file with mode: 0644]
packaging/70_req_start_all_depends.patch [new file with mode: 0644]
packaging/71_complete_makefile.patch [new file with mode: 0644]
packaging/81_lessverbose.patch [new file with mode: 0644]
packaging/82_loop_exit_msg.patch [new file with mode: 0644]
packaging/91_kfreebsd_nofadvice.patch [new file with mode: 0644]
packaging/92_m68k_alignment.patch [new file with mode: 0644]
packaging/93_hurd_no_path_max.patch [new file with mode: 0644]
packaging/94_v1_12_2.patch [new file with mode: 0644]
packaging/95_stop_all.patch [new file with mode: 0644]
packaging/96_hurd_no_at_funcs.patch [new file with mode: 0644]
packaging/bash-completion [new file with mode: 0644]
packaging/check-archive-initd-scripts [new file with mode: 0644]
packaging/check-initd-order [new file with mode: 0644]
packaging/devfsd [new file with mode: 0644]
packaging/hotplug [new file with mode: 0644]
packaging/hotplug-net [new file with mode: 0644]
packaging/initrd-tools.sh [new file with mode: 0644]
packaging/insserv.spec [new file with mode: 0644]
packaging/make-testsuite [new file with mode: 0644]
packaging/modutils [new file with mode: 0644]
packaging/seq-changes [new file with mode: 0644]
packaging/update-bootsystem-insserv [new file with mode: 0644]
packaging/update-rc.d-insserv [new file with mode: 0644]
remove_initd [new file with mode: 0755]
tests/suite [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..bfc7bce
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,416 @@
+-------------------------------------------------------------------
+Tue Jul 29 15:23:43 CEST 2008 - werner@suse.de
+
+- Resolve server minor problems on openSUSE and Debian
+  * Handle the runlevel bit for system boot in lvl2str()
+  * Handle dependencies on several script on command line
+  * Let link scheme overwrite empty default start/stop tags
+
+-------------------------------------------------------------------
+Wed Jul  2 19:38:15 CEST 2008 - werner@suse.de
+
+- Use prefetch from kernels code for lists
+- Make start/stop requirements link to the services its self
+- Make -pedantic work
+- Be sure that the code is optimized
+
+-------------------------------------------------------------------
+Wed Jun 25 19:37:35 CEST 2008 - werner@suse.de
+
+- Handle provides and service lists in parallel, this should
+  reduce the double efforts.
+- Calculate start oder and stop order separately
+- Sort targets in the makefile accordingly to their order
+
+-------------------------------------------------------------------
+Wed Jun 18 15:27:16 CEST 2008 - werner@suse.de
+
+- Clean out several provides of one specific script, add therefore
+  an alias list to the first provide. This makes less work load on
+  following the full dependcy trees.
+- Use aligned memory allocation to avoid memory fragmentation
+- Use reference counts to be able to free not needed memory
+- Be able to follow not only the start but also the stop dependcies
+
+-------------------------------------------------------------------
+Wed Jun 11 14:35:13 CEST 2008 - werner@suse.de
+
+- Make kbd interactive to avoid race during tty resize (bnc#259577)
+
+-------------------------------------------------------------------
+Wed Jun  4 12:17:44 CEST 2008 - werner@suse.de
+
+- Scan service links even for non LSB scripts (bnc#391014)
+
+-------------------------------------------------------------------
+Thu May 29 00:42:42 CEST 2008 - dmueller@suse.de
+
+- really remove last reference to boot.setclock (bnc#384254)
+
+-------------------------------------------------------------------
+Tue May 20 09:25:41 CEST 2008 - werner@suse.de
+
+- Remove last occurence of boot.setclock (bnc#384254)
+
+-------------------------------------------------------------------
+Thu May 15 13:42:57 CEST 2008 - werner@suse.de
+
+- Also ignore temporary (mostly?) errors if executed within an rpm
+  scriptlet (bnc#385498, bnc#384254)
+- Move stat() check for /etc/insserv.conf.d/ configure files
+  to scan_conf() otherwise we never scan those files.
+
+-------------------------------------------------------------------
+Mon May  5 18:47:26 CEST 2008 - werner@suse.de
+
+- Ignore temporary errors during update with YaST/zypper (bnc#385498)
+
+-------------------------------------------------------------------
+Mon Apr 28 15:25:54 CEST 2008 - werner@suse.de
+
+- boot.clock was into two scripts for boot and shutdown
+  Todo: make insserv knowing about Required-Stop to merge them
+  again to one boot.clock.
+
+-------------------------------------------------------------------
+Wed Apr  9 16:02:26 CEST 2008 - mkoenig@suse.de
+
+- add boot.crypto-early to insserv.conf
+
+-------------------------------------------------------------------
+Mon Feb  4 18:32:33 CET 2008 - werner@suse.de
+
+- Expand system facilities to make deep of the dependcy graph
+  less deeper.
+
+-------------------------------------------------------------------
+Fri Feb  1 14:34:52 CET 2008 - werner@suse.de
+
+- Avoid SIGSEGV in functions which can handle NULL pointers
+  thanks goes to Petter Reinholdtsen for his report
+
+-------------------------------------------------------------------
+Wed Jan 30 17:49:55 CET 2008 - werner@suse.de
+
+- New version 1.11.0 of insserv
+- Code cleanup, update copyrights, and manual pages
+- Use __attribute__ of gcc for better function management
+- Use __attribute__ of gcc for alignment of list_t pointers
+- Some preparation listing.c for kill link sorting (TODO)
+
+-------------------------------------------------------------------
+Thu Jan 24 18:59:14 CET 2008 - werner@suse.de
+
+- Add and integrate many patches from Debian svn tree done by
+  Petter Reinholdtsen
+  * Make it possible to set the path at runtime, to make it easier
+    to write test suites
+  * Support for reading LSB headers info from override directroy
+  * Accept script names like 'rc.local' for Debian build
+  * Use other defaults on Debian systems (start, stop levels)
+  * Put redundant level informations in one API
+  * Fix the handling of stop scripts and the shutdown sequence
+    on Debian systems
+  * Better loop report
+  * Make loops fatal if not forced
+- Clean the API for listing the services
+
+-------------------------------------------------------------------
+Wed Oct 10 12:39:25 CEST 2007 - werner@suse.de
+
+- Even disabled scripts should be occur in dependcies (#331615)
+- Handle return values of strsep in case of several provides
+- Do not scan services links if removed later on
+- New version 1.10.0 of insserv
+
+-------------------------------------------------------------------
+Fri Aug 31 16:08:47 CEST 2007 - werner@suse.de
+
+- Scan all scripts for Start-Before even if already known (#297214)
+- Do not add disabled scripts to the depend files
+
+-------------------------------------------------------------------
+Fri Jul 13 12:05:19 CEST 2007 - werner@suse.de
+
+- Remove hotplug and pcmcia from insserv.conf because they are
+  dropped (bug #291417)
+
+-------------------------------------------------------------------
+Tue Jun 19 18:59:30 CEST 2007 - werner@suse.de
+
+- Scan all files in `should start before' even facilities
+- Read insserv.conf in other root environments
+
+-------------------------------------------------------------------
+Tue May 29 17:45:06 CEST 2007 - werner@suse.de
+
+- Ignore rcs-files (bug #278520)
+
+-------------------------------------------------------------------
+Mon Jan 29 15:08:17 CET 2007 - werner@suse.de
+
+- Split insserv.conf off from source tar ball to avoid patching
+- Add boot.crypto to $local_fs
+- Add smbfs/cifs to $remote_fs
+
+-------------------------------------------------------------------
+Mon Jan 22 15:17:23 CET 2007 - werner@suse.de
+
+- Add missed `start this script before' feature patch (fate#301269)
+
+-------------------------------------------------------------------
+Tue Jan 16 14:04:06 CET 2007 - werner@suse.de
+
+- Remove obsolate `$netdaemons' facility (#209380)
+- Add `start this script before' feature (fate #301269)
+- New version 1.09.0 of insserv
+
+-------------------------------------------------------------------
+Mon Nov 20 11:42:40 CET 2006 - werner@suse.de
+
+- Expand aliases even for services which requires $all (#216202)
+
+-------------------------------------------------------------------
+Mon May 15 12:56:27 CEST 2006 - werner@suse.de
+
+- Make kdump boot script a interactive script to enforce that this
+  script runs not in parallel with other script (#175340, #171332)
+
+-------------------------------------------------------------------
+Wed Mar  8 17:06:47 CET 2006 - werner@suse.de
+
+- Ignore .orig and .org file (bug #155944)
+
+-------------------------------------------------------------------
+Wed Mar  1 12:51:17 CET 2006 - werner@suse.de
+
+- Add a few lines about $all into the man page (bug #151561)
+
+-------------------------------------------------------------------
+Mon Feb  6 16:40:46 CET 2006 - werner@suse.de
+
+- Handle duplets even for interactive scripts
+
+-------------------------------------------------------------------
+Tue Jan 31 15:06:53 CET 2006 - werner@suse.de
+
+- Be sure to find all interactive scripts and set their unique
+  start number.  This solves the problem of two interactive
+  scripts in the same start order.
+
+-------------------------------------------------------------------
+Tue Apr  4 18:23:24 CEST 2006 - werner@suse.de
+
+- Add patches from Petter Reinholdtsen
+- Make debian part work
+
+-------------------------------------------------------------------
+Wed Jan 25 14:52:26 CET 2006 - werner@suse.de
+
+- Fix the broken fix (bug #145403)
+
+-------------------------------------------------------------------
+Mon Jan 23 13:35:40 CET 2006 - werner@suse.de
+
+- Make missing Provides and Requires non-fatal.
+
+-------------------------------------------------------------------
+Fri Jan 20 18:13:39 CET 2006 - werner@suse.de
+
+- Fix bug in handling of non-LSB scripts
+- Add error condition for broken LSB scripts
+- Make calculation of order number somewhat smarter, e.g. do not
+  count system facilities.
+
+-------------------------------------------------------------------
+Thu Jan 19 15:33:06 CET 2006 - werner@suse.de
+
+- Make the restore option work even on broken link scheme
+- Don't count empty provides
+
+-------------------------------------------------------------------
+Thu Nov 10 18:05:53 CET 2005 - werner@suse.de
+
+- Add patches from Petter Reinholdtsen
+  * Avoid zero pointer
+  * Allow not existing rc ditrectories at dryrun
+  * Some more debugging code
+  * Map the runlevel scheme into a common struct
+
+-------------------------------------------------------------------
+Fri Oct 28 17:48:38 CEST 2005 - werner@suse.de
+
+- Fix duplet handling in make like service handling (bug #130451)
+
+-------------------------------------------------------------------
+Thu Sep 15 16:54:40 CEST 2005 - werner@suse.de
+
+- Add dryrun changes from Petter Reinholdtsen
+- First step for support of traditional SystemV link scheme
+
+-------------------------------------------------------------------
+Wed May 25 17:33:30 CEST 2005 - werner@suse.de
+
+- Include confdir patch from Ludwig Nussel
+- Bounce version to 1.01.0
+
+-------------------------------------------------------------------
+Mon Nov 29 16:32:04 CET 2004 - werner@suse.de
+
+- Add some comments about boot script file names.
+
+-------------------------------------------------------------------
+Thu Nov 25 18:24:35 CET 2004 - werner@suse.de
+
+- Update to 1.00.8 : use correct listing head (bug #48415)
+
+-------------------------------------------------------------------
+Thu Nov 25 13:48:45 CET 2004 - werner@suse.de
+
+- Update to 1.00.7 : be more verbose on invalid file names
+
+-------------------------------------------------------------------
+Tue Nov 23 13:13:35 CET 2004 - werner@suse.de
+
+- Update to 1.00.6
+
+-------------------------------------------------------------------
+Tue Nov 23 13:00:22 CET 2004 - werner@suse.de
+
+- Fix segmentation fault caused by broken cast on reversed scanned
+  linkage structure (bug #48415)
+
+-------------------------------------------------------------------
+Wed Sep 22 11:52:43 CEST 2004 - werner@suse.de
+
+- Do not call error recursively if chdir fails (bugzilla #45767)
+
+-------------------------------------------------------------------
+Mon Sep 20 16:40:13 CEST 2004 - werner@suse.de
+
+- Add a few lines about the make like dependency files to the
+  manual page of insserv.
+
+-------------------------------------------------------------------
+Fri Sep 17 12:16:04 CEST 2004 - werner@suse.de
+
+- Boot scripts which may call sulogin are INTERACTIVE
+
+-------------------------------------------------------------------
+Thu Sep 16 14:19:56 CEST 2004 - werner@suse.de
+
+- Add dnsmasq and lwresd as optional to system facility named
+
+-------------------------------------------------------------------
+Thu Sep  2 11:34:09 BST 2004 - werner@suse.de
+
+- Fix dependency of boot.clock also used in single mode (bug#44610)
+
+-------------------------------------------------------------------
+Fri Aug 27 17:50:39 CEST 2004 - werner@suse.de
+
+- Fix dependencies of single script
+- Fix $ALL handling for dependency files
+- Fix handling of interactive scripts for for dependency files
+
+-------------------------------------------------------------------
+Thu Aug 19 17:37:06 CEST 2004 - werner@suse.de
+
+- Update to 1.00.3 to support dependency files for make calls
+
+-------------------------------------------------------------------
+Wed Mar 31 11:52:31 CEST 2004 - werner@suse.de
+
+- Verbose option and explain exit status in manual page (#37599)
+
+-------------------------------------------------------------------
+Thu Mar 18 17:53:04 CET 2004 - werner@suse.de
+
+- Remove debug message
+
+-------------------------------------------------------------------
+Wed Mar 17 15:12:55 CET 2004 - werner@suse.de
+
+- Implement the `$all' feature (bug #36140)
+
+-------------------------------------------------------------------
+Wed Mar 10 17:27:53 CET 2004 - werner@suse.de
+
+- YAL (Yet Another Loop) fixed (bug #35522)
+
+-------------------------------------------------------------------
+Thu Feb 19 18:40:36 CET 2004 - werner@suse.de
+
+- Do not create a K* link if no S* link exist.
+
+-------------------------------------------------------------------
+Thu Feb 19 13:55:14 CET 2004 - werner@suse.de
+
+- More about K* links in /etc/init.d/boot.d
+
+-------------------------------------------------------------------
+Tue Feb 17 14:18:30 CET 2004 - ro@suse.de
+
+- enable K* (kill) links in /etc/init.d/boot.d
+
+-------------------------------------------------------------------
+Wed Oct  1 17:58:08 CEST 2003 - werner@suse.de
+
+- Allow numbers in initial segment of namespace of scripts (#31793)
+
+-------------------------------------------------------------------
+Mon Sep 22 18:41:26 CEST 2003 - werner@suse.de
+
+- Stop recursive walk on dependency tree hard if a loop is detected
+
+-------------------------------------------------------------------
+Tue Sep 16 13:57:59 CEST 2003 - werner@suse.de
+
+- Add extra flag for ENABLED status of services due the level
+  can not used for checking this anymore (bug #31000)
+
+-------------------------------------------------------------------
+Mon Sep  1 13:49:23 CEST 2003 - werner@suse.de
+
+- Move (re)calculation of order of active scripts after the
+  calculation of all start orders to hold dependencies unique
+
+-------------------------------------------------------------------
+Fri Aug 29 14:42:22 CEST 2003 - werner@suse.de
+
+- Update to 1.00.0 which fixes the handling of interactive
+  services for passphrase input (bug #29375) and enhance
+  the calculation of already enabled NONE-LSB scripts.
+
+-------------------------------------------------------------------
+Thu Jul  3 14:53:39 CEST 2003 - werner@suse.de
+
+- Follow LSB specs and specify script functions for proc
+  handling (no /sbin in PATH anymore).
+
+-------------------------------------------------------------------
+Wed Jun 18 14:39:47 CEST 2003 - werner@suse.de
+
+- Update to 0.99.9: better handling with not LSB conform scripts
+
+-------------------------------------------------------------------
+Thu Jun 12 10:47:07 CEST 2003 - kukuk@suse.de
+
+- fix filelist 
+
+-------------------------------------------------------------------
+Wed Apr 16 18:31:07 CEST 2003 - werner@suse.de
+
+- Update to 0.99.8: be able to remove doubles with -rf
+
+-------------------------------------------------------------------
+Sat Mar  8 16:00:23 CET 2003 - kukuk@suse.de
+
+- Add /lib/lsb back [Bug #24904]
+
+-------------------------------------------------------------------
+Wed Jan 15 17:07:54 CET 2003 - ro@suse.de
+
+- split from aaa_base
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..60549be
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..96d7673
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,192 @@
+#
+# Makefile for compiling insserv tool
+#
+# Author: Werner Fink,  <werner@suse.de>
+#
+
+INITDIR  =     /etc/init.d
+INSCONF  =     /etc/insserv.conf
+#DESTDIR =     /tmp/root
+#DEBUG  =      -DDEBUG=1 -Wpacked
+DEBUG   =
+ISSUSE  =      -DSUSE
+DESTDIR         =
+VERSION         =      1.12.0
+DATE    =      $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
+
+#
+# Architecture
+#
+ifdef RPM_OPT_FLAGS
+         COPTS = -g $(RPM_OPT_FLAGS)
+else
+          ARCH = $(shell uname -i)
+ifeq ($(ARCH),i386)
+         COPTS = -g -O3 -mcpu=i586 -mtune=i686
+else
+         COPTS = -g -O2
+endif
+endif
+        CFLAGS = -W -Wall $(COPTS) $(DEBUG) $(LOOPS) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \
+                 $(ISSUSE) -DINITDIR=\"$(INITDIR)\" -DINSCONF=\"$(INSCONF)\" -pipe
+         CLOOP = -falign-loops=0
+       LDFLAGS = -Wl,-O,3,--relax
+          LIBS =
+ifdef USE_RPMLIB
+        CFLAGS += -DUSE_RPMLIB=1
+       LDFLAGS += -Wl,--as-needed
+          LIBS += -lrpm
+endif
+            CC = gcc
+            RM = rm -f
+         MKDIR = mkdir -p
+         RMDIR = rm -rf
+   INSTBINFLAGS = -m 0700
+       INSTBIN = install $(INSTBINFLAGS)
+   INSTSRPFLAGS = -m 0700
+       INSTSRP = install $(INSTSRPFLAGS)
+   INSTDOCFLAGS = -c -m 0444
+       INSTDOC = install $(INSTDOCFLAGS)
+   INSTCONFLAGS = -c -m 0644
+       INSTCON = install $(INSTDOCFLAGS)
+          LINK = ln -sf
+#
+       SDOCDIR = $(DESTDIR)/usr/share/man/man8
+       SBINDIR = $(DESTDIR)/sbin
+       CONFDIR = $(DESTDIR)/etc
+        LSBDIR = $(DESTDIR)/lib/lsb
+      USRLSBDIR = $(DESTDIR)/usr/lib/lsb
+
+#
+# Determine if a library provides a specific function
+# Fist argument is the function to test, the second
+# one is the library its self.
+#
+         CTEST = $(CC) -nostdinc -fno-builtin -o /dev/null -xc
+    cc-function = $(shell printf 'void *$(1)();\nint main(){return($(1)(0)?0:1);}'|$(CTEST) - -l$(2:lib%=%) > /dev/null 2>&1 && echo $(1))
+
+#
+# The rules
+#
+
+TODO   =       insserv insserv.8
+
+all:           $(TODO)
+
+insserv:       insserv.o listing.o
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+listing.o:     listing.c listing.h config.h .system
+       $(CC) $(CFLAGS) $(CLOOP) -c $<
+
+insserv.o:     insserv.c listing.h config.h .system
+       $(CC) $(CFLAGS) $(CLOOP) -c $<
+
+listing.h:     .system
+
+config.h:      ADRESSES  = ^\#\s*if\s+defined\(HAS_[[:alnum:]_]+\)\s+&&\s+defined\(_ATFILE_SOURCE\)
+config.h:      FUNCTIONS = $(shell sed -rn '/$(ADRESSES)/{ s/.*defined\(HAS_([[:alnum:]_]+)\).*/\1/p; }' listing.h)
+config.h:      listing.h
+       @echo '/* Generated automatically by running make -- do not edit */'  > config.h
+       @echo '#ifndef CONFIG_H' >> config.h
+       @echo '#define CONFIG_H' >> config.h
+       @for def in $(foreach func,$(FUNCTIONS),$(call cc-function,$(func),libc)); do \
+           echo "#define HAS_$$def"; \
+        done >> config.h
+       @echo '#endif' >> config.h
+
+ifeq ($(ISSUSE),-DSUSE)
+insserv.8:     insserv.8.in .system
+       sed -r '\!@@(ELSE|NOT)_SUSE@@!,\!@@END_SUSE@@!d;\!@@(BEGIN|END)_SUSE@@!d' < $< > $@
+else
+insserv.8:     insserv.8.in .system
+       sed -r '\!@@BEGIN_SUSE@@!,\!@@(ELSE|END)_SUSE@@!d;\!@@(NOT|END)_SUSE@@!d' < $< > $@
+endif
+
+.system:       SYSTEM=$(shell cat .system 2> /dev/null)
+.system:       .force
+       @test "$(SYSTEM)" = "$(ISSUSE)$(DEBUG)" || echo "$(ISSUSE)$(DEBUG)" > .system
+
+.force:
+
+.PHONY:                clean
+clean:
+       $(RM) *.o *~ $(TODO) config.h .depend.* .system
+
+ifneq ($(MAKECMDGOALS),clean)
+
+-include       .depend.listing .depend.insserv
+
+.depend.listing::      listing.c listing.h
+       @$(CC) $(CFLAGS) -M listing.c >$@ 2>/dev/null
+
+.depend.insserv::      insserv.c listing.h
+       @$(CC) $(CFLAGS) -M insserv.c >$@ 2>/dev/null
+
+endif
+
+install:       $(TODO)
+       $(MKDIR)   $(SBINDIR)
+       $(MKDIR)   $(SDOCDIR)
+       $(MKDIR)   $(CONFDIR)
+ifeq ($(ISSUSE),-DSUSE)
+       $(MKDIR)   $(LSBDIR)
+       $(MKDIR)   $(DESTDIR)/usr/lib
+       $(MKDIR)   $(USRLSBDIR)
+endif
+       $(INSTBIN) insserv        $(SBINDIR)/
+       $(INSTDOC) insserv.8      $(SDOCDIR)/
+       $(INSTCON) insserv.conf   $(CONFDIR)/
+ifeq ($(ISSUSE),-DSUSE)
+       $(INSTCON) init-functions $(LSBDIR)/
+       $(INSTSRP) install_initd  $(USRLSBDIR)/
+       $(INSTSRP) remove_initd   $(USRLSBDIR)/
+endif
+
+#
+# Make distribution
+#
+FILES  = README         \
+         COPYING        \
+         CHANGES        \
+         Makefile       \
+         listing.c      \
+         listing.h      \
+         insserv.8.in   \
+         insserv.c      \
+         insserv.conf   \
+         init-functions \
+         remove_initd   \
+         install_initd  \
+         tests/suite    \
+         insserv-$(VERSION).lsm
+
+dest:  clean
+       $(MKDIR) insserv-$(VERSION)/tests
+       @echo -e "Begin3\n\
+Title:         insserv tool for boot scripts\n\
+Version:       $(VERSION)\n\
+Entered-date:  $(DATE)\n\
+Description:   Used for enabling of installed boot scripts\n\
+x              by scanning comment headers which are LSB conform.\n\
+Keywords:      boot service control, LSB\n\
+Author:                Werner Fink <werner@suse.de>\n\
+Maintained-by: Werner Fink <werner@suse.de>\n\
+Primary-site:  sunsite.unc.edu /pub/Linux/system/daemons/init\n\
+x              @UNKNOWN insserv-$(VERSION).tar.gz\n\
+Alternate-site:        ftp.suse.com /pub/projects/init\n\
+Platforms:     Linux with System VR2 or higher boot scheme\n\
+Copying-policy:        GPL\n\
+End" | sed 's@^ @@g;s@^x@@g' > insserv-$(VERSION).lsm
+       for file in $(FILES) ; do \
+           case "$$file" in \
+           tests/*) cp -p $$file insserv-$(VERSION)/tests/ ;; \
+           *)       cp -p $$file insserv-$(VERSION)/ ;; \
+           esac; \
+       done
+       tar -cps -zf  insserv-$(VERSION).tar.gz insserv-$(VERSION)/
+       $(RMDIR)    insserv-$(VERSION)
+       set -- `gzip -l insserv-$(VERSION).tar.gz | tail -1` ; \
+       sed "s:@UNKNOWN:$$1:" < insserv-$(VERSION).lsm > \
+       insserv-$(VERSION).lsm.tmp ; \
+       mv insserv-$(VERSION).lsm.tmp insserv-$(VERSION).lsm
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..af199e3
--- /dev/null
+++ b/README
@@ -0,0 +1,34 @@
+   Install
+   =======
+
+Edit the Makefile (set INITDIR to the path of the
+boot scripts used by the system during boot time),
+type `make' and `make install'.
+
+   Downloading latest version
+   ==========================
+
+The latest version of the insserv source is available from
+<URL: ftp://ftp.suse.com/pub/projects/init/ >.
+
+   Processes controlling
+   =====================
+
+This small package provides a tool for process controlling
+in System V boot scripts.
+
+The syntax is simple:
+
+   insserv
+
+   insserv etc/init.d
+
+   insserv etc/init.d/myscript
+
+See manual page for more information.
+
+
+Happy booting,
+
+       Werner Fink
+
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644 (file)
index 0000000..e3049c0
--- /dev/null
@@ -0,0 +1,45 @@
+Dependency based boot sequencing is the default in Debian.  The
+insserv program is used by sysv-rc to order init.d scripts based on
+their declared dependencies.
+
+An experimental feature to run init.d scripts in parallel is also
+available.  Use the CONCURRENCY setting in /etc/default/rcS to
+enable it.
+
+In short:
+
+  # Enable parallel booting
+  echo CONCURRENCY=makefile >> /etc/default/rcS
+
+  # Ready to reboot
+  shutdown -r now
+
+The next boot should then start services in parallel, as early as
+possible during the boot process based on the dependency information
+provided.
+
+The 'makefile' style concurrency depend on complete and correct
+dependencies in all init.d scripts.  There is a simpler and less
+strict style 'startpar', which only require all scripts with the same
+sequence number to be able to run in parallel, and thus accept
+incomplete dependencies as long as the boot sequence number is OK.
+
+To monitor the boot sequence, the bootchart project is a good choice.
+Debian packages are available in etch and sid.  The project itself is
+available from <URL:http://www.bootchart.org/>.
+
+Background info on alternative boot systems in Debian is available
+from
+<URL:http://alioth.debian.org/docman/view.php/30730/38/debconf2-initscripts-bkg.pdf>.
+
+Information on the LSB initscript comment convention is available from
+<URL:http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html>,
+<URL:http://wiki.debian.org/LSBInitScripts> and
+<URL:http://wiki.debian.org/LSBInitScripts/DependencyBasedBoot>.
+
+Information on an alternative approach to parallelism during boot is
+available from
+<URL:http://www-128.ibm.com/developerworks/linux/library/l-boot.html>.
+
+A tool to detect cycles is available from Adam Jensen using the git
+repository <URL:http://linuxguy.org/git/initcycle.git>.
diff --git a/debian/README.source b/debian/README.source
new file mode 100644 (file)
index 0000000..813fafb
--- /dev/null
@@ -0,0 +1,16 @@
+This package uses quilt to manage all modifications to the upstream
+source. Changes are stored in the source package as diffs in
+debian/patches and applied during the build.
+
+To get the fully patched source after unpacking the source package, cd
+to the root level of the source package and run:
+
+    debian/rules patch
+
+Removing a patch is as simple as removing its entry from the
+debian/patches/series file, and please also remove the patch file
+itself.
+
+To clean up afterwards again, "debian/rules unpatch" will do the
+work for you - or you can of course choose to call
+"fakeroot debian/rules clean" all together.
diff --git a/debian/bash-completion b/debian/bash-completion
new file mode 100644 (file)
index 0000000..68c0ef3
--- /dev/null
@@ -0,0 +1,36 @@
+# insserv(8) completion
+#
+# Copyright (c) 2009 Kel Modderman <kel@otaku42.de>
+#
+
+have insserv &&
+_insserv()
+{
+    local cur prev sysvdir services options
+
+    cur=`_get_cword`
+    prev=${COMP_WORDS[COMP_CWORD-1]}
+
+    [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d \
+       || sysvdir=/etc/init.d
+
+    services=( $(echo $sysvdir/!(README*|*.dpkg*|*.rpm@(orig|new|save))) )
+    services=( ${services[@]#$sysvdir/} )
+    options=( -c --config -d -f -n -o --override -p --path -r -v )
+
+    case "$prev" in
+       -c|--config)
+           _filedir
+           ;;
+       -o|--override|-p|--path)
+           _filedir -d
+           ;;
+       *)
+           COMPREPLY=( $( compgen -W '${options[@]} ${services[@]}' -- \
+               $cur ) )
+           ;;
+    esac
+
+    return 0
+} &&
+complete -F _insserv insserv
diff --git a/debian/bts-lefttoreport b/debian/bts-lefttoreport
new file mode 100644 (file)
index 0000000..b9121f6
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+basedir=$(dirname $0)
+
+ls $basedir/overrides |sort > bts-total.txt
+(cd $basedir/overrides ; egrep -l 'BTS|Already present' *) |sort> bts-reported.txt
+comm -23 bts-total.txt bts-reported.txt
+rm bts-total.txt bts-reported.txt
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..79bd45e
--- /dev/null
@@ -0,0 +1,1222 @@
+insserv (1.12.0-14+s2) unstable; urgency=low
+
+  * Revert "Lower the debconf compatibility level to 5 to enable
+    building under Scratchbox."
+  * Set myself as maintainer.
+
+ -- Rafal Krypa <r.krypa@samsung.com>  Wed, 14 Apr 2010 13:37:20 +0200
+
+insserv (1.12.0-14+s1) unstable; urgency=low
+
+  * Lower the debconf compatibility level to 5 to enable building under
+    Scratchbox.
+  * debian/control: replace the Uploaders field.
+
+ -- Rafal Krypa <r.krypa@samsung.com>  Fri, 29 Jan 2010 18:06:34 +0900
+
+insserv (1.12.0-14) unstable; urgency=low
+
+  * Remove obsolete rules targets missing-overrides, bin-by-inst.txt,
+    missingpkgs, missing-by-popcon and clean-extra.
+  * New patch 82_loop_exit_msg.patch to make exit message when a loop
+    is detected loop more like the exit messages when other problems
+    are detected.
+  * Make check-initd-order report missing provides header as errors
+    instead of printing perl warnings.
+  * New patch 62_upstart_job.patch implementing support for upstart
+    jobs (Closes: #547235).  Add testsuite test to ensure that it is
+    working.
+  * Refreshed all patches.
+  * New patch 96_hurd_no_at_funcs.patch to try harder to get the
+    source building on hurd, where for example the readlinkat() symbol
+    exist in libc but always fail.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 01 Oct 2009 19:58:44 +0200
+
+insserv (1.12.0-13) unstable; urgency=low
+
+  * New argument -b to check-initd-order, to be able to replace /etc/
+    with another directory.  This allow for easier testing of the script.
+  * Update update-rc.d-insserv to the one in sysv-rc svn.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 20 Sep 2009 21:58:11 +0200
+
+insserv (1.12.0-12) unstable; urgency=low
+
+  * Use dh_lintian during build.  Depend on debhelper (>= 6.0.7) for this.
+  * Correct wiki URL in README.Debian (Closes: #545171).  Thanks to
+    Josh Triplett for noticing the old URL.
+  * Make sure check-initd-order generated valid dotty files when
+    scripts provide strings with " in them (Closes: #545521).  Thanks
+    to Laurent Bonnaud for discovering the problem.
+  * Drop the Loading... messages from the default verbosity level, and
+    only show them when -v is used several times.
+  * Add script check-archive-initd-scripts to check all init.d scripts
+    in the Debian archive for consistency.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 13 Sep 2009 11:27:49 +0200
+
+insserv (1.12.0-11) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * Migrate the responsibility for enabling or disabling dependency
+    based boot sequencing from the insserv package to the sysv-rc
+    package.  Rewrite package description to reflect this (Closes:
+    #475478, #511753, #538959).  Keep a dummy update-bootsystem-insserv
+    script to avoid having to conflict with sysv-rc version 2.87dsf-2.
+    Keep update-rc.d-insserv to make it impossible for the update-rc.d
+    diversion to be a dangling link during upgrades.  Make it a copy
+    of update-rc.d from the new sysv-rc version to make sure both
+    behave the same way.  update-rc.d-insserv should be removed in
+    Squeeze+1.  update-bootsystem-insserv could be removed when
+    sysv-rc 2.87dsf-2 has been gone from unstable for 3 months.
+  * Drop dependencies on sysv-rc, initscripts and sysvinit-utils, and
+    leave it for sysv-rc to pull in the packages needed for dependency
+    based boot sequencing to work properly.
+  * Update README to reflect that dependency based boot sequencing is
+    now the default in Debian.  Drop reference to obsolete CONCURRENCY
+    setting (Closes: #540447).
+  * Add new test case test_override_remove trying to reproduce bug #540866.
+    No luck so far.
+  * Add new test case test_insserv_virt_loop to reproduce a bug
+    reported by Raphael Geissert, where an incorrect insserv.conf will
+    make insserv hang forever.  Add new patch 94_v1_12_2.patch from
+    upstream to fix it (Closes: #541613).
+  * Correct test test_early_all to fail if $all do not work with stop
+    sequences.  Add new patch 95_stop_all.patch from upstream to fix
+    it (Closes: #542043).
+  * Change the definition of $syslog to include rsyslog, sysklogd,
+    dsyslog, inetutils-syslogd  and syslog-ng, to include all syslog
+    implmenetations in the archive.  Dropped the syslog provide from
+    the list, as it should not be used.
+  * Update to Standards-Version 3.8.3, no changes required.
+  * Add lintian override for the transitient update-bootsystem-insserv
+    binary missing a manual page.
+  * Add new test test_local_virtual to verify that local virtual
+    facilities work properly.
+
+  [ Kel Modderman ]
+  * Add new patch 20_install_perms_fixup.patch to install binary and
+    conffile with correct permissions.
+  * Add new patch 21_tests_suite_new_functions.patch to add a couple
+    of new test suite functions to upstream test suite.
+  * Make sure update-rc.d compares command line parameters for start/stop
+    runlevel configuration with the Default-Start and Default-Stop values in
+    LSB info comment of script and warns if there are differences.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 05 Sep 2009 11:50:22 +0200
+
+insserv (1.12.0-10) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * Change check-initd-order to return a exit code when there is a problem
+    with the boot sequence or dependencies.
+  * Change the default to enable dependency based boot sequencing if
+    it is safe to do.  This should enable it in the common case,
+    while avoiding conversion on problems.
+  * Move all code from insserv.config to insserv.postist and remove
+    insserv.config to make sure update-bootsystem-insserv is available
+    and working when it is needed to test if it is safe to migrate to
+    dependency based boot sequencing.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 26 Jul 2009 21:06:56 +0200
+
+insserv (1.12.0-9) unstable; urgency=low
+
+  * Adjust patch 71_complete_makefile to make sure the recursion depth
+    calculation is done correctly in expand_faci().
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 23 Jul 2009 20:41:24 +0200
+
+insserv (1.12.0-8) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * Refresh 92_m68k_alignment.patch.
+  * Simplify test for bug #534526, while still triggering the bug.
+  * Change definition of $time to make hwclock optional, as it might
+    be dropped from the boot sequence in the future.
+  * New patch 71_complete_makefile from upstream fixing .depend.*
+    content when processing virtual facility definitions refering to
+    other virtual facilities (Closes: #534526).
+
+  [ Kel Modderman ]
+  * Before inserting an initscript with insserv, check that
+    /etc/init.d/<basename> exists in update-rc.d-insserv.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed, 22 Jul 2009 23:53:05 +0200
+
+insserv (1.12.0-7) unstable; urgency=low
+
+  * Update standards-version from 3.8.1 to 3.8.2.  No changes needed.
+  * Fix wrong quote char in insserv(8) manual page.
+  * Add required trailing slash to Vcs-Browser URL.
+  * Improve package description to make it more obvious that insserv
+    is not activated when installed.
+  * Depend on sysvinit-utils (>= 2.86.ds1-62) to get a version of
+    startpar that keep working even when /dev/pts is not yet mounted.
+  * Depend on the initscripts version we want (>= 2.86.ds1-63)
+    (instead of conflicting with the version we do not want which can
+    give upgrade problems), to get one with the X-Interactive flags
+    set in the scripts.  Drop hostname, mountkernfs, mountdevsubfs,
+    checkroot and checkfs from the list of interactive scripts.
+  * New patch 91_kfreebsd_nofadvice.patch trying to get the source
+    building on kfreebsd.
+  * New patch 92_m68k_alignment.patch trying to get the source
+    building on m68k (Closes: #493637).
+  * New patch 93_hurd_no_path_max.patch trying to get the source
+    building on hurd.  Need a better one.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed, 01 Jul 2009 00:17:13 +0200
+
+insserv (1.12.0-6) unstable; urgency=low
+
+  * Add keyboard-setup, console-setup, cryptdisks, cryptdisks-early
+    and checkfs-loop as interactive scripts while we wait for scripts
+    to use X-Interactive: true as documented in bug #458224 (Closes:
+    #510517, #534711).
+  * Fix typo in testsuite function initdir_purge(), making sure the
+    rc?.d directories are removed during purge.
+  * Add new patch introducing a new keyword 'X-Interactive: true' in
+    the LSB header (Closes: #458224).  Add test suite to verify that
+    it is working.
+  * Add DM-Upload-Allowed: yes header to allow my co-maintainer to
+    upload this package.
+  * Add testcase for incomplete .depend.boot file based on test
+    created by Raphael Geissert for bug #534526.  Make this a
+    non-fatal error in production builds while we figure out what is
+    wrong.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri, 26 Jun 2009 20:18:36 +0200
+
+insserv (1.12.0-5) unstable; urgency=low
+
+  [ Kel Modderman ]
+  * Convert dpatches to quilt series and adjust debian/rules and
+    debian/control.
+  * Refresh debian/patches/10_nosuse.patch to apply without fuzz.
+  * Add debian/patches/70_req_start_all_depends.patch to correct
+    dependency information written to .depend.* files for scripts which
+    declare Required-Start: $all. Thanks to upstream developer Werner
+    Fink for giving us th heads up about this problem and patch.
+  * Add Japanese translation. Thanks Hideki Yamane. (Closes: #512858)
+  * Add Swedish translation. Thanks Martin Bagge. (Closes: #503603)
+  * Add debian/manpages and call dh_installman without specific
+    arguments in debian/rules.
+  * Depend on debhelper >= 6 and use compat level of 6.
+  * Update to Standards-Version 3.8.1 without any required changes.
+  * Add Homepage field to debian/control.
+  * Add debian/patches/80_manual_warnings.patch to correct format,
+    spelling and grammar errors in manual page.
+  * Add debian/patches/90_no_runlevel_spec_for_debian.patch to remove
+    reference to known runlevels on Debian systems. These should be
+    defined in Debian policy. (Closes: #500542)
+  * Add interface to disable|enable service symlinks for all Default-
+    Start runlevels or those specified on the command line. This is
+    analogous to the interface introduced to update-rc.d of 2.86.ds1-62.
+  * Make sure disable|enable action does not call insserv if it did not
+    alter any runlevel symlinks.
+  * Consolidate debian/insserv.dirs into debian/dirs, only one should
+    exist.
+  * Add debian/bash-completion and install it to /etc/bash_completion.d/
+    to enhance usability for bash shell users.
+  * When arguments to start/stop/defaults action are given to update-
+    rc.d wrapper, emit a warning that the LSB information of script
+    overrides the given arguments.
+  * Improve the way in which update-rc.d disable/enable function
+    determines index of S or K bit of runlevel symlink by using rindex
+    instead of a hardcoded index.
+  * Improve update-rc.d enable/disable function for when an unhandled
+    runlevel is given as argument.
+  * Also look in /usr/share/insserv/overrides/ when performing
+    disable/enable function in update-rc.d.
+
+  [ Petter Reinholdtsen ]
+  * Make a note in the usage text that update-rc.d disable and enable
+    API is not yet set in stone.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Tue, 23 Jun 2009 08:19:19 +0200
+
+insserv (1.12.0-4) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * New test test_early_all to control that $all only affect start or
+    stop sequences.  Trying to reproduce issue reported in #485307.
+
+  [ Kel Modderman ]
+  * Add 60_all_keyword_start_only.dpatch to prevent Required-Stop: $all
+    from modifying start link sort order. (Closes: #499721)
+  * Make test_early_all() test suite function unconditionally fatal,
+    this is an importan bug fixed by 60_all_keyword_start_only.dpatch.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 25 Sep 2008 20:36:10 +0200
+
+insserv (1.12.0-3) unstable; urgency=low
+
+  [ Kel Modderman ]
+  * test_fake_loop() and test_fake_loop_reverse() are now unconditionally fatal
+    tests because they pass with insserv >= 1.12.0.
+  * Modify 10_nosuse.dpatch to define ISSUSE as -DNOTSUSE instead of unsetting
+    it, to avoid fooling the build system.
+  * Purge the rc symlinks in initddir_purge() function of testsuite-common.
+  * Add a remscript() function to testsuite-common for deleting initscripts
+    from test init.d/ directory.
+  * Add test_all_keyword() function to run-testsuite to observe the
+    semantics of using the $all keyword. It is currently a non-fatal
+    test.
+  * Add test_script_in_runlevel() function to expose segfault reported
+    in #493202.
+  * Add 40_badboy_segfault.dpatch to fix segfault when scriptname()
+    function of insserv does not return script name due to script in
+    runlevel directory not being a symlink (or corrupt). (Closes: #493202)
+  * Add 50_symlink_in_initddir.dpatch to defend aginst symlinks
+    installed to /etc/init.d/ that point to other scripts in
+    /etc/init.d/, causing insserv to fail due to duplicate provides.
+    (Closes: #485045)
+  * Extend test_initd_symlink() test suite case to handle cases which
+    50_symlink_in_initddir.dpatch must handle.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 20 Sep 2008 21:31:55 +0200
+
+insserv (1.12.0-2) unstable; urgency=low
+
+  [ Kel Modderman ]
+  * Make test_duplicate_provides() test case more realistic by placing
+    initscripts in init.d dir before registering with insserv. Make sure first
+    script is registered.
+  * Add test_deterministic_order() test function to make sure that when two or
+    more initscripts provide the same facility, the first script actually can
+    be registered with insserv reliably.
+  * Add 30_deterministic_order.dpatch to defend against the inconsistent
+    directory stream sequence returned by readdir(3) under different
+    circumstances. (Closes: #494514)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed, 20 Aug 2008 21:08:13 +0200
+
+insserv (1.12.0-1) unstable; urgency=low
+
+  [ Kel Modderman ]
+  * New upstream version.
+    - preserve empty runlevel configurations, override adding or removoval of
+      existing start/top runlevel configration (Closes: #477415, #492526)
+  * Discard patches applied to or no longer relevant to new upstream:
+    - 11_more_warnings.dpatch
+    - 32_debug_option.dpatch
+    - 33_nosuse_scripts.dpatch
+    - 40_segfault_virtprov.dpatch
+    - 41_cleansystem.dpatch
+    - 42_loopnochangemsg.dpatch
+    - 50_sign_warning.dpatch
+    - 51_overwrite_output.dpatch
+    - 52_shutdown_links.dpatch
+    - 60_disable_cfgfilter_stat.dpatch
+    - 62_warn_on_missing_required_fields.dpatch
+    - 63_warn_on_missing_default_fields.dpatch
+    - 64_missing_default_fields_fallback.dpatch
+  * Discard patches not applied in series:
+    - 32_debug_option.dpatch
+    - 34_debian_fixedscripts.dpatch
+  * Refresh patches that still apply to new upstream:
+    - 10_nosuse.dpatch
+    - 31_debian_conf.dpatch
+  * Add an extra call to list_rclinks() in test_newbug_keepoldorder()
+    function of run-testsuite, after introducing the bug.
+  * Make test_adding_start() and test_adding_stop() run-testsuite
+    functions unconditionally fatal on failure.
+  * Make test_bogus_facility() run-testsuite function non-fatal.
+  * Mark tests that are currently failing with a comment in run-testsuite.
+  * Add test_removing_start() and test_removing_stop() to run-testsuite,
+    showing that insserv will preserve existing links when script header is
+    unproperly replaced with empty Default-Start or Default-Stop.
+  * Make test_adding_start() case a more realistic example.
+  * Make test_incorrect_stopscripts() a fatal test, insserv should not
+    add shutdown links when none are present.
+  * Make test_newbug_keepoldorder() test case non-fatal, the fact that it
+    passed before was not by design but by luck, as per upstream analysis
+    which is included with test code.
+  * Handle CFLAGS in debian/rules more consistently, different options were
+    passed to make in build and install targets, and dpkg now also tampers
+    with the variable.
+  * Remove a bunch of overrides for scripts now with valid LSB information in
+    testing distribution today, or have been removed from archive.
+  * Add common test suite function for purging init directory, runlevel links
+    and dependency makefiles.
+  * Add test_incorrect_startscripts() to replicate bug report described in
+    #492526, and make sure insserv do not regress in this behaviour.
+  * Now we have no overrides to install by default, but we may in future,
+    modify debian/rules to only install overrides from ./debian/overrides/* if
+    they are present, but not fail otherwise.
+  * Add test_initd_symlink() test suite function to test if illegal
+    symlinks in /etc/init.d/ cause problems.
+  * Bump Standards Version to 3.8.0, add debian/README.source to describe patch
+    system to conform. No other changes required.
+  * Add myself to Uploaders.
+  * Rename 31_debian_conf.dpatch to 11_debian_conf.dpatch, to keep
+    Debian port patches in tight sequence.
+
+  [ Petter Reinholdtsen ]
+  * Mention initcycle tool from Adam Jensen in README.Debian.
+  * Adjust test_initd_symlink test to accept the first insertion
+    and reject the second, as both scripts have the same provide.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed, 30 Jul 2008 18:18:00 +0200
+
+insserv (1.11.0-9) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * New test case to demonstrate the bug reported in #477415.
+  * Include empty directories /etc/insserv.conf.d and
+    /etc/insserv/overrides in the package, to get dpkg to warn about
+    content there when purging insserv (Closes: #471237).
+  * Debconf translations:
+    - Updated German from Erik Schanze (Closes: #479254).
+
+  [ Kel Modderman ]
+  * Add patch 60_disable_cfgfilter_stat to remove stat check from the
+    callback function that filters the scanning of /etc/insserv.conf.d/ dir
+    for confiuration file snippets. Instead do stat check in scan_conf().
+  * New test case to show that two initscripts cannot have the same Provides
+    field.
+  * New test case exposing ability to insert a script into runlevel
+    configuration that depends on virtual facility that is not provided or
+    does not exist.
+  * New test case to check that /etc/insserv.conf.d/ can be used to allow one
+    or more services to define and provide a virtual facility.
+  * Ensure custom insserv.conf.d/* files are cleaned after
+    test_insserv_conf_d() in run-testsuite.
+  * Add test_onlystart() test case to check we can insert scripts with empty
+    stop runlevel configuration.
+  * Add test_broken_header() test case to show it seems possible to insert a
+    script missing Required-{Start,Stop} lsb info fields.
+  * Add test_no_default_start() to show that it seems possible to insert script
+    missing Default-Start field.
+  * Add test_no_default_stop() to show that it seems possible to insert script
+    missing Default-Stop field, and that links are created in stop runlevels.
+  * Add 62_warn_on_missing_required_fields and
+    63_warn_on_missing_default_fields to enable warnings by default about
+    missing Provides, Required-Start, Required-Stop, Default-Start or
+    Default-Stop  LSB comment keywords.
+  * Add a note to new patches to relate them to a case function of the test
+    suite.
+  * Add 64_missing_default_fields_fallback to ensure sane fallback of
+    empty runlevel configuration is used for scripts missing Default-
+    Start or Default-Stop lsb keywords.
+  * Add test_noprovides_header() to show that it is possible to insert script
+    missing Provides keyword, and many warnings are exposed as a result.
+  * Add test_adding_start() to expose that adding start levels uncleanly
+    modifies on disk configuration. Give test_adding_start and
+    test_adding_stop test script unique names.
+
+  [ Petter Reinholdtsen ]
+  * Made test_adding_start and test_adding_stop checks non-fatal for
+    production builds, as this problem is no regression from earlier versions.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 25 May 2008 21:46:04 +0200
+
+insserv (1.11.0-8) unstable; urgency=low
+
+  * Make sure the consistency check in update-bootsystem-insserv
+    report all problems and not only the first one.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Mon, 24 Mar 2008 23:32:22 +0100
+
+insserv (1.11.0-7) unstable; urgency=low
+
+  * Added override files for digitools and ddns3-client.
+  * Make sure the dependency based update-rc.d check the argument list
+    slightly, to avoid bugs like #470062.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 13 Mar 2008 13:54:31 +0100
+
+insserv (1.11.0-6) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * Added override files for at, fiaif, gom, ifupdown-scripts-zg2 and tspc.
+  * Correct typo in override file for lvm2.
+  * Changed postinst and update-bootsystem-insserv to remove the
+    generated files /etc/init.d/.depend.* when disabled or removed.
+  * Implemented better support in check-initd-orderfor graphing $all
+    relations.
+  * Restructure update-bootsystem-insserv slightly to make it possible
+    to check if it is safe to convert to dependency based boot
+    sequencing without doing the conversion.
+  * Updated 31_debian_conf to list glibc, hostname and keymap as interactive
+    scripts, as none of them can use a pseudoterminal.
+  * Add two new tests to verify that x-start-before and x-stop-after
+    work as they should.
+  * Debconf translations:
+    - Added Spanish from Steve Lord Flaubert (Closes: #467391).
+    - Added German from Erik Schanze (Closes: #467483).
+    - Added Dutch from Bart Cornelis (Closes: #467418).
+
+  [ Kel Modderman ]
+  * Modify debian/insserv.config debconf script to honour a preseeded debconf
+    value enabling dependency based boot on first installation only.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun,  2 Mar 2008 18:00:02 +0100
+
+insserv (1.11.0-5) unstable; urgency=low
+
+  * Add test to verify that introducing a loop will not change the boot
+    sequence, but make insserv exit with an error.
+  * Added patch 42_loopnochangemsg to change the message printed when
+    a loop is detected, to let the user know that the boot sequence is
+    untouched.
+  * Added patch 52_shutdown_links to fix incorrecly inserted stop
+    symlinks (Closes: #464017).
+  * Added patch 53_debugoutput to provide more useful debug output
+    used to track down the stop symlink issues.  Not enabled by default.
+  * Debconf translations:
+    - Added Russian from Yuri Kozlov (Closes: #467164).
+    - Added Czech from Miroslav Kure (Closes: #467170).
+    - Added Italian from Luca Monducci (Closes: #467295).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 24 Feb 2008 23:49:12 +0100
+
+insserv (1.11.0-4) unstable; urgency=low
+
+  * Added override file for whitelister.
+  * Reinsert previously removed override file for lvm2 and others
+    while we wait for the packages in testing to be fixed (Closes:
+    #466700).  These should be removed when lenny is verified to have
+    headers in place.
+  * Debconf translations:
+    - Added French from Christian Perrier (Closes: #466345).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 21 Feb 2008 09:27:34 +0100
+
+insserv (1.11.0-3) unstable; urgency=low
+
+  * Rewrote patch debian/patches/40_segfault_virtprov.dpatch with a
+    solution provided by upstream.
+  * Added script debian/seq-changes from Frans Pop installed in
+    /usr/share/insserv/ to extract the sequence changes done by
+    insserv.
+  * New testsuite check to detect incorrectly inserted stop symlinks
+    when scripts with incorrect headers are encountered.
+  * Removed override file for snmptrapfmt, as the package now include
+    the LSB header.
+  * Removed override file save-etc-disk.  It is not present in Debian.
+  * Update the package description and debconf question text (Closes: #464109).
+  * New patch 11_more_warnings to activate more warning flags during
+    build.  Obsoletes setting the same flags in debian/rules.
+  * New patch 50_sign_warning getting rid of some signed/unsigned
+    compare issues.
+  * Update test suite to the one provided by Werner Fink.
+  * Extended test suite to report status at the end.
+  * New patch 32_debug_option to add new option -D to print debug
+    output.
+  * New patch 33_nosuse_scripts to disable some SUSE specific settings.
+  * New patch 51_overwrite_output to improve output when symlinks on
+    disk do not match the default-* headers.
+  * Added override file for slashem-common.
+  * New patch 41_cleansystem to clean the .system file.  Changed rules
+    file to make sure it take effect.
+  * Change test suite to use /bin/bash, as it uses bash-features.
+  * Debconf translations:
+    - Added Galician from Jacobo Tarrio (Closes: #465067).
+    - Added Vietnamese from Clytie Siddall (Closes: #465437).
+    - Added Portugese from Américo Monteiro  (Closes: #465519).
+    - Added Finnish from Esko Arajärvi (Closes: #465800).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 17 Feb 2008 13:54:03 +0100
+
+insserv (1.11.0-2) unstable; urgency=low
+
+  * Changed patch 31_debian_conf to accept rsyslog and syslog-ng as
+    implementations for the $syslog facility.
+  * Added test case to detect insserv crashing when it find scripts
+    providing virtual system facilities.
+  * Changed update-bootsystem-insserv to refuse to enable dependency
+    based boot sequencing when a script provide a virtual system
+    facility.
+  * Changed patch 10_nosuse.dpatch to make sure we build with -g.
+  * Added patch debian/patches/40_segfault_virtprov.dpatch to avoid
+    segfault when finding an enabled script that provide a virtual
+    system facility.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri,  1 Feb 2008 09:24:10 +0100
+
+insserv (1.11.0-1) unstable; urgency=low
+
+  * New upstream version.
+    - Drop patches 20_path_at_runtime, 21_overrides, 32_debian_nolsb,
+      33_debian_localok, 38_debuginfo, 40_nosusescript,
+      41_debiandefault, 42_redundantlvl, 43_shutdown,
+      44_reportloopmemb, 45_loopsarefatal and 46_complete_removal
+      merged upstream.
+    - Updated insserv(8) manual page for Debian (Closes: #462064).
+    - Correct path to insserv.conf in test suite to keep it working.
+    - A lot faster (Closes: #462211).
+  * New example script make-testsuite useful to generate a test script
+    demonstrating a problem.
+  * Added override files for guidedog and puppet.
+  * Removed override file for atd and lvm2, as the packages now include
+    the LSB header.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 31 Jan 2008 09:05:07 +0100
+
+insserv (1.10.0-6) unstable; urgency=low
+
+  * Implement support for preseeding insserv, to make it possible to
+    enable it at install time.  This only work the first time the
+    package is installed and config is executed when
+    /usr/sbin/update-rc.d-insserv does not exist yet.
+  * Changed check-initd-order to load virtual facilities from
+    /etc/insserv.conf (Closes: #459522)
+  * Extended testsuite to more closely match real Debian for the
+    shutdown sequence.
+  * New patch 46_complete_removal.dpatch to make sure all symlinks are
+    removed on removal (Closes: #460034).  Based on patch from Kel
+    Modderman.  Made failing removal test fatal.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 19 Jan 2008 14:45:27 +0100
+
+insserv (1.10.0-5) unstable; urgency=low
+
+  * Made sure to initialize the badstate variable before it is used in
+    update-bootsystem-insserv.
+  * Removed override files for uptimed and uptimed.sh, as the uptimed
+    package now include the LSB headers.
+  * Make sure to give a proper error message when failing to enable
+    dependency based boot system and insserv return an error code
+    (Closes: #461141).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed, 16 Jan 2008 23:29:09 +0100
+
+insserv (1.10.0-4) unstable; urgency=low
+
+  * Made problematic test cases for bug #460034 and #458582 fatal
+    in testing and non-fatal when uploading.
+  * Added override files for bastille-firewall.
+  * Do not warn about obsolete init.d scripts that have been removed
+    (Closes: #461073).  Patch from Kel Modderman.
+  * Provide more information when convertion to dependency based boot
+    sequencing can not be done.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed, 16 Jan 2008 22:00:50 +0100
+
+insserv (1.10.0-3) unstable; urgency=low
+
+  * Added test case for problem with symlink removal, bug #460034.
+  * Added override files for uptimed, uptimed.sh and guarddog.
+  * Removed override file nfs-user-server as the compiled in defaults
+    are better than the proposed overrides.
+  * Add mountoverflowtmp to virtual facility $local_fs, to make sure
+    /tmp/ is always mounted before the scripts needing /tmp/ is
+    started.  Conflict with initscripts before 2.86.ds1-48, to avoid a
+    dependency loop with this change.
+  * Make debconf question translatable (Closes: #386703).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 13 Jan 2008 19:32:34 +0100
+
+insserv (1.10.0-2) unstable; urgency=low
+
+  * Implement new check-initd-order option -c to be used with -g to
+    generate a combined graph for boot and shutdown dependencies.
+  * Split test suite into two files, one generic part
+    (testsuite-common) and one Debian specific part (run-testsuite).
+  * Remove ntpdate and ntp-server as optional dependencies for $time
+    as both are obsolete, and changing them to the current 'ntp' would
+    make a loop.
+  * Removed override file for resolvconf and laptop-netconf, as the
+    unstable packages got the header now.
+  * Removed override file for devmapper, as the unstable packages no
+    longer include a init.d script
+  * Remove reference to lwresd in headers-reported, as the unstable
+    package got the header now.
+  * Added override files for the console-cyrillic and
+    gibraltar-bootsupport package.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed,  9 Jan 2008 22:42:31 +0100
+
+insserv (1.10.0-1) unstable; urgency=low
+
+  * New upstream version released 2007-10-10.
+    - Updated patches 10_nosuse, 20_path_at_runtime, 21_overrides and
+      43_shutdown to apply on the new version.
+    - Removed patch 11_revdepend as it is included upstream.
+  * In graphs, name scripts without provides header, and scripts
+    without LSB header, using the name of the file in /etc/init.d/.
+    This make it easier to spot loops involving these scripts.
+  * Added override file for hpoj.
+  * Ask if insserv should be activated at install time, using a medium
+    priority debconf question.  The default is no.
+  * Restructure test script to work with new test feature implemented
+    in version 1.10.
+  * Update patch 42_redundantlvl to get rid of two compiler warnings.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Mon,  7 Jan 2008 23:37:53 +0100
+
+insserv (1.09.0-14) unstable; urgency=low
+
+  * Changed patch 21_overrides to only warn once about scripts without
+    LSB header, to reduce the noise.
+  * Changed patch 21_overrides to speed up processing by only reading
+    override default files only when the script is lacking an LSB header.
+  * Moved default dependency values from patch 21_overrides to
+    41_debiandefault where it belong.
+  * New test to check that scripts introducing a loop (or a fake loop,
+    see bug #458582) will refuse to install.
+  * New patch 45_loopsarefatal to make sure insserv considering all
+    kind of loops fatal, to not mess up the script sequences.
+  * Introduce very simple manual page for update-rc.d-insserv.
+  * Make failing 'make clean' fatal, as it should always work.
+  * Change debconf template text to make it easier to understand.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun,  6 Jan 2008 09:37:43 +0100
+
+insserv (1.09.0-13) unstable; urgency=low
+
+  * Update patch 21_overrides to fix bug in override handling.  Now a
+    header in a script or override file complete replaces previously
+    loaded headers.
+  * Add test to check and verify that override files in
+    /etc/insserv/override replaces headers in the scripts in
+    /etc/init.d/, and made previously failing loop breaking test
+    fatal, as it is working with the fixed override patch.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri,  4 Jan 2008 12:25:55 +0100
+
+insserv (1.09.0-12) unstable; urgency=low
+
+  * New patch 34_debian_fixedscripts to hardcode a few script sequence
+    numbers, to let the generated boot sequence be more like the
+    original one.  Modified 40_nonsusescripts to no longer disable the
+    setlsb() function.  This patch is not enabled by default, as it is
+    not obvious that it is a good idea.
+  * Added override files for hostname.dhcp and mountfix.
+  * Adjust override file for lvm2, to provide both lvm2 and lvm, to
+    make it easier until the lvm provide is dropped.
+  * Adjust override file for lvm2 to use reverse depend on checkfs,
+    mountall and umountfs to make it possible to drop lvm relations
+    from initscripts.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri,  4 Jan 2008 01:38:00 +0100
+
+insserv (1.09.0-11) unstable; urgency=low
+
+  * Added test to demonstrate the fake loop warning issue (bug
+    #458582).
+  * Implemented support for non-fatal tests in the testsuite.
+  * Added override file for dmraid, scsitools-pre.sh and scsitools.sh.
+  * Added patch 44_reportloopmemb to make loop reporting code in
+    insserv more helpful, and make sure to report the extended loop
+    output in update-bootsystem-insserv when refusing to switch to
+    dependency based boot (Closes: #458683).
+  * Move code to divert update-rc.d from postinst to
+    update-bootsystem-insserv, to make sure both ways to activate
+    insserv are equivalent.
+  * Extended check-initd-order to graph services with multiple
+    provides as two nodes that depend on each other, and which ahve
+    the same dependencies.
+  * Changed update-bootsystem-insserv to call 'reset' after looping
+    over packages postinst scripts, in case the terminal is messed up
+    as it is when I test it.
+  * Disabled check for reverse dependencies in check-initd-order.  It
+    does not to work properly, and gave false error reports.
+  * Removed flag file /etc/update-rc.d-insserv and use the update-rc.d
+    diversion as the flag to detect if insserv is enabled.  Adjustd
+    package removal and update-rc.d-insserv to reflect this.
+  * Added Vcs-Svn and Vcs-Browser info in control file, pointing to
+    the Debian packaging project.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed,  2 Jan 2008 18:41:31 +0100
+
+insserv (1.09.0-10) unstable; urgency=low
+
+  * Make sure to exit with an error code if it isn't safe to remove
+    the package.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Tue,  1 Jan 2008 21:12:24 +0100
+
+insserv (1.09.0-9) unstable; urgency=low
+
+  * Removed override file pptpd as the compiled in defaults are better
+    than the proposed overrides.
+  * Correct override file for laptop-netconf after checking the script
+    and the package.
+  * Added override file for racoon, and corrected override file for
+    setkey, after checking the scripts in the package.
+  * Try to make recovery routine more robust by not trying to run
+    non-existing postinst scripts, and only run postinst scripts for
+    packages with executable scripts in /etc/init.d/.
+  * Extended check-initd-order to check optional start dependencies,
+    and implement check of the shutdown sequence.
+  * Extended to check reverse dependencies too.
+  * Changed enabling code to refuse to convert to dependency based
+    boot sequence when obsolete init.d scripts are found, as these
+    tend to mess up the boot sequence.
+  * Changed enabling code to refuse to convert to dependency based
+    boot sequence if several scripts provide the same service.
+  * Added prerm code to refuse to be removed while enabled, to avoid
+    messing up the boot system completely.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Tue,  1 Jan 2008 21:08:14 +0100
+
+insserv (1.09.0-8) unstable; urgency=low
+
+  [ Petter Reinholdtsen ]
+  * Removed override files cpqarrayd, hotkey-setup and spamassassin as
+    they are equivalent with the defaults compiled into insserv.
+  * Removed override files courier-ldap, courier-authdaemon,
+    courier-imap-ssl and courier-imap, irqbalance and nethack-common
+    as the compiled in defaults are better than the proposed
+    overrides.
+  * Extended check-initd-order to graph reverse dependencies
+    (X-Start-Before and X-Stop-AFter).  Draw reverse dependencies in
+    yellow.
+  * Added patch 11_revdepend fetched from a review copy of version
+    1.10.  Modified 20_override to cope with the change.  Based on
+    changes from Werner Fink.
+  * Renamed patches 20_overrides to 21_overrides and
+    44_path_at_runtime to 20_path_at_runtime, to prepare for Otavios
+    extensions.
+
+  [ Otavio Salvador ]
+  * Extended patch 21_override to allow override path changing so the
+    unit test can use it.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Mon, 31 Dec 2007 19:26:00 +0100
+
+insserv (1.09.0-7) unstable; urgency=low
+
+  * Try to make it it easier to disabling the dependency based boot
+    sequencing by calling the postinst of all packages with init.d
+    scripts to  register the scripts again.
+  * Extend check-initd-order to handle the virtual dependecy $all.
+  * Reword the debconf question to try to make it clearer and
+    easier to understand.
+  * Minor cleanup in irqbalance and atd override file, only depend
+    on $remote_fs, no need to also depend on $local_fs.
+  * Update check-initd-order to use the same default dependencies
+    ($remote_fs $syslog) and the same virtual dependencies as insserv
+    when generating dotty graphs.
+  * Update check-initd-order to draw left-to-right dotty graphs.
+    Based on tip from Frans Pop and Trent Buck.
+  * Update lvm2 override to stop before umountroot.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 30 Dec 2007 18:48:47 +0100
+
+insserv (1.09.0-6) unstable; urgency=low
+
+  * Update patch 20_overrides to let scripts without an LSB header
+    depend on $syslog as well as $remote_fs.
+  * Add test case to check that scripts without LSB header is ordered
+    after syslog
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 30 Dec 2007 12:39:33 +0100
+
+insserv (1.09.0-5) unstable; urgency=low
+
+  * Update patch 44_path_at_runtime to include support for -c to point
+    to a local config file.  It is required for a proper test suite.
+  * Fix typo in test suite and extend it to check more scenarios.
+  * Use local config file when running test suite.
+  * Change $syslog virtual facility to depend on either syslog or
+    sysklogd.  The sysklogd script provide syslog and not the sysklogd
+    string that was requested in bug #324679.
+  * Update patch 31_debian_conf to list udev mountdevsubfs checkroot
+    checkfs console-screen as interactive scripts that should run
+    alone.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 30 Dec 2007 09:23:22 +0100
+
+insserv (1.09.0-4) unstable; urgency=low
+
+  * Update patch 20_overrides to add useful default values for scripts
+    without LSB header (Closes: #431697).
+  * Update patch 43_shutdown to handle scripts with both start and
+    stop levels.  (Closes: #452462).
+  * New patch 44_path_at_runtime to add new option -p to make it
+    possible to replace /etc/init.d with another path for testing.
+  * Add script debian/run-testsuite to test the generated order, and
+    use it during the build.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 29 Dec 2007 16:00:31 +0100
+
+insserv (1.09.0-3) unstable; urgency=low
+
+  * Update patch 40_nosusescript to disable unused function setlsb().
+  * Add sendsigs to the $remote_fs virtual facility, to make sure the
+    services depending on $remote_fs for the shutdown sequence are not
+    killed before their init.d script get a chance to stop them.
+  * New patch 43_shutdown to fix the handling of stop scripts and thus
+    the shutdown sequence (Closes: #452462).  Thanks to Otavio
+    Salvador for help with debugging and part of the patch.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 29 Dec 2007 00:20:04 +0100
+
+insserv (1.09.0-2) unstable; urgency=low
+
+  * New patch 10_nosuse to disable SUSE specific build.  This make
+    it easier to debug insserv.
+  * Update patch 40_nosusescript to remove SUSE-specific handling
+    of the halt and reboot script.
+  * Remove all override files for init.d scripts with LSB style
+    dependency headers (Closes: #386544).
+  * Update snmptrapfmt override file, making it more accurate.
+  * Updated standards-version from 3.7.2 to 3.7.3.  No changes needed.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Tue, 25 Dec 2007 14:24:26 +0100
+
+insserv (1.09.0-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #426091)
+    - Support X-Start-Before and X-Stop-After (Closes: #326120)
+    - Building with DEB_BUILD_OPTIONS=nostrip no longer strip the
+      binary. (Closes: #437210)
+  * Let /usr/share/insserv/check-initd-order read override files in
+    /etc/insserv/overrides/ just like insserv does.  Patch from Arjan
+    Oosting.  (Closes: #429398)
+  * Correct the dependencies for nbd-client and libnss-ldap.
+  * Add override file for spamassassin.
+  * Update watch file with new upstream URL. (Closes: #450044)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 17 Nov 2007 21:17:20 +0100
+
+insserv (1.08.0-14) unstable; urgency=low
+
+  * Correct the dependencies for hwclock.sh.
+  * Update libdevmapper*, raid2 and mdadm-raid by adding
+    module-init-tools as an alternative to modutils, and move
+    both from required-start to should-start, as either or both
+    might be available. (Closes: #432072)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Mon,  9 Jul 2007 13:40:36 +0200
+
+insserv (1.08.0-13) unstable; urgency=low
+
+  * Add override files for sysfsutils and hplip.
+  * Add cryptdisks-early as should-start to the lvm2 override
+    file (Closes: 429402)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Mon, 18 Jun 2007 17:32:50 +0100
+
+insserv (1.08.0-12) unstable; urgency=low
+
+  * Add override files for nbd-server and libdevmapper1.02.1.
+  * Update override files for atd, atftpd, discover, enable-nat,
+    keymap.sh, klogd, mplayer, networking, open-backdoor,
+    openbsd-inetd, report-reboot, rsync and start-wlan
+    based on the headers in the packages themselves.
+  * Add override file for lvm2 (Closes: #426104).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 26 May 2007 12:42:38 +0200
+
+insserv (1.08.0-11) unstable; urgency=low
+
+  * Add override file for timidity.
+  * Add override file for powernowd.
+  * Add override file for laptop-mode.
+  * Update override file for libnss-ldap.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu,  2 Nov 2006 13:36:10 +0100
+
+insserv (1.08.0-10) unstable; urgency=low
+
+  * Add override file for cpqarrayd.
+  * Add override file for libpam-devperm.
+  * Add override file for screen-cleanup.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 14 Oct 2006 21:00:31 +0200
+
+insserv (1.08.0-9) unstable; urgency=low
+
+  * Change bind9 override file to avoid dependency loop involving
+    $syslog->sysklogd->$named->bind9.  Remove $syslog dependency and
+    insert $remote_fs dependency instead.  Make the $network dependency
+    conditional to work when netbase is not installed.
+  * Add override file for resolvconf.
+  * Add override file for installation-report.
+  * Minor cleanup in nviboot override file, only depend on $remote_fs, no need
+    to also depend on $local_fs.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat,  7 Oct 2006 10:08:04 +0200
+
+insserv (1.08.0-8) unstable; urgency=low
+
+  * Add override files for festival, hotkey-setup and lisa.
+  * New patch 41_debiandefault to set the default runlevels for start (2345)
+    and stop (016) on Debian.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat, 16 Sep 2006 17:32:24 +0200
+
+insserv (1.08.0-7) unstable; urgency=low
+
+  * Remove override file console-screen.sh.  The info is now present in the
+    file itself.
+  * Modify override file for lvm to document that it should stop just
+    before halt and reboot.
+  * Modify override file for exim4 to only conditional depend on $named.
+  * Rewrite check-initd-order to avoid the dependency on perl-modules,
+    to make it easier to run in systems with small disks.
+  * Remove override files for aumix, cfengine2, cryptdisk, hdparm,
+    ifupdown, ifupdown-clean, kdm, nfs-common, nfs-kernel-server,
+    pcmcia, portmap, sudo, udev, udev-mtab, x11-common,
+    xdebconfigurator.  It is good enough in the scripts themselves
+    now.
+  * Modify override file for atd to avoid redundant dependencies and
+    drop runlevel 'S' from the stop list.  Reported as bug #376780.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 14 Sep 2006 15:15:49 +0200
+
+insserv (1.08.0-6) unstable; urgency=low
+
+  * Minor change to the template text, explaining that the S* symlinks
+    are renamed to K* symlinks in rc0.d/ and rc6.d/.
+  * Correct override file for sysklogd and klogd.  These should not
+    start in runlevel S, and should stop in runlevel 1.
+  * Add $syslog to the dependency list for openbsd-inetd, to make sure
+    it can log its start to syslog.  Drop $local_fs, as it is a
+    dependency for $remote_fs.
+  * New patch debian/patches/40_nosusescript to avoid inserting the
+    'single' script showing up in runlevel S, and also avoid fixing
+    the sequence number to the values used by SuSe.
+  * Correct override file for hotplug-net, it should depend on $local_fs.
+  * Correct override file for hotplug, it should stop before $local_fs.
+  * Modify patch 31_debian_conf to also list ifupdown as part of the
+    $network facility, to make $network available in runlevel 0 and 6.
+  * Try to make update-bootsystem-insserv more robust on restores.
+    Move conversion logs and related files to /var/lib/insserv.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun, 10 Sep 2006 20:17:15 +0200
+
+insserv (1.08.0-5) unstable; urgency=low
+
+  * New flag -k for check-initd-order to look at the stop sequence instead
+    of the start sequence.
+  * Correct override files for acpid, alsa, alsa-utils, apmd,
+    hwclockfirst.sh, ifupdown, modutils, networking, nullmailer,
+    openbsd-inetd, pcmcia, procps.sh, and update-hostname.
+  * Remove override files for bootlogd, bootmisc.sh, checkfs.sh,
+    checkroot.sh, glibc.sh, halt, hostname.sh, module-init-tools,
+    mountall.sh, mountdevsubfs.sh, mountnfs.sh, reboot, rmnologin,
+    sendsigs, single, stop-bootlogd, umountfs umountnfs.sh and urandom
+    as the scripts themselves now have correct dependency information
+    in them.
+  * With the current patches and dependency info, insserv generate
+    correct shutdown order.  (Closes: #350188)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat,  9 Sep 2006 20:23:28 +0200
+
+insserv (1.08.0-4) unstable; urgency=low
+
+  * Change update-bootsystem-insserv to refuse to convert the boot
+    system if there are dependency loops.
+  * New patch 37_consistent_path to make more consistent log output.
+  * Adjust the the rules file to make sure we build using the compiler options
+    specified there.
+  * New patch 33_debian_localok making .local a valid ending,
+    to accept script names like 'rc.local'.
+  * New patch 38_debuginfo to improve the debug output.
+  * New patch 39_debianlvl.dpatch to handle rcS.d/ a bit better.
+  * Add override for mountdevsubfs.sh, documenting its
+    relation to udev.
+  * Add override for stop-bootlogd, documenting that it should come late,
+    after rmnologin.
+  * Make it easier to enable the dependency based boot system by
+    adding a fairly well hidden debconf question to activate it.
+  * Adjust the override files for dns-clean, hotplug, hotplug-net,
+    hwclock.sh, keymap.sh, libdevmapper1.00, libdevmapper1.01,
+    libdevmapper1.02, modutils, nviboot and procps.sh to make sure
+    they only start in runlevel S.
+  * Adjust override file for acpid, nstxd and nstxcd, to make sure
+    they are not started in runlevel S.
+  * Adjust override file for makedev and rmnologin, there is
+    no reason to add stop links for them.
+  * Remove 'S' from all override files listing it in should-stop.  It
+    never make sense to add stop scripts in rcS.d/.
+  * Allow check-initd-order to continue even if one file is unreadable.
+  * Add override files for apt-index-watcher, vbesave, acpi-support
+    and libnss-ldap.
+  * Correct the definition of $remote_fs to include mountnfs,
+    mountnfs-bootclean and umountnfs.
+  * Correct the definition of $local_fs to include mountfs,
+    mountfs-bootclean and umountfs.
+  * Adjust the override file for openbsd-inetd, to make sure it start
+    after /usr/ is mounted.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri,  8 Sep 2006 19:14:15 +0200
+
+insserv (1.08.0-3) unstable; urgency=low
+
+  * Extend check-initd-order to accept a new argument -o, to not load
+   the override files.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu,  7 Sep 2006 11:59:17 +0200
+
+insserv (1.08.0-2) unstable; urgency=low
+
+  * New patch 35_fixunused removing incorrect 'unused' flagg from a
+    few functions, to avoid compile warning on s390.
+  * New patch 36_memleak fixing a minor memory leak.
+  * Updated override file for libdevmapper1.00.
+  * Added override file for libdevmapper1.02.
+  * Sync override files with the unstable init.d scripts for
+    alsa,alsa-utils, atd, bootlogd, bootmisc.sh, cfengine2,
+    checkfs.sh, checkroot.sh, console-screen.sh, cryptdisk, exim4,
+    fam, halt, hdparm, kdm, keymap.sh, makedev, module-init-tools,
+    mountall.sh, mountnfs.sh, networking, nfs-common,
+    nfs-kernel-server, pcmcia, portmap, pppd-dns, procps.sh, reboot,
+    rmnologin, single, sudo, udev, udev-mtab, umountfs, umountnfs.sh,
+    urandom and xdebconfigurator.  I assume the package maintainer
+    know the scripts best, and use their values.
+  * Added override file for usplash.
+  * Modify update-bootsystem-insserv to report dependency loop
+    problems. (Closes: #386301)
+  * Add recommend on perl-modules. (Closes: #386300)
+  * Update standards-version to 2.7.2.  No changes needed.
+  * Do not include 'klogd' in the $syslog facility, to avoid
+    dependency loop.
+  * Change mountvirtfs to mountdevsubfs in all override files, to
+    use the new name instead of the obsolete name.
+  * The keymap override should not depend on $syslog, and neither should
+    keymap.sh itself (bug #386338).
+  * Update 20_overrides.dpatch to new version of the source.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu,  7 Sep 2006 00:45:18 +0200
+
+insserv (1.08.0-1) unstable; urgency=low
+
+  * New upstream release.
+  * Correct name of logfile, moving the stderr redirect to the insserv
+    call. (Closes: #349494)
+  * Add code in update-bootsystem-insserv to convert all S* symlinks
+    in rc1.d and rc6.d to K* symlinks before insserv is executed. to
+    reflect the argument passed on to these scripts in debian.
+    Addresses part of bug #350188.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sun,  1 Apr 2006 17:30:35 +0100
+
+insserv (1.04.0-2) unstable; urgency=low
+
+  * Modify 20_override.dpatch based on input from upstream author
+    Werner Fink, to add more error handling.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri, 11 Nov 2005 15:35:27 +0100
+
+insserv (1.04.0-1) unstable; urgency=low
+
+  * New upstream release.
+    - Start building without -DSUSE, to enable processing of *-stop headers.
+  * Updated upstream URL in copyright file to match the latest location.
+  * Remove 40_dryrunmore.dpatch, applied upstream.
+  * Remove 41_dryrun_msg.dpatch, applied upstream.
+  * Remove 50_cfgfilter.dpatch, applied upstream.
+  * Merged 20_overrides.dpatch and 25_overrides.dpatch into one patch
+    20_overrides.dpatch.
+  * New 34_debian.dpatch modifying the paths from rc#.d/, getting
+    non-SUSE case working on Debian.
+  * New patch 30_non_suse.dpatch fixing segfault in the non-SUSE case.
+  * Updated init.d override files for hwclockfirst, ifupdown,
+    ifupdwon-clean, initrd-tools, keymap, networking, procps and
+    udev-mtab.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 10 Nov 2005 22:50:14 +0100
+
+insserv (1.02.0-3) unstable; urgency=low
+
+  * Added init.d override files for acct, apache2, snmpd and snmptrapfmt.
+  * Updated and corrected override file for alsa, apache, atd, cron,
+    gdm, gpsd, initrd-tools, udev-mtab and xdm.
+  * Wrote graphviz dotty graph generation support for check-init-order (-g).
+  * Updated README.Debian to reflect the current status in Debian, and
+    included some instructions on how to use this package.
+  * Documented in the override files which dependency information I've
+    reported to BTS.
+  * Add 'ntpdate' as a optional dependency for the $time virtual
+    facility, to make sure NTP update is done on machines without
+    their own NFS server
+  * Wrote manual page for update-bootsystem-insserv(8).
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu, 10 Nov 2005 00:18:49 +0100
+
+insserv (1.02.0-2) unstable; urgency=low
+
+  * Added init.d override files for hibernate, mdadm-raid, start-wlan
+    and x11-common.
+  * Corrected sysklogd override file, to only provide sysklogd.
+  * Document BTS bug numbers in the override file for the init.d
+    dependency headers I've submitted to the package maintainer.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Wed,  5 Oct 2005 17:04:01 +0200
+
+insserv (1.02.0-1) unstable; urgency=low
+
+  * New upstream version.
+    - Rewritten to handle non-SuSe systems better.
+    - Patches 05_verbose_doc, 10_dryrun, and 50_lsb_shold_std removed,
+      as they are included upstream.
+    - Updated patch 40_dryrunmore to match new version, and extend it to
+      also cover SuSe code.
+  * Still building with -DSUSE as the new non-SuSe features are still
+    buggy.
+  * Changed download URL in copyright file to
+    <URL:ftp://ftp.suse.com/pub/projects/init/>.
+  * Removed rc and rcS, as a version of sysvinit
+    with equivalent patches is in sid and etch now.
+  * Added and updated init.d dependency info override files.
+    The provided dependencies is tested to work on my test machines
+    with 2.4 and 2.6 installs. (Closes: #325798)
+  * New script update-bootsystem-insserv to reorder
+    the boot scripts with a backup.
+  * Avoid initscripts with .dpkg* in the name.
+    (51_cfgfilter_dpkg.dpatch) (Closes: #326445)
+  * Add dependency on sysv-rc. (Closes: #329279)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Sat,  3 Sep 2005 13:18:51 +0200
+
+insserv (1.00.8-5) unstable; urgency=low
+
+  * Updated dependency info for (module-init-tools, modutils, raid2, mdadm)
+  * Added dependency override files (noflushd, laptop-net, whereami, pcscd)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri,  2 Sep 2005 09:21:25 +0200
+
+insserv (1.00.8-4) unstable; urgency=low
+
+  * Added dependecy override files (xdm, irqbalance).
+  * Updated dependency info for a few override files (devfsd,
+    discover, hotplug, hotplug-net, hwclock.sh, keymap.sh, rmnologin,
+    sudo, gdm, lvm, ntpdate, xfs, aumix, freevo, laptop-netconf,
+    report-reboot, open-backdoor).
+  * New patch to avoid warning about missing override files if the
+    init.d file already contain LSB tags.  (25_override.dpatch)
+  * Correct header example in the insserv(8) manual page.
+    (50_lsb_should_std.dpatch)
+
+ -- Petter Reinholdtsen <pere@debian.org>  Thu,  1 Sep 2005 22:24:51 +0200
+
+insserv (1.00.8-3) unstable; urgency=low
+
+  * Added dependecy override files (nullmailer, binfmt-support).
+  * Add suggests on bootchart, a great tool to debug the boot
+    sequence.
+  * New patch to get dryrun mode working also when /etc/rc.boot is
+    missing. (40_dryrunmore.dpatch)
+  * Added more information about the dangers of reorganizing the boot
+    sequence in README.Debian.
+  * Some package cleanup.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri, 30 Aug 2005 00:20:16 +0200
+
+insserv (1.00.8-2) unstable; urgency=low
+
+  * Updated and added dependecy override files.
+  * Added script check-initd-order, trying to check the current boot
+    sequence in debian based on the LSB headers present.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri, 26 Aug 2005 00:20:16 +0200
+
+insserv (1.00.8-1) unstable; urgency=low
+
+  * Initial Release. (Closes: #324926)
+  * Document the -v (--verbose) flag. (05_verbose_doc.dpatch)
+  * Implement new option -n (--dryrun). (10_dryrun.dpatch)
+  * Implement support for reading LSB init.d header info from override
+    files. (20_overrides.dpatch)
+  * Adjust some paths and avoid installing LSB install scripts to
+    match Debian policy.  (30_debian.dpatch)
+  * Add README.Debian explaining how to test this.
+
+ -- Petter Reinholdtsen <pere@debian.org>  Fri, 26 Aug 2005 00:19:16 +0200
diff --git a/debian/check-archive-initd-scripts b/debian/check-archive-initd-scripts
new file mode 100644 (file)
index 0000000..343a718
--- /dev/null
@@ -0,0 +1,247 @@
+#!/usr/bin/perl
+#
+# Check the consistency of all init.d scripts in the archive.  Run
+# this on bellini.debian.org.
+
+use warnings;
+use strict;
+use File::Basename;
+
+my $warn = 1;
+
+my $basedir = "/org/lintian.debian.org/laboratory/binary";
+
+my @scripts = @ARGV;
+@scripts = <$basedir/*/init.d/*> unless (@scripts);
+
+my %scriptinfo;
+my %provides;
+
+my @virts = qw($local_fs $remote_fs $syslog $time $named
+               $portmap $network $all
+               $mail-transport-agent $x-font-server
+               );
+my @harddepheaders = qw(required-start required-stop);
+my @softdepheaders = qw(should-start
+                    should-stop x-start-before x-stop-after);
+my $lsbheaders = "Provides|Required-Start|Required-Stop|Default-Start|Default-Stop";
+my $optheaders = "x-start-before|x-stop-after|should-start|should-stop";
+
+for my $virt (@virts) {
+    $provides{$virt} = ['insserv/etc/insserv.conf'];
+}
+
+# Ignore obsolete scripts, as these are unlikely to cause problems.
+for my $old (qw(glibc evms raid2 ldm sdm)) {
+    $provides{$old} = ['obsolete'];
+}
+
+# First pass to load the database
+for my $initdscript (@scripts) {
+    next if $initdscript =~ m%/rc|/rcS|/README%;
+    my %lsbinfo = parse_lsb_header($initdscript);
+    $scriptinfo{$initdscript} = \%lsbinfo;
+    next unless ($lsbinfo{'found'});
+
+    my %checked;
+    for my $provide (split(/[ ,\t]+/, $lsbinfo{provides})) {
+        if (exists $provides{$provide}) {
+            push(@{$provides{$provide}}, $initdscript)
+        } else {
+            $provides{$provide} = [$initdscript];
+        }
+        $checked{$provide} = 1;
+    }
+}
+
+for my $provide (sort keys %provides) {
+    if (1 < scalar @{$provides{$provide}}) {
+        my %script;
+        map { $script{basename($_)} = 1; } @{$provides{$provide}};
+        if (1 < scalar keys %script) {
+            error(sprintf("scripts %s provide duplicate '%s'",
+                          join(",", short_name(@{$provides{$provide}})),
+                          $provide));
+        }
+    }
+}
+
+# Second pass, to see which dependencies are missing
+for my $initdscript (@scripts) {
+    next unless ($scriptinfo{$initdscript}->{'found'});
+    my $short = short_name($initdscript);
+    my %checked;
+    my @hardmissing = ();
+    for my $header (@harddepheaders) {
+        my $list = $scriptinfo{$initdscript}->{$header};
+        next unless defined $list;
+        for my $facility (split(/[ ,\t]+/, $list)) {
+            next if exists $checked{$facility};
+            $checked{$facility} = 1;
+            push(@hardmissing, $facility)
+                unless exists $provides{$facility};
+        }
+    }
+    error("script $short depend on non-existing provides: "
+          . join(" ", @hardmissing)) if (@hardmissing);
+    my @softmissing = ();
+    for my $header (@softdepheaders) {
+        my $list = $scriptinfo{$initdscript}->{$header};
+        next unless defined $list;
+        for my $facility (split(/[ ,\t]+/, $list)) {
+            next if exists $checked{$facility};
+            $checked{$facility} = 1;
+            push(@softmissing, $facility)
+                unless exists $provides{$facility};
+        }
+    }
+    warning("script $short relate to non-existing provides: "
+            . join(" ", @softmissing)) if (@softmissing);
+
+    if (exists $checked{'$syslog'}
+        && $scriptinfo{$initdscript}->{'default-start'} =~ m/s/i) {
+        error("script $short depend on \$syslog and start from rcS.d/");
+    }
+    if (!exists $checked{'$remote_fs'}
+        && !exists $checked{'$syslog'}
+        && $scriptinfo{$initdscript}->{'need_remove_fs'}
+        && $scriptinfo{$initdscript}->{'default-start'} =~ m/s/i) {
+        warning("script $short possibly missing dependency on \$remote_fs");
+    } elsif (!exists $checked{'$local_fs'}
+             && !exists $checked{'$remote_fs'}
+             && !exists $checked{'$syslog'}
+             && $scriptinfo{$initdscript}->{'need_local_fs'}
+             && $scriptinfo{$initdscript}->{'default-start'} =~ m/s/i) {
+        warning("script $short possibly missing dependency on \$local_fs");
+    }
+
+    my %provided;
+    for my $provide (split(/[ ,\t]+/,
+                           $scriptinfo{$initdscript}->{provides})) {
+        $provided{$provide} = 1;
+        if ($provide =~ m/\$/) {
+            error("script $short provide virtual facility $provide");
+        }
+    }
+
+    my $basename = basename($initdscript, ".sh");
+    warning("script $short does not provide its own name")
+        unless exists $provided{$basename};
+
+    # Detect common problems with runlevel settings.
+    my @startrl = sort split(/\s+/, lc($scriptinfo{$initdscript}->{'default-start'}));
+    my @stoprl = sort split(/\s+/, lc($scriptinfo{$initdscript}->{'default-stop'}));
+
+    # Scripts starting in rcS.d/ normally do not stop or only stop
+    # during hald and shutdown.
+    if ((array_equal(['s'], \@startrl) && array_equal([], \@stoprl))
+        || ( array_equal(['s'], \@startrl)
+             && array_equal(['0','6'], \@stoprl))) {
+        # OK
+    } else {
+        # Most scripts either start in rcS.d, or in runlevels 2-5
+        if (!array_equal(['2', '3', '4', '5'], \@startrl) &&
+            !array_equal(['s'], \@startrl) &&
+            (!array_equal([], \@startrl) && @stoprl)) {
+            warning("script $short does not start in the usual runlevels: ",
+                    join(" ", @startrl));
+        }
+
+        # And most scripts stop in runlevel (1) runlevels (0, 1, 6),
+        # only starts or only stops in (0) or (6).
+        if (!array_equal(['0', '1', '6'], \@stoprl) &&
+            !array_equal(['1'], \@stoprl) &&
+            !array_equal(['0', '6'], \@stoprl) &&
+            !(array_equal(['0'], \@stoprl) && !@startrl) &&
+            !(array_equal(['6'], \@stoprl) && !@startrl) &&
+            !(array_equal([], \@stoprl) && @startrl)) {
+            warning("script $short does not stop in the usual runlevels: ",
+                    join(" ", @stoprl));
+        }
+    }
+}
+
+exit 0;
+
+sub parse_lsb_header {
+    my $initdscript = shift;
+    my $short = short_name($initdscript);
+    my %lsbinfo;
+    unless (open(INIT, "<", $initdscript)) {
+        error("script $short is unreadable");
+        return ();
+    }
+    my $inheader = 0;
+    while (<INIT>) {
+#        print;
+        chomp;
+        if (m/^\#\#\# BEGIN INIT INFO\s*$/) {
+            $lsbinfo{'found'} = 1;
+            $inheader = 1;
+        }
+        $inheader = 0 if (m/\#\#\# END INIT INFO$/);
+        if ($inheader
+            && m/^\# ($lsbheaders|$optheaders):\s*(\S?.*)$/i) {
+#            print "$1\n";
+            $lsbinfo{lc($1)} = $2;
+        }
+        s/\#.*$//; # Remove comments
+        $lsbinfo{'need_remove_fs'} = 1 if m%/usr/s?bin/%;
+        $lsbinfo{'need_local_fs'} = 1 if m%/var/%;
+
+        # Detect the use of tools resting in /usr/
+        $lsbinfo{'need_remove_fs'} = 1 if m%awk%;
+        $lsbinfo{'need_remove_fs'} = 1 if m%which%;
+    }
+    close(INIT);
+
+    # Check that all the required headers are present
+    if (!$lsbinfo{'found'}) {
+        error("script $short is missing LSB header");
+    } else {
+        for my $key (split(/\|/, lc($lsbheaders))) {
+            if (!exists $lsbinfo{$key}) {
+                error("script $short missing LSB keyword '$key'");
+            }
+        }
+    }
+    return %lsbinfo
+}
+
+sub short_name {
+    my @scripts;
+    for my $script ( @_ ) {
+        my $copy = $script;
+        $copy =~ s%$basedir/%%g;
+        push @scripts, $copy;
+    }
+    if (wantarray) {
+        return @scripts;
+    } else {
+        return $scripts[0];
+    }
+}
+
+sub array_equal {
+    my ($a1, $a2) = @_;
+    return 0 if (scalar @{$a1} != scalar @{$a2});
+
+    my $i = 0;
+    while ($i < scalar @{$a1}) {
+        return 0 if $a1->[$i] ne $a2->[$i];
+        $i++;
+    }
+    return 1;
+}
+
+sub info {
+    print "info: @_\n";
+}
+
+sub warning {
+    print "warning: @_\n" if $warn;
+}
+
+sub error {
+    print "error: @_\n";
+}
diff --git a/debian/check-initd-order b/debian/check-initd-order
new file mode 100644 (file)
index 0000000..e7d0ef6
--- /dev/null
@@ -0,0 +1,425 @@
+#!/usr/bin/perl
+#
+# Author: Petter Reinholdtsen
+# Date:   2005-08-21
+#
+# Read LSM init.d headers in SysV init.d scripts, and verify correct
+# start order for all runlevels.  It can also provide a graph.
+#
+# To generate a graph, run it like this
+#
+#   check-initd-order -g > initorder.dotty && dotty initorder.dotty
+
+use strict;
+use warnings;
+
+my $rcbase = "/etc";
+
+my $overridepath = "/usr/share/insserv/overrides";
+my $hostoverridepath =  "/etc/insserv/overrides";
+
+my $debug = 0;
+my $errors = 0;
+
+my %rcmap =
+    (
+     'B' => 'rc.boot',
+     'S' => 'rcS.d',
+     '1' => 'rc1.d',
+     '2' => 'rc2.d',
+     '3' => 'rc3.d',
+     '4' => 'rc4.d',
+     '5' => 'rc5.d',
+     '6' => 'rc6.d',
+     );
+
+my %sysmap;
+
+my %provideslist;
+my %scriptorder;
+my %opts;
+
+# Used to draw graphs
+my %gotrevdeps;
+my %allprovides;
+
+while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
+        shift @ARGV;
+        if (/^-([cdgko])$/) { $opts{$1}++; next }
+        if (/^-b$/) { $rcbase = shift; next }
+        if (/^-h|--help$/) { &usage; }
+        &usage("unknown option");
+}
+
+load_sysmap("$rcbase/insserv.conf");
+
+$debug = $opts{'d'};
+my $useoverrides = $opts{'o'} ? 0 : 1;
+
+if ($opts{'g'}) {
+    graph_generate();
+    exit 0;
+}
+
+check_bootorder();
+exit $errors > 0 ? 1 : 0;
+
+sub usage {
+    print STDERR "check-initd-order: error: @_\n" if ($#_ >= 0);
+    print STDERR <<EOF;
+usage: check-initd-order [-cdgko] [-b basedir]
+  -b basedir (default /etc)
+  -d enable debug output
+  -o do not load override files
+  -k use shutdown (reboot) sequence instead of boot sequence
+  -g generate graph
+  -c use combined boot and shutdown sequence (only for graphs)
+EOF
+    exit 1;
+}
+
+# Simple basename implementatin to avoid dependin on File::Basename
+# from perl-modules
+sub basename {
+    my $path = shift;
+    $path =~ s%^.*/([^/]+)$%$1%;
+    return $path;
+}
+
+sub error {
+    print STDERR "error: ", @_;
+    $errors++;
+}
+
+# Map packages to system metapackages.  These dependencies should
+# probably be more complex
+sub load_sysmap {
+    my $filename = shift;
+    unless (open(CONF, "<", "$filename")) {
+        print STDERR "error: unable to load $filename";
+        return;
+    }
+    while (<CONF>) {
+        chomp;
+        s/\#.*$//;
+        next if m/^\s*$/;
+        if (m/^(\$\S+)\s+(\S.*\S*)\S*$/) {
+            my $virt = $1;
+            for my $dep (split(/\s+/, $2)) {
+                $dep =~ s/^\+//g;
+                $sysmap{$dep} = $virt;
+            }
+        }
+    }
+    close(CONF);
+}
+
+sub graph_addnode {
+    my ($isstopseq, $lsbinforef) = @_;
+    my %lsbinfo = %{$lsbinforef};
+
+    unless ($lsbinfo{'provides'}) {
+        error "File ". $lsbinfo{'file'} . " is missing the provides header\n";
+        $lsbinfo{'provides'} = $lsbinfo{'file'};
+        $lsbinfo{'provides'} =~ s/^[SK]\d{2}//;
+    }
+
+    my $key = $opts{'k'} ? 'stop' : 'start';
+    my $revkey = $opts{'k'} ? 'stop-after' : 'start-before';
+    my @provides = split(/\s+/, $lsbinfo{'provides'});
+    for my $name (@provides) {
+        if (exists $sysmap{$name}) {
+            graph_addnode($isstopseq,
+                          {'provides'      => $sysmap{$name},
+                          "required-$key" => $name});
+        }
+    }
+
+    if (1 < @provides) {
+        my @providescopy = @provides;
+        my $lastprovide = shift @providescopy;
+        for my $provide (@providescopy) {
+            graph_addnode($isstopseq,
+                          {'provides'      => $lastprovide,
+                           "required-$key" => $provide});
+            graph_addnode($isstopseq,
+                          {'provides'      => $provide,
+                           "required-$key" => $lastprovide});
+        }
+    }
+
+    for my $provide (@provides) {
+        my $provideesc = $provide; $provideesc =~ s/"/\\"/g;
+        my %deps =
+            (
+             "required-$key" => 'blue',
+             "should-$key" => 'springgreen',
+             "$revkey" => 'yellow'
+             );
+
+        for $key (keys %deps) {
+            if (exists $lsbinfo{$key} && $lsbinfo{$key}) {
+                my @depends = split(/\s+/, $lsbinfo{$key});
+
+                my $dependonall = 0;
+                for my $pkg (@depends) {
+                    $dependonall = 1 if ($pkg eq '$all');
+                }
+
+                for my $pkg (@depends) {
+                    my $pkgesc = $pkg; $pkgesc =~ s/"/\\"/g;
+                    my $color = $deps{$key};
+                    if ($revkey eq $key) {
+                        print "\"$provideesc\" -> \"$pkgesc\"[color=$color] ;\n";
+                        $gotrevdeps{$pkg} = 1 unless $dependonall;
+                    } else {
+                        print "\"$pkgesc\" -> \"$provideesc\"[color=$color] ;\n";
+                        $gotrevdeps{$provide} = 1 unless $dependonall;
+                    }
+                }
+            }
+        }
+
+        print "\"$provideesc\" [shape=box];\n" unless $allprovides{$provide};
+        $allprovides{$provide} = 1;
+    }
+}
+
+sub graph_generate_mode {
+    my ($isstopseq) = @_;
+    my @dirs = $isstopseq ? $rcmap{6} : ($rcmap{S}, $rcmap{2});
+    for my $rcdir (@dirs) {
+        chdir "$rcbase/$rcdir/.";
+        my @scripts = $isstopseq ? <K*> : <S*>;
+        for my $script (@scripts) {
+            my $lsbinforef = load_lsb_tags("$rcbase/$rcdir/$script",
+                                           $useoverrides);
+
+            unless (defined $lsbinforef) {
+                error "LSB header missing in $rcbase/$rcdir/$script\n";
+                $script =~ s/^[SK]\d{2}//;
+                $lsbinforef = {'provides'       => $script,
+                               'required-start' => '$remote_fs $syslog',
+                               'required-stop'  => '$remote_fs $syslog'};
+            }
+            graph_addnode($isstopseq, $lsbinforef);
+        }
+    }
+    # Mark all packages without any reverse dependencies as depending
+    # on $all
+    for my $provide (keys %allprovides) {
+        next unless (exists $gotrevdeps{$provide});
+        my $lsbinforef = {'provides'       => '$all',
+                          'required-start' => "$provide",
+                          'required-stop'  => "$provide"};
+        graph_addnode($isstopseq, $lsbinforef);
+    }
+}
+
+sub graph_generate {
+    print "# Generating graph\n";
+    print <<EOF;
+digraph packages {
+rankdir=LR;
+concentrate=true;
+EOF
+    if ($opts{'c'}) {
+        graph_generate_mode();
+        graph_generate_mode(1);
+    } else {
+        graph_generate_mode($opts{'k'});
+    }
+    print <<EOF;
+}
+EOF
+}
+
+sub check_deps {
+    my ($lsbinforef, $tag, $order, $bootorder, $headername, $required) = @_;
+    my %lsbinfo = %{$lsbinforef};
+    my $name = $lsbinfo{'file'};
+    if ($lsbinfo{$headername}) {
+        my @depends = split(/\s+/, $lsbinfo{$headername});
+        for my $dep (@depends) {
+            if (! $required && exists $provideslist{$dep}) {
+                unless (exists $scriptorder{$tag}{$dep}
+                        and ("S" eq $tag
+                             ? $scriptorder{$tag}{$dep} < $bootorder
+                             : $scriptorder{$tag}{$dep} > $bootorder)) {
+                    my $deporder;
+                    if (exists $scriptorder{$tag}{$dep}) {
+                        $deporder = $scriptorder{$tag}{$dep}
+                    } else {
+                        $deporder = exists $provideslist{$dep} ? $provideslist{$dep} : "?";
+                    }
+                    error(sprintf("Incorrect order %s@%s %s %s%s\n",
+                           $dep, $deporder, 'S' eq $tag ? '>' : '<',
+                           $name, $order));
+                }
+            }
+        }
+    }
+}
+
+sub check_bootorder {
+    my $bootorder = 0;
+    my @dirs = $opts{'k'} ? $rcmap{6} : ($rcmap{S}, $rcmap{2});
+    my @scripts;
+    for my $rcdir (@dirs) {
+        push(@scripts, $opts{'k'} ? <$rcbase/$rcdir/K*> : <$rcbase/$rcdir/S*>);
+    }
+
+    if ($opts{'k'}) {
+        $scriptorder{'K'}{'$all'} = 1;
+    } else {
+        # Calculate script order for the script before the scripts
+        # with the last boot sequence number.
+        my $tmpbootorder = 0;
+        my $allorder = 0;
+        my $maxorder = 0;
+        my $maxbootorder = 0;
+        for my $scriptpath (@scripts) {
+            my $script = $scriptpath;
+            $script =~ s%^.*/([^/]+)$%$1%;
+            $tmpbootorder++;
+            my ($tag, $order, $name) = $script =~ m/^(.)(\d{2})(.+)$/;
+            if ($order > $maxorder) {
+                $allorder = $maxbootorder;
+                $maxbootorder = $tmpbootorder;
+                $maxorder = $order;
+            }
+
+            my $lsbinforef = load_lsb_tags($scriptpath,
+                                           $useoverrides);
+
+            if (exists $lsbinforef->{'provides'}
+                && $lsbinforef->{'provides'}) {
+                for my $provide (split(/\s+/, $lsbinforef->{'provides'})) {
+                    $provideslist{$provide} = $order;
+                }
+            } else {
+                $provideslist{$script} = $order;
+            }
+        }
+        $scriptorder{'S'}{'$all'} = $allorder;
+    }
+    for my $scriptpath (@scripts) {
+        my $script = $scriptpath;
+        $script =~ s%^.*/([^/]+)$%$1%;
+        $bootorder++;
+        my ($tag, $order, $name) = $script =~ m/^(.)(\d{2})(.+)$/;
+
+        $scriptorder{$tag}{$name} = $bootorder;
+        $scriptorder{$tag}{$sysmap{$name}} = $bootorder
+            if (exists $sysmap{$name});
+
+#           print "$script\n";
+#           print "T: $tag O: $order N: $name\n";
+        my $lsbinforef = load_lsb_tags($scriptpath,
+                                       $useoverrides);
+
+        unless (defined $lsbinforef) {
+            error "LSB header missing in $scriptpath\n";
+            next;
+        }
+        my %lsbinfo = %{$lsbinforef};
+
+        if (exists $lsbinfo{'provides'} && $lsbinfo{'provides'}) {
+            for my $provide (split(/\s+/, $lsbinfo{'provides'})) {
+                $scriptorder{$tag}{$provide} = $bootorder;
+                $scriptorder{$tag}{$sysmap{$provide}} = $bootorder
+                    if (exists $sysmap{$provide});
+            }
+        } else {
+            error "no LSB header provides value in script $scriptpath\n";
+        }
+
+        if ('S' eq $tag) {
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'required-start', 1);
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'should-start', 0);
+#            check_deps($lsbinforef, 'K', $order, $bootorder, 'start-before', 0);
+        }
+        if ('K' eq $tag) {
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'required-stop', 1);
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'should-stop', 0);
+#            check_deps($lsbinforef, 'S', $order, $bootorder, 'stop-after', 0);
+        }
+    }
+}
+
+sub load_lsb_tags {
+    my ($initfile, $useoverrides) = @_;
+    my $lsbinforef = load_lsb_tags_from_file($initfile);
+
+    if ($useoverrides) {
+        # Try override file
+        $initfile = readlink($initfile) if (-l $initfile);
+        my $basename = basename($initfile);
+
+        # Only read shipped override file when initscript does not
+        # contain LSB tags.
+        if (! defined($lsbinforef) && -f "$overridepath/$basename") {
+            print STDERR "Override $overridepath/$basename\n" if $debug;
+            $lsbinforef = load_lsb_tags_from_file("$overridepath/$basename");
+        }
+
+        # Always read the host override in $hostoverridepath.
+        if (-f "$hostoverridepath/$basename") {
+            print STDERR "Override $hostoverridepath/$basename\n" if $debug;
+            $lsbinforef = load_lsb_tags_from_file("$hostoverridepath/$basename");
+        }
+
+    }
+    return $lsbinforef;
+}
+
+sub load_lsb_tags_from_file {
+    my ($file) = @_;
+    print STDERR "Loading $file\n" if $debug;
+    ### BEGIN INIT INFO
+    # Provides:          xdebconfigurator
+    # Required-Start:    $syslog
+    # Required-Stop:     $syslog
+    # Default-Start:     2 3 4 5
+    # Default-Stop:      1 6
+    # Short-Description: Genererate xfree86 configuration at boot time
+    # Description:       Preseed X configuration and use dexconf to
+    #                    genereate a new configuration file.
+    ### END INIT INFO
+    unless (open(FILE, "<$file")) {
+        warn "error: Unable to read $file";
+        return;
+    }
+    my $found = 0;
+    my ($provides, $requiredstart, $requiredstop, $shouldstart, $shouldstop);
+    my ($startbefore, $stopafter);
+    while (<FILE>) {
+        chomp;
+        $found = 1 if (m/\#\#\# BEGIN INIT INFO/);
+        next unless $found;
+        last if (m/\#\#\# END INIT INFO/);
+
+        $provides = $1      if (m/^\# provides:\s+(\S*.*\S+)\s*$/i);
+        $requiredstart = $1 if (m/^\# required-start:\s+(\S*.*\S+)\s*$/i);
+        $requiredstop = $1  if (m/^\# required-stop:\s+(\S*.*\S+)\s*$/i);
+        $shouldstart = $1   if (m/^\# should-start:\s+(\S*.*\S+)\s*$/i);
+        $shouldstop = $1    if (m/^\# should-stop:\s+(\S*.*\S+)\s*$/i);
+        $startbefore = $1   if (m/^\# X-Start-Before:\s+(\S*.*\S+)\s*$/i);
+        $stopafter = $1     if (m/^\# X-Stop-After:\s+(\S*.*\S+)\s*$/i);
+    }
+    close(FILE);
+
+    return undef unless ($found);
+
+#    print "Provides: $provides\n" if $provides;
+    return {
+            'provides'       => $provides,
+            'required-start' => $requiredstart,
+            'required-stop'  => $requiredstop,
+            'should-start'   => $shouldstart,
+            'should-stop'    => $shouldstop,
+            'start-before'   => $startbefore,
+            'stop-after'     => $stopafter,
+            'file'           => $file,
+            };
+}
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..1e8b314
--- /dev/null
@@ -0,0 +1 @@
+6
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..6377523
--- /dev/null
@@ -0,0 +1,31 @@
+Source: insserv
+Section: misc
+Priority: optional
+Maintainer: Rafal Krypa <r.krypa@samsung.com>
+X-Original-Maintainer: Petter Reinholdtsen <pere@debian.org>
+X-Original-Uploaders: Kel Modderman <kel@otaku42.de>
+Build-Depends: debhelper (>= 6.0.7), po-debconf, quilt
+Standards-Version: 3.8.3
+DM-Upload-Allowed: yes
+Homepage: http://ftp.suse.com/pub/projects/init/
+Vcs-Svn: svn://svn.debian.org/initscripts-ng/trunk/src/insserv
+Vcs-Browser: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/
+
+Package: insserv
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Suggests: bootchart
+Breaks: sysv-rc (<< 2.87dsf-3)
+Description: Tool to organize boot sequence using LSB init.d script dependencies
+ The insserv program is used to update the order of symlinks in
+ /etc/rc?.d/ with sysv-rc based on dependencies specified in the
+ scripts themselves using LSB init.d script headers.
+ .
+ This allow each package maintainer to specify their init.d script
+ relation to other scripts and make it possible to detect and reject
+ script dependency loops as well as making sure all scripts start in
+ their intended order.
+ .
+ The program insserv in this package should be used with care and
+ together with the sysv-rc package, as using it incorrectly can lead
+ to an unbootable system.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..5d841a2
--- /dev/null
@@ -0,0 +1,20 @@
+This package was debianized by Petter Reinholdtsen <pere@hungry.com> on
+Sun, 21 Aug 2005 11:20:54 +0200.
+
+It was downloaded from <URL: ftp://ftp.suse.com/pub/projects/init/ >
+
+Copyright Holder: Werner Fink <werner@suse.de> and SuSE LINUX AG.
+
+License:
+
+ Copyright 2000-2004 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
+                                  2003 SuSE Linux AG, Germany.
+                                  2004 SuSE LINUX AG, Germany.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+On Debian systems, a copy of the GNU General Public License version 2
+may be found in the file /usr/share/common-licenses/GPL-2.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..97b3b20
--- /dev/null
@@ -0,0 +1,6 @@
+etc/bash_completion.d
+etc/insserv.conf.d
+etc/insserv/overrides
+usr/sbin
+usr/share/insserv/overrides
+var/lib/update-rc.d
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..e845566
--- /dev/null
@@ -0,0 +1 @@
+README
diff --git a/debian/lintian-overrides b/debian/lintian-overrides
new file mode 100644 (file)
index 0000000..d31810e
--- /dev/null
@@ -0,0 +1 @@
+insserv: binary-without-manpage usr/sbin/update-bootsystem-insserv
diff --git a/debian/make-testsuite b/debian/make-testsuite
new file mode 100644 (file)
index 0000000..c4aec47
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Extract key information from the current to try to generate a test
+# suite script to demonstrate detected bugs.
+
+echo "cat <<'EOF' > \$tmpdir\$insconf"
+grep -v '#' /etc/insserv.conf |grep -v '^$'
+echo "EOF"
+
+for f in /etc/init.d/*; do
+       name=$(basename $f)
+       case $name in
+           README|rc|rcS|skeleton)
+               ;;
+           *)
+               echo "addscript $name <<EOF"
+               sed -n -r '/^### BEGIN INIT INFO/, /END INIT INFO/p' < $f
+               echo "EOF"
+               echo
+               ;;
+       esac
+done
+
+cd /etc
+for f in rc?.d/*; do
+       case $f in
+           */README)
+               ;;
+           *)
+               echo ln -s $(readlink $f) $f
+               ;;
+       esac
+done
diff --git a/debian/manpages b/debian/manpages
new file mode 100644 (file)
index 0000000..80588fc
--- /dev/null
@@ -0,0 +1 @@
+debian/update-rc.d-insserv.8
diff --git a/debian/overrides/devfsd b/debian/overrides/devfsd
new file mode 100644 (file)
index 0000000..ed36858
--- /dev/null
@@ -0,0 +1,8 @@
+### BEGIN INIT INFO
+# Provides:          devfsd
+# Required-Start:    mountdevsubfs 
+# Required-Stop:     reboot
+# Default-Start:     S 1 2 3 4 5
+# Default-Stop:      0 6
+### END INIT INFO
+# Reported to BTS as bug #324671
diff --git a/debian/overrides/hotplug b/debian/overrides/hotplug
new file mode 100644 (file)
index 0000000..9e7b8d1
--- /dev/null
@@ -0,0 +1,7 @@
+### BEGIN INIT INFO
+# Provides:          hotplug
+# Required-Start:    mountdevsubfs checkroot $local_fs
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
diff --git a/debian/overrides/hotplug-net b/debian/overrides/hotplug-net
new file mode 100644 (file)
index 0000000..6f612d3
--- /dev/null
@@ -0,0 +1,7 @@
+### BEGIN INIT INFO
+# Provides:          hotplug-net
+# Required-Start:    $local_fs ifupdown
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
diff --git a/debian/overrides/initrd-tools.sh b/debian/overrides/initrd-tools.sh
new file mode 100644 (file)
index 0000000..2f4a800
--- /dev/null
@@ -0,0 +1,7 @@
+### BEGIN INIT INFO
+# Provides:          initrd-tools
+# Required-Start:    mountdevsubfs
+# Required-Stop: 
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
diff --git a/debian/overrides/modutils b/debian/overrides/modutils
new file mode 100644 (file)
index 0000000..dacdc4f
--- /dev/null
@@ -0,0 +1,8 @@
+### BEGIN INIT INFO
+# Provides:          modutils
+# Required-Start:    checkroot
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+# Reported to BTS as #335311
diff --git a/debian/patches/10_nosuse.patch b/debian/patches/10_nosuse.patch
new file mode 100644 (file)
index 0000000..faad0a8
--- /dev/null
@@ -0,0 +1,17 @@
+Purpose: Disable the SUSE flag.
+Fixes:   None, made as part of Debian porting.
+Status:  Debian specific, showed to upstream.
+---
+Index: insserv/Makefile
+===================================================================
+--- insserv.orig/Makefile      2009-09-26 22:35:26.000000000 +0200
++++ insserv/Makefile   2009-09-26 22:35:45.000000000 +0200
+@@ -9,7 +9,7 @@
+ #DESTDIR =    /tmp/root
+ #DEBUG         =      -DDEBUG=1 -Wpacked
+ DEBUG  =
+-ISSUSE         =      -DSUSE
++ISSUSE         =      -DNOTSUSE
+ DESTDIR        =
+ VERSION        =      1.12.0
+ DATE   =      $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
diff --git a/debian/patches/11_debian_conf.patch b/debian/patches/11_debian_conf.patch
new file mode 100644 (file)
index 0000000..5ca0d2a
--- /dev/null
@@ -0,0 +1,55 @@
+Purpose: Adjust the insserv configuration for Debian init.d script names.
+Fixes:   None, made as part of Debian porting.
+Status:  Debian specific, showed to upstream.
+---
+Index: insserv/insserv.conf
+===================================================================
+--- insserv.orig/insserv.conf  2009-09-26 22:35:26.000000000 +0200
++++ insserv/insserv.conf       2009-09-26 22:35:39.000000000 +0200
+@@ -1,29 +1,29 @@
+ #
+ # All local filesystems are mounted (done during boot phase)
+ #
+-$local_fs     boot.localfs
++$local_fs     +mountall +mountoverflowtmp +umountfs
+ #
+ # Low level networking (ethernet card)
+ #
+-$network      network +pcmcia +hotplug
++$network      +networking +ifupdown
+ #
+ # Named is operational
+ #
+-$named                +named +dnsmasq +lwresd $network
++$named                +named +dnsmasq +lwresd +bind9 $network
+ #
+ # All remote filesystems are mounted (note in some cases /usr may
+ # be remote. Most applications that care will probably require
+ # both $local_fs and $remote_fs)
+ #
+-$remote_fs    $local_fs +nfs
++$remote_fs    $local_fs +mountnfs +mountnfs-bootclean +umountnfs +sendsigs
+ #
+ # System logger is operational
+ #
+-$syslog               syslog
++$syslog               +rsyslog +sysklogd +syslog-ng +dsyslog +inetutils-syslogd 
+ #
+ # SunRPC portmapper available
+@@ -33,9 +33,9 @@
+ #
+ # The system time has been set correctly
+ #
+-$time         boot.clock +xntpd
++$time         +hwclock
+ #
+ # Services which need to be interactive
+ #
+-<interactive>   boot.crypto boot.localfs boot.rootfsck apache apache2 kdump
++<interactive>   glibc udev console-screen keymap keyboard-setup console-setup cryptdisks cryptdisks-early checkfs-loop
diff --git a/debian/patches/20_install_perms_fixup.patch b/debian/patches/20_install_perms_fixup.patch
new file mode 100644 (file)
index 0000000..c3ac3c8
--- /dev/null
@@ -0,0 +1,29 @@
+Purpose: Use correct permissions for installing /sbin/insserv and
+         /etc/insserv.conf
+Authour: Kel Modderman
+Fixes:   -
+Status:  Not yet submitted upstream.
+
+Index: insserv/Makefile
+===================================================================
+--- insserv.orig/Makefile      2009-09-26 22:35:39.000000000 +0200
++++ insserv/Makefile   2009-09-26 22:35:39.000000000 +0200
+@@ -41,14 +41,14 @@
+            RM = rm -f
+         MKDIR = mkdir -p
+         RMDIR = rm -rf
+-   INSTBINFLAGS = -m 0700
++   INSTBINFLAGS = -m 0755
+       INSTBIN = install $(INSTBINFLAGS)
+-   INSTSRPFLAGS = -m 0700
++   INSTSRPFLAGS = -m 0755
+       INSTSRP = install $(INSTSRPFLAGS)
+-   INSTDOCFLAGS = -c -m 0444
++   INSTDOCFLAGS = -c -m 0644
+       INSTDOC = install $(INSTDOCFLAGS)
+    INSTCONFLAGS = -c -m 0644
+-      INSTCON = install $(INSTDOCFLAGS)
++      INSTCON = install $(INSTCONFLAGS)
+          LINK = ln -sf
+ #
+       SDOCDIR = $(DESTDIR)/usr/share/man/man8
diff --git a/debian/patches/21_tests_suite_new_functions.patch b/debian/patches/21_tests_suite_new_functions.patch
new file mode 100644 (file)
index 0000000..14c0f23
--- /dev/null
@@ -0,0 +1,36 @@
+Purpose: Add some extra functions used by Debian test suite script
+Authour: Kel Modderman
+Fixes:   -
+Status:  Should be sent upstream
+
+Index: insserv/tests/suite
+===================================================================
+--- insserv.orig/tests/suite   2009-09-26 22:35:26.000000000 +0200
++++ insserv/tests/suite        2009-09-26 22:35:39.000000000 +0200
+@@ -94,6 +94,12 @@
+     $insserv $debug -c $insconf -p $initddir -o $overridedir -r $script
+ }
++initdir_purge ()
++{
++    rm -rf ${initddir}/../rc*.d ${initddir}
++    mkdir -p ${initddir}
++}
++
+ relpath ()
+ {
+     local OLDIFS IFS
+@@ -201,6 +207,13 @@
+     chmod u+w,a+rx $script
+ }
++remscript ()
++{
++    local scriptname=$1
++    local script=${initddir}/$scriptname
++    rm -f $script
++}
++
+ insertscript ()
+ {
+     local scriptname=$1
diff --git a/debian/patches/30_deterministic_order.patch b/debian/patches/30_deterministic_order.patch
new file mode 100644 (file)
index 0000000..5e52033
--- /dev/null
@@ -0,0 +1,77 @@
+Purpose: Defend against undeterministic directory stream sequence
+         returned by readdir(3). Make sure script which is being
+         registered is processed before all others.
+Fixes:   #494514
+Status:  Applied upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:25.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:44.000000000 +0200
+@@ -2238,6 +2238,7 @@
+     boolean del = false;
+     boolean defaults = false;
+     boolean ignore = false;
++    boolean loadarg = false;
+     myname = basename(*argv);
+@@ -2305,7 +2306,9 @@
+     argv += optind;
+     argc -= optind;
+-    if (!argc && del)
++    if (argc)
++      loadarg = true;
++    else if (del)
+       error("usage: %s [[-r] init_script|init_directory]\n", myname);
+     if (*argv) {
+@@ -2490,17 +2493,45 @@
+     /*
+      * Scan now all scripts found in the init.d/ directory
+      */
+-    while ((d = readdir(initdir)) != (struct dirent*)0) {
+-      const boolean isarg = chkfor(d->d_name, argv, argc);
++    for (;;) {
+       service_t * service = (service_t*)0;
+       char * token;
+       char * begin = (char*)0;        /* hold start pointer of strings handled by strsep() */
+       boolean hard = false;
++      boolean isarg = false;
+       uchar lsb = 0;
+ #if defined(DEBUG) && (DEBUG > 0)
+       int nobug = 0;
+ #endif
++      if ((d = readdir(initdir)) == (struct dirent*)0) {
++          /*
++           * If first script in argument list was loaded in advance, then
++           * rewind the init.d/ directory stream and attempt to load all
++           * other scripts.
++           */
++          if (loadarg) {
++              loadarg = false;
++              rewinddir(initdir);
++              continue;
++          }
++          break;
++      }
++
++      isarg = chkfor(d->d_name, argv, argc);
++
++      /*
++       * Load first script in argument list before all other scripts. This
++       * avoids problems with loading scripts in underterministic sequence
++       * returned by readdir(3).
++       */
++      if (loadarg && !isarg)
++          continue;
++      if (loadarg  && isarg && (curr_argc != 0))
++          continue;
++      if (!loadarg && isarg && (curr_argc == 0))
++          continue;
++
+       if (*d->d_name == '.')
+           continue;
+       errno = 0;
diff --git a/debian/patches/40_badboy_segfault.patch b/debian/patches/40_badboy_segfault.patch
new file mode 100644 (file)
index 0000000..cd36055
--- /dev/null
@@ -0,0 +1,21 @@
+Purpose: Defend against corrupt or invalid scripts living in
+         /etc/rc[S0-6].d/
+Fixes:   #493202
+Status:  Acked by upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:44.000000000 +0200
+@@ -1696,6 +1696,11 @@
+           }
+           lsb = scan_script_defaults(dfd, d->d_name, override_path, &name, true, ignore);
++          if (!name) {
++              warn("warning: script is corrupt or invalid: %s/%s%s\n", path, rcd, d->d_name);
++              continue;
++          }
++
+           if (!script_inf.provides || script_inf.provides == empty)
+               script_inf.provides = xstrdup(ptr);
diff --git a/debian/patches/50_symlink_in_initddir.patch b/debian/patches/50_symlink_in_initddir.patch
new file mode 100644 (file)
index 0000000..11ee33e
--- /dev/null
@@ -0,0 +1,67 @@
+Purpose: Defend against symlinks in init.d/ to other scripts in init.d/
+Fixes:   #485045
+Status:  Work in progress.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:44.000000000 +0200
+@@ -2542,11 +2542,12 @@
+       errno = 0;
+       /* d_type seems not to work, therefore use (l)stat(2) */
+-      if (xstat(dfd, d->d_name, &st_script) < 0) {
++      if (xlstat(dfd, d->d_name, &st_script) < 0) {
+           warn("can not stat(%s)\n", d->d_name);
+           continue;
+       }
+-      if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode))
++      if ((!S_ISLNK(st_script.st_mode) && !S_ISREG(st_script.st_mode)) ||
++          !(S_IXUSR & st_script.st_mode))
+       {
+           if (S_ISDIR(st_script.st_mode))
+               continue;
+@@ -2555,6 +2556,43 @@
+           continue;
+       }
++      /*
++       * Do extra sanity checking of symlinks in init.d/ dir, except if it
++       * is named reboot, as that is a special case on SUSE
++       */
++      if (S_ISLNK(st_script.st_mode) && ((strcmp(d->d_name, "reboot") != 0)))
++      {
++          char * base;
++          char linkbuf[PATH_MAX+1];
++          int  linklen;
++
++          linklen = xreadlink(dfd, d->d_name, linkbuf, sizeof(linkbuf)-1);
++          if (linklen < 0)
++              continue;
++          linkbuf[linklen] = '\0';
++
++          /* skip symbolic links to other scripts in this relative path */
++          if (!(base = strrchr(linkbuf, '/'))) {
++              if (isarg)
++                  warn("script %s is a symlink to another script, skipped!\n",
++                       d->d_name);
++              continue;
++          }
++
++          /* stat the symlink target and make sure it is a valid script */
++          if (xstat(dfd, d->d_name, &st_script) < 0)
++              continue;
++
++          if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode)) {
++              if (S_ISDIR(st_script.st_mode))
++                  continue;
++              if (isarg)
++                  warn("script %s is not an executable regular file, skipped!\n",
++                       d->d_name);
++              continue;
++          }
++      }
++
+       if (!strncmp(d->d_name, "README", strlen("README"))) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
diff --git a/debian/patches/60_all_keyword_start_only.patch b/debian/patches/60_all_keyword_start_only.patch
new file mode 100644 (file)
index 0000000..dafea55
--- /dev/null
@@ -0,0 +1,22 @@
+Purpose: Prevent Required-Stop: $all from modifying start links
+Fixes:   #485307
+Status:  Work in progress.
+---
+--- a/insserv.c
++++ b/insserv.c
+@@ -291,8 +291,13 @@
+           break;
+       case '$':
+           if (strcasecmp(token, "$all") == 0) {
+-              serv->attr.flags |= SERV_ALL;
+-              break;
++              if (bit & REQ_KILL) {
++                  /* $all has no effect on stop sort order */
++                  break;
++              } else {
++                  serv->attr.flags |= SERV_ALL;
++                  break;
++              }
+           }
+           /* Expand the `$' token recursively down */
+           list_for_each(ptr, sysfaci_start) {
diff --git a/debian/patches/61_interactive_keyword.patch b/debian/patches/61_interactive_keyword.patch
new file mode 100644 (file)
index 0000000..3d85384
--- /dev/null
@@ -0,0 +1,132 @@
+Purpose: Add support for a X-Interactive keyword to avoid specifying it in insserv.conf
+Fixes:   #458224
+Status:  Work in progress.
+---
+
+Index: insserv/insserv.8.in
+===================================================================
+--- insserv.orig/insserv.8.in  2009-09-26 22:35:25.000000000 +0200
++++ insserv/insserv.8.in       2009-09-26 22:35:43.000000000 +0200
+@@ -76,6 +76,7 @@
+  # X-Stop-After:      boot_facility_1 [ boot_facility_2 ...]
+  # Default-Start:     run_level_1 [ run_level_2 ...]
+  # Default-Stop:      run_level_1 [ run_level_2 ...]
++ # X-Interactive:     true
+  # Short-Description: single_line_description
+  # Description:       multiline_description
+  ### END INIT INFO
+@@ -117,6 +118,11 @@
+ these tags is stopped.
+ @@END_SUSE@@
+ .PP
++The optional X\-Interactive keyword implies that the script using this
++keyword should be started alone in a concurrent boot configuration
++because it interact with the user at the console.  Only the value
++`true' is recogniced.  All other are ignored.
++.PP
+ The optional
+ .B X\-Start\-Before
+ keyword implies that the script using this keyword
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:43.000000000 +0200
+@@ -97,6 +97,7 @@
+ #define DEFAULT_START DEFAULT  START VALUE
+ #define DEFAULT_STOP  DEFAULT  STOP  VALUE
+ #define DESCRIPTION   COMM "description" VALUE
++#define INTERACTIVE   COMM "x-interactive" VALUE
+ /* System facility search within /etc/insserv.conf */
+ #define EQSIGN                "([[:blank:]]*[=:][[:blank:]]*|[[:blank:]]+)"
+@@ -133,6 +134,7 @@
+     char *default_start;
+     char *default_stop;
+     char *description;
++    char *interactive;
+ } attribute((aligned(sizeof(char*)))) lsb_t;
+ /* Search results points here */
+@@ -147,6 +149,7 @@
+     regex_t def_start;
+     regex_t def_stop;
+     regex_t desc;
++    regex_t interact;
+ } attribute((aligned(sizeof(regex_t)))) reg_t;
+ typedef struct creg_struct {
+@@ -1132,6 +1135,7 @@
+     regcompiler(&reg.def_start, DEFAULT_START,  REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+     regcompiler(&reg.def_stop,  DEFAULT_STOP,   REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+     regcompiler(&reg.desc,      DESCRIPTION,    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
++    regcompiler(&reg.interact,  INTERACTIVE,    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ }
+ static inline void scan_script_reset(void) attribute((always_inline));
+@@ -1147,6 +1151,7 @@
+     xreset(script_inf.default_start);
+     xreset(script_inf.default_stop);
+     xreset(script_inf.description);
++    xreset(script_inf.interactive);
+ }
+ #define FOUND_LSB_HEADER   0x01
+@@ -1177,6 +1182,7 @@
+ #define default_start script_inf.default_start
+ #define default_stop  script_inf.default_stop
+ #define description   script_inf.description
++#define interactive   script_inf.interactive
+     info("Loading %s\n", path);
+@@ -1273,6 +1279,14 @@
+               description = empty;
+       }
++      if (!interactive    && regexecutor(&reg.interact,      COMMON_ARGS) == true) {
++          if (val->rm_so < val->rm_eo) {
++              *(pbuf+val->rm_eo) = '\0';
++              interactive = xstrdup(pbuf+val->rm_so);
++          } else
++              interactive = empty;
++      }
++
+       /* Skip scanning below from LSB magic end */
+       if ((end = strstr(buf, "### END INIT INFO")))
+           break;
+@@ -1341,6 +1355,7 @@
+ #undef default_start
+ #undef default_stop
+ #undef description
++#undef interactive
+     return ret;
+ }
+@@ -1503,6 +1518,7 @@
+     regfree(&reg.def_start);
+     regfree(&reg.def_stop);
+     regfree(&reg.desc);
++    regfree(&reg.interact);
+ }
+ static struct {
+@@ -1781,6 +1797,9 @@
+               if (script_inf.stop_after && script_inf.stop_after != empty) {
+                   reversereq(service, REQ_SHLD|REQ_KILL, script_inf.stop_after);
+               }
++              if (script_inf.interactive && 0 == strcmp(script_inf.interactive, "true")) {
++                  service->attr.flags |= SERV_INTRACT;
++              }
+           }
+           if (name) 
+@@ -2881,6 +2900,9 @@
+                       if (script_inf.should_stop && script_inf.should_stop != empty) {
+                           rememberreq(service, REQ_SHLD|REQ_KILL, script_inf.should_stop);
+                       }
++                      if (script_inf.interactive && 0 == strcmp(script_inf.interactive, "true")) {
++                          service->attr.flags |= SERV_INTRACT;
++                      }
+                   }
+                   if (script_inf.start_before && script_inf.start_before != empty) {
diff --git a/debian/patches/62_upstart_job.patch b/debian/patches/62_upstart_job.patch
new file mode 100644 (file)
index 0000000..2c0570e
--- /dev/null
@@ -0,0 +1,170 @@
+Purpose: Add support for upstart jobs.
+Fixes:   #547235
+Status:  Work in progress, not submitted upstream yet.
+---
+
+Index: insserv/insserv.8.in
+===================================================================
+--- insserv.orig/insserv.8.in  2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.8.in       2009-09-26 22:35:42.000000000 +0200
+@@ -266,6 +266,10 @@
+ .BR \-f ,\  \-\-force
+ Ignore if a required service is missed.
+ .TP
++.BR \-u\ <path> ,\  \-\-upstart-job\ <path>
++Path to replace existing upstart job path.  (default path is
++.IR /lib/init/upstart-job ).
++.TP
+ .BR \-h ,\  \-\-help
+ Print out short usage message.
+ .PP
+@@ -339,6 +343,12 @@
+ name as the boot or init script in the directory
+ .IR /etc/insserv/overrides/ .
+ .\"
++.SH UPSTART JOB COMPATIBILITY
++To allow upstart jobs to work as init.d scripts, insserv will
++recognize a symlink from path/to/init.d/script to
++/lib/init/upstart-job as upstart jobs, and instead of reading the
++header from the file will run the script with the argument lsb-header
++to get the script header.
+ .SH EXIT CODES
+ The exit codes have the following conditions:
+ .RS 7
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:43.000000000 +0200
+@@ -70,6 +70,8 @@
+ # define INSCONF      "/etc/insserv.conf"
+ #endif
++const char *upstartjob_path = "/lib/init/upstart-job";
++
+ /*
+  * For a description of regular expressions see regex(7).
+  */
+@@ -1154,6 +1156,43 @@
+     xreset(script_inf.interactive);
+ }
++static char *is_upstart_job_recursive(const char *path,
++                                    const char *basenamestr)
++{
++    struct stat statbuf;
++    if (-1 == lstat(path, &statbuf)) {
++      return 0;
++    }
++    if (S_ISLNK(statbuf.st_mode)) {
++        char buf[2048];
++        int len = readlink(path, buf, sizeof(buf)-1);
++      if (0 < len) {
++          buf[len] = '\0';
++          if (0 == strcmp(buf, upstartjob_path)) {
++            /* upstart job, return base name of original symlink */
++            return strdup(basenamestr);
++          } else
++            return is_upstart_job_recursive(buf, basenamestr);
++      }
++    }
++    return 0;
++}
++
++/*
++ * return name of upstart job if the script is a symlink to
++ * /lib/init/upstart-job, or NULL if path do not point to an
++ * upstart job.
++ */
++static char* is_upstart_job(const char *path)
++{
++
++    char *basenamestr = basename(path); /* GNU basename */
++    char *retval = is_upstart_job_recursive(path, basenamestr);
++    if (retval)
++        info("script '%s' is upstart job\n", basenamestr);
++    return retval;
++}
++
+ #define FOUND_LSB_HEADER   0x01
+ #define FOUND_LSB_DEFAULT  0x02
+ #define FOUND_LSB_OVERRIDE 0x04
+@@ -1170,7 +1209,8 @@
+     char *pbuf = buf;
+     FILE *script;
+     uchar ret = 0;
+-    int fd;
++    int fd = -1;
++    char *upstart_job = NULL;
+ #define provides      script_inf.provides
+ #define required_start        script_inf.required_start
+@@ -1186,12 +1226,23 @@
+     info("Loading %s\n", path);
+-    if ((fd = xopen(dfd, path, o_flags)) < 0 || (script = fdopen(fd, "r")) == (FILE*)0)
+-      error("fopen(%s): %s\n", path, strerror(errno));
++    if (NULL != (upstart_job = is_upstart_job(path))) {
++        char cmd[2048];
++      int len;
++      len = snprintf(cmd, sizeof(cmd),
++                     "%s %s lsb-header", upstartjob_path, upstart_job);
++      if (len < 0 || sizeof(cmd) == len)
++          error("snprintf: insufficient buffer for %s\n", path);
++      if ((FILE*)0 == (script = popen(cmd, "r")))
++          error("popen(%s): %s\n", path, strerror(errno));
++    } else {
++        if ((fd = xopen(dfd, path, o_flags)) < 0 || (script = fdopen(fd, "r")) == (FILE*)0)
++          error("fopen(%s): %s\n", path, strerror(errno));
+ #if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+-    (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
++      (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ #endif
++    }
+ #define COMMON_ARGS   buf, SUBNUM, subloc, 0
+ #define COMMON_SHD_ARGS       buf, SUBNUM_SHD, subloc, 0
+@@ -1303,7 +1354,12 @@
+       (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
+ #endif
+-    fclose(script);
++    if (upstart_job) {
++        pclose(script);
++        free(upstart_job);
++        upstart_job = 0;
++    } else
++        fclose(script);
+     if (begin && end)
+       ret |= FOUND_LSB_HEADER;
+@@ -2224,6 +2280,7 @@
+     {"force", 0, (int*)0, 'f'},
+     {"path",  1, (int*)0, 'p'},
+     {"override",1, (int*)0, 'o'},
++    {"upstart-job",1, (int*)0, 'u'},
+     {"help",  0, (int*)0, 'h'},
+     { 0,      0, (int*)0,  0 },
+ };
+@@ -2277,7 +2334,7 @@
+     for (c = 0; c < argc; c++)
+       argr[c] = (char*)0;
+-    while ((c = getopt_long(argc, argv, "c:dfrhvno:p:", long_options, (int *)0)) != -1) {
++    while ((c = getopt_long(argc, argv, "c:dfrhvno:p:u:", long_options, (int *)0)) != -1) {
+       size_t l;
+       switch (c) {
+           case 'c':
+@@ -2317,6 +2374,11 @@
+               override_path = optarg;
+               set_override = true;
+               break;
++          case 'u':
++              if (optarg == (char*)0 || *optarg == '\0')
++                  goto err;
++              upstartjob_path = optarg;
++              break;
+           case '?':
+           err:
+               error("For help use: %s -h\n", myname);
diff --git a/debian/patches/70_req_start_all_depends.patch b/debian/patches/70_req_start_all_depends.patch
new file mode 100644 (file)
index 0000000..2144003
--- /dev/null
@@ -0,0 +1,30 @@
+Purpose: Correct dependency information written to .depend.* files
+         for scripts which declare Required-Start: $all
+Fixes:   nil
+Status:  Applied upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:42.000000000 +0200
+@@ -776,9 +776,6 @@
+           continue;
+ #endif /* not MINIMAL_RULES */
+-      if (list_empty(&serv->sort.req))
+-          continue;
+-
+       if (serv->start->lvl & LVL_BOOT)
+           out = boot;
+       else
+@@ -820,6 +817,10 @@
+               fprintf(out, " %s", name);
+           }
+       } else {
++
++          if (list_empty(&serv->sort.req))
++              continue;
++
+           np_list_for_each(pos, &serv->sort.req) {
+               req_t * req = getreq(pos);
+               service_t * dep = req->serv;
diff --git a/debian/patches/71_complete_makefile.patch b/debian/patches/71_complete_makefile.patch
new file mode 100644 (file)
index 0000000..7b13a54
--- /dev/null
@@ -0,0 +1,56 @@
+Purpose: Make sure the .depend.* files have complete dependencies when
+         recursive virtual facilities are used.
+Fixes:   #534526
+Status:  From upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:42.000000000 +0200
+@@ -2109,33 +2109,26 @@
+           goto out;
+       }
+-      if ((*deep)++ > 10) {
+-          warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
+-          goto out;
+-      }
+-
+       list_for_each_safe(tmp, safe, ptr) {
+           repl_t * rnxt = getrepl(tmp);
+           if (*rnxt->r[0].name == '$') {
+-              expand_faci(tmp, head, deep);
+-          } else {
+-              if (*deep == 1) {
+-                  if (--(*rent->r[0].ref) <= 0)
+-                      free(rent->r[0].ref);
+-                  rent->r[0] = rnxt->r[0];
+-                  ++(*rent->r[0].ref);
+-              } else {
+-                  repl_t *restrict subst;
+-                  if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+-                      error("%s", strerror(errno));
+-                  insert(&subst->r_list, head);
+-                  subst->r[0] = rnxt->r[0];
+-                  ++(*subst->r[0].ref);
++              if (*deep > 10) {
++                  warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
++                  goto out;
+               }
++              (*deep)++;
++              expand_faci(tmp, head, deep);
++              (*deep)--;
++          } else if (*deep > 0) {
++              repl_t *restrict subst;
++              if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
++                  error("%s", strerror(errno));
++              insert(&subst->r_list, head->prev);
++              subst->r[0] = rnxt->r[0];
++              (*subst->r[0].ref) = 1;
+           }
+       }
+ out:
+-      (*deep)--;
+       return;
+ }
diff --git a/debian/patches/80_manual_warnings.patch b/debian/patches/80_manual_warnings.patch
new file mode 100644 (file)
index 0000000..176780d
--- /dev/null
@@ -0,0 +1,114 @@
+Purpose: Fix format warnings of manual page
+Fixes:   lintian - manpage-has-errors-from-man
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.8.in
+===================================================================
+--- insserv.orig/insserv.8.in  2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.8.in       2009-09-26 22:35:41.000000000 +0200
+@@ -12,11 +12,9 @@
+ @@BEGIN_SUSE@@
+ .TH INSSERV 8 "Jul 29, 2008" "Version 1.11" "The SuSE boot concept"
+ .UC 8
+-.OS SuSE Linux
+ @@ELSE_SUSE@@
+ .TH INSSERV 8 "Jul 29, 2008" "Version 1.11"
+ .UC 8
+-.OS Debian
+ @@END_SUSE@@
+ .SH NAME
+ insserv \- Enable an installed system init script
+@@ -35,9 +33,9 @@
+ .RB [ \-c\ <config> ]
+ .RB [ \-p\ <path> ]
+ @@BEGIN_SUSE@@
+-.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2>\ ... ]
++.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1,lvl2,...> ]
+ @@ELSE_SUSE@@
+-.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2>\ ... ] ,stop=<lvl1> [ ,<lvl2>\ ... ]]
++.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1,lvl2,...> ,stop=<lvl1,lvl2,...> ]
+ @@END_SUSE@@
+ .PP
+ .B insserv
+@@ -129,7 +127,7 @@
+ should be started
+ .B before
+ the specified service names.
+-Wereas the optional
++Whereas the optional
+ .B X\-Stop\-After
+ keyword implies that the script using this keyword
+ should be stopped
+@@ -223,7 +221,7 @@
+ a passphrase or password input during boot
+ or runlevel change.
+ .P
+-Beside the defined
++In addition to the defined
+ .B System Facilities
+ in the configuration file
+ .IR /etc/insserv.conf ,
+@@ -246,8 +244,8 @@
+ directory.  Useful for testing.
+ .TP
+ .BR \-o\ <path> ,\  \-\-override\ <path>
+-Path to replace existing LSB comment headers with the comment
+-headers found in this path (default path is
++LSB comment headers found in this path will override existing
++LSB comment headers of scripts in the init.d directory (default path is
+ .IR /etc/insserv/overrides/ ).
+ .TP
+ .BR \-p\ <path> ,\  \-\-path\ <path>
+@@ -260,7 +258,7 @@
+ Remove the listed scripts from all runlevels.
+ .TP
+ .BR \-d ,\  \-\-default
+-Use default runlevels a defined in the scripts.
++Use default runlevels as defined in the scripts.
+ This may restore an edited runlevel link scheme.
+ .TP
+ .BR \-f ,\  \-\-force
+@@ -307,17 +305,16 @@
+ For the runlevels the information found in
+ the script is used.
+ .TP
+-.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2> ]]\ ...
++.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1,lvl2,...> ]
+ List of scripts which have to be added to
+ the specified runlevels to be started with.
+ You may use this extension to override the default values
+ for start and stop runlevels of the script.
+ Note that
+-.BR <lvl1> ,\  <lvl2> ,\ ...
++.BR lvl1 ,\  lvl2 ,\ ...
+ are the known runlevels explained above.
+ The extension
+-.IR ,stop=<lvl1> [ ,<lvl2> ]]
+-is possible
++.IR ,stop=<lvl1,lvl2,...>
+ @@BEGIN_SUSE@@
+ is possible but ignored on SuSE Linux.
+ @@ELSE_SUSE@@
+@@ -334,9 +331,9 @@
+ .\"
+ .SH OVERRIDES
+ Beside using the extensions
+-.IR ,start=<lvl1> [ ,<lvl2> ]]
++.IR ,start=<lvl1,lvl2,...>
+ and
+-.IR ,stop=<lvl1> [ ,<lvl2> ]]
++.IR ,stop=<lvl1,lvl2,...>
+ it is possible to use override files replace a LSB comment header
+ or simple provide a missing LSB comment header.  This can be done
+ by placing a file with the new LSB comment header using the same
+@@ -395,7 +392,9 @@
+ .sp 1
+ will be ignored.
+ .SH BUGS
+-Boot script sometimes misses comments.
++Boot scripts sometimes lack a LSB comment header. Contact a package
++maintainer or developer of the software which provides the script to
++have a LSB comment header added to it.
+ .SH FILES
+ .TP
+ .I /etc/insserv.conf
diff --git a/debian/patches/81_lessverbose.patch b/debian/patches/81_lessverbose.patch
new file mode 100644 (file)
index 0000000..e8ed476
--- /dev/null
@@ -0,0 +1,157 @@
+Purpose: Reduce verbosity level (drop Loading... messages)
+Fixes:   -
+Status:  Not yet submitted upstream.
+---
+
+Index: insserv/listing.h
+===================================================================
+--- insserv.orig/listing.h     2009-09-26 22:35:25.000000000 +0200
++++ insserv/listing.h  2009-09-26 22:35:39.000000000 +0200
+@@ -283,7 +283,7 @@
+ extern const char *const delimeter;
+ extern void error(const char *restrict fmt, ...) attribute((noreturn,format(printf,1,2)));
+ extern void warn (const char *restrict fmt, ...) attribute((format(printf,1,2)));
+-extern void info (const char *restrict fmt, ...) attribute((format(printf,1,2)));
++extern void info (int level, const char *restrict fmt, ...) attribute((format(printf,2,3)));
+ extern inline int map_has_runlevels(void) attribute((always_inline));
+ extern inline char map_runlevel_to_key(const int runlevel);
+ extern inline ushort map_key_to_lvl(const char key);
+@@ -312,23 +312,23 @@
+       (unlinkat(d,x,0) != 0 && (errno != EISDIR || unlinkat(d,x,AT_REMOVEDIR) != 0)))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+       else \
+-      info("remove service %s/%s%s\n", path, rcd, x); }))
++      info(1, "remove service %s/%s%s\n", path, rcd, x); }))
+ #else
+ # define xremove(d,x) (__extension__ ({ if ((dryrun ? 0 : (remove(x) != 0))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+       else \
+-      info("remove service %s/%s%s\n", path, rcd, x); }))
++      info(1, "remove service %s/%s%s\n", path, rcd, x); }))
+ #endif
+ #if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE)
+ # define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlinkat(x, d, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+-      info("enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
++      info(1, "enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+ #else
+ # define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlink(x, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+-      info("enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
++      info(1, "enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+ #endif
+ #if defined(HAS_fstatat) && defined(_ATFILE_SOURCE)
+ # define xstat(d,x,s) (__extension__ ({ fstatat(d,x,s, 0); }))
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:41.000000000 +0200
+@@ -114,8 +114,8 @@
+ /* The main line buffer if unique */
+ static char buf[LINE_MAX];
+-/* When to be verbose */
+-static boolean verbose = false;
++/* When to be verbose, and what level of verbosity */
++static int verbose = 0;
+ /* When to be verbose */
+ static boolean dryrun = false;
+@@ -690,9 +690,9 @@
+     if (dryrun) {
+ #ifdef USE_KILL_IN_BOOT
+-      info("dryrun, not creating .depend.boot, .depend.start, .depend.halt, and .depend.stop\n");
++      info(1, "dryrun, not creating .depend.boot, .depend.start, .depend.halt, and .depend.stop\n");
+ #else  /* not USE_KILL_IN_BOOT */
+-      info("dryrun, not creating .depend.boot, .depend.start, and .depend.stop\n");
++      info(1, "dryrun, not creating .depend.boot, .depend.start, and .depend.stop\n");
+ #endif /* not USE_KILL_IN_BOOT */
+       return;
+     }
+@@ -707,8 +707,8 @@
+       return;
+     }
+-    info("creating .depend.boot\n");
+-    info("creating .depend.start\n");
++    info(1, "creating .depend.boot\n");
++    info(1, "creating .depend.start\n");
+     lsort('S');                                       /* Sort into start order, set new sorder */
+@@ -874,9 +874,9 @@
+       return;
+     }
+-    info("creating .depend.halt\n");
++    info(1, "creating .depend.halt\n");
+ #endif /* USE_KILL_IN_BOOT */
+-    info("creating .depend.stop\n");
++    info(1, "creating .depend.stop\n");
+     lsort('K');                                       /* Sort into stop order, set new korder */
+@@ -1014,9 +1014,9 @@
+ /*
+  * Print message when verbose is enabled
+  */
+-void info(const char *fmt, ...) {
++void info(int level, const char *fmt, ...) {
+     va_list ap;
+-    if (!verbose)
++    if (level > verbose)
+       goto out;
+     va_start(ap, fmt);
+     _logger(fmt, ap);
+@@ -1062,7 +1062,7 @@
+     if (stat(rcpath, &st) < 0) {
+       if (errno == ENOENT) {
+-          info("creating directory '%s'\n", rcpath);
++          info(1, "creating directory '%s'\n", rcpath);
+           if (!dryrun)
+               mkdir(rcpath, (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH));
+       } else
+@@ -1190,7 +1190,7 @@
+     char *basenamestr = basename(path); /* GNU basename */
+     char *retval = is_upstart_job_recursive(path, basenamestr);
+     if (retval)
+-        info("script '%s' is upstart job\n", basenamestr);
++        info(2, "script '%s' is upstart job\n", basenamestr);
+     return retval;
+ }
+@@ -1225,7 +1225,7 @@
+ #define description   script_inf.description
+ #define interactive   script_inf.interactive
+-    info("Loading %s\n", path);
++    info(2, "Loading %s\n", path);
+     if (NULL != (upstart_job = is_upstart_job(path))) {
+         char cmd[2048];
+@@ -1882,7 +1882,7 @@
+     regmatch_t subloc[SUBCONFNUM], *val = (regmatch_t*)0;
+     FILE *conf;
+-    info("Loading %s\n", file);
++    info(2, "Loading %s\n", file);
+     do {
+       const char * fptr = file;
+@@ -2347,10 +2347,10 @@
+               ignore = true;
+               break;
+           case 'v':
+-              verbose = true;
++              verbose ++;
+               break;
+           case 'n':
+-              verbose = true;
++              verbose ++;
+               dryrun = true;
+               break;
+           case 'p':
diff --git a/debian/patches/82_loop_exit_msg.patch b/debian/patches/82_loop_exit_msg.patch
new file mode 100644 (file)
index 0000000..2c8dd66
--- /dev/null
@@ -0,0 +1,20 @@
+Purpose: Make message printed when loops are detected look more like
+         the messages printed when other errors are detected ("exiting
+         now!"), to make it easier for piuparts to discover these errors too.
+Fixes:   -
+Status:  Not yet submitted upstream.
+---
+
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:41.000000000 +0200
+@@ -3250,7 +3250,7 @@
+      */
+     follow_all();
+     if (is_loop_detected() && !ignore)
+-      error("exiting without changing boot order!\n");
++      error("exiting now without changing boot order!\n");
+     /*
+      * Be sure that interactive scripts are the only member of
diff --git a/debian/patches/90_no_runlevel_spec_for_debian.patch b/debian/patches/90_no_runlevel_spec_for_debian.patch
new file mode 100644 (file)
index 0000000..bf145eb
--- /dev/null
@@ -0,0 +1,33 @@
+Purpose: Debian runlevels are a bit different to SUSE.
+Fixes:   #500542
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.8.in
+===================================================================
+--- insserv.orig/insserv.8.in  2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.8.in       2009-09-26 22:35:39.000000000 +0200
+@@ -143,6 +143,7 @@
+ @@ELSE_SUSE@@
+ directories.
+ @@END_SUSE@@
++@@BEGIN_SUSE@@
+ Known runlevels are:
+ .sp 1
+ .in +1l
+@@ -154,15 +155,12 @@
+  \fB4\fR\   reserved for local use
+  \fB5\fR\   used for full multiuser with network and xdm
+  \fB6\fR\   used for System reboot
+-@@BEGIN_SUSE@@
+  \fBS\fR\   used during boot into single user mode
+  \fBB\fR\   used during boot before any other runlevel
+-@@ELSE_SUSE@@
+- \fBS\fR\   used during boot before any other runlevel
+-@@END_SUSE@@
+ .fi
+ .in -1l
+ .sp 1
++@@END_SUSE@@
+ .PP
+ .B insserv
+ scans for
diff --git a/debian/patches/91_kfreebsd_nofadvice.patch b/debian/patches/91_kfreebsd_nofadvice.patch
new file mode 100644 (file)
index 0000000..ec8a447
--- /dev/null
@@ -0,0 +1,22 @@
+Purpose: Get insserv building on kfreebsd, missing the argument values for posix_fadvise().
+Fixes:   #?
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:40.000000000 +0200
+@@ -40,6 +40,13 @@
+ #endif /* USE_RPMLIB */
+ #include "listing.h"
++#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
++/* kfreebsd fail to provide working posix_fadvise */
++#  ifndef POSIX_FADV_SEQUENTIAL
++#    define posix_fadvise(fd, off, len, adv)        (-1)
++#  endif
++#endif
++
+ #ifdef SUSE
+ # define DEFAULT_START_LVL    "3 5"
+ # define DEFAULT_STOP_LVL     "3 5"
diff --git a/debian/patches/92_m68k_alignment.patch b/debian/patches/92_m68k_alignment.patch
new file mode 100644 (file)
index 0000000..ef4fe3c
--- /dev/null
@@ -0,0 +1,20 @@
+Purpose: Get insserv building on m68k, dropping some problematic
+         alignments (error: requested alignment is not a power of 2)
+Fixes:   #493637
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:40.000000000 +0200
+@@ -131,6 +131,10 @@
+ static boolean set_override = false;
+ static boolean set_insconf = false;
++#ifdef __m68k__ /* Fix #493637 */
++#  define aligned(a)
++#endif
++
+ /* Search results points here */
+ typedef struct lsb_struct {
+     char *provides;
diff --git a/debian/patches/93_hurd_no_path_max.patch b/debian/patches/93_hurd_no_path_max.patch
new file mode 100644 (file)
index 0000000..bad0d1a
--- /dev/null
@@ -0,0 +1,19 @@
+Purpose: Try to get insserv building on hurd, by faking a PATH_MAX value.
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:40.000000000 +0200
+@@ -1427,6 +1427,11 @@
+     return ret;
+ }
++#ifndef PATH_MAX
++/* for example hurd.  Should really dynamically aligh the buffer. */
++# define PATH_MAX 1024
++#endif
++
+ /*
+  * Follow symlinks, return the basename of the file pointed to by
+  * symlinks or the basename of the current path if no symlink.
diff --git a/debian/patches/94_v1_12_2.patch b/debian/patches/94_v1_12_2.patch
new file mode 100644 (file)
index 0000000..7b6c970
--- /dev/null
@@ -0,0 +1,82 @@
+Patch from upstream to detect and reject loops in virtual
+facilities (#541613) and warn about indirect dependencies to $all.
+
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:39.000000000 +0200
+@@ -233,6 +233,7 @@
+ typedef struct repl {
+     list_t     r_list;
+     string_t   r[1];
++    ushort    flags;
+ } __align repl_t;
+ #define getrepl(arg)  list_entry((arg), struct repl, r_list)
+@@ -1946,6 +1947,7 @@
+                               if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+                                   error("%s", strerror(errno));
+                               insert(&subst->r_list, r_list->prev);
++                              subst->flags = 0;
+                               r = &subst->r[0];
+                               if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
+                                   error("%s", strerror(errno));
+@@ -1975,6 +1977,7 @@
+                               error("%s", strerror(errno));
+                           insert(&subst->r_list, r_list->prev);
+                           r = &subst->r[0];
++                          subst->flags = 0;
+                           if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
+                               error("%s", strerror(errno));
+                           *r->ref = 1;
+@@ -2127,13 +2130,19 @@
+       list_for_each_safe(tmp, safe, ptr) {
+           repl_t * rnxt = getrepl(tmp);
++          if (rnxt->flags & 0x0001) {
++              error("Loop detected during expanding system facilities in the insserv.conf file(s): %s\n",
++                    rnxt->r[0].name);
++          }
+           if (*rnxt->r[0].name == '$') {
+               if (*deep > 10) {
+                   warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
+                   goto out;
+               }
+               (*deep)++;
++              rnxt->flags |= 0x0001;
+               expand_faci(tmp, head, deep);
++              rnxt->flags &= ~0x0001;
+               (*deep)--;
+           } else if (*deep > 0) {
+               repl_t *restrict subst;
+@@ -2154,9 +2163,12 @@
+     list_for_each(ptr, sysfaci_start) {
+       list_t * rlist, * safe, * head = &getfaci(ptr)->replace;
+       list_for_each_safe(rlist, safe, head) {
+-          if (*getrepl(rlist)->r[0].name == '$') {
++          repl_t * tmp = getrepl(rlist);
++          if (*tmp->r[0].name == '$') {
+               int deep = 0;
++              tmp->flags |= 0x0001;
+               expand_faci(rlist, rlist, &deep);
++              tmp->flags &= ~0x0001;
+           }
+       }
+     }
+Index: insserv/listing.c
+===================================================================
+--- insserv.orig/listing.c     2009-09-26 22:35:24.000000000 +0200
++++ insserv/listing.c  2009-09-26 22:35:39.000000000 +0200
+@@ -398,6 +398,12 @@
+               break;                          /* Loop detected, stop recursion */
+           }
++          if ((mode == 'S') && (attof(tmp)->flags & SERV_ALL)) {
++              warn("%s depends on %s and therefore on system facility `$all' which can not be true!\n",
++                   target->script ? target->script : target->name, tmp->script ? tmp->script : tmp->name);
++              continue;
++          }
++
+           if (ptrg->deep >= deep)             /* Nothing new */
+               continue;
+                                               /* The inner recursion */
diff --git a/debian/patches/95_stop_all.patch b/debian/patches/95_stop_all.patch
new file mode 100644 (file)
index 0000000..d78eb41
--- /dev/null
@@ -0,0 +1,159 @@
+Patch from upstream making $all work for stop sequences, placing
+scripts first in the stop sequence.  This patch invalidates
+60_all_keyword_start_only.patch
+
+Fixes #542043
+
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:39.000000000 +0200
+@@ -308,7 +308,10 @@
+           break;
+       case '$':
+           if (strcasecmp(token, "$all") == 0) {
+-              serv->attr.flags |= SERV_ALL;
++              if (bit & REQ_KILL)
++                  serv->attr.flags |= SERV_FIRST;
++              else
++                  serv->attr.flags |= SERV_ALL;
+               break;
+           }
+           /* Expand the `$' token recursively down */
+@@ -630,8 +633,7 @@
+ }
+ /*
+- * Last but not least the `$all' scripts will be set to the
+- * end of the current start order.
++ * The `$all' scripts will be set to the end of the current start order.
+  */
+ static inline void all_script(void) attribute((always_inline));
+ static inline void all_script(void)
+@@ -688,6 +690,50 @@
+ }
+ /*
++ * Last but not least the `$all' scripts will be set to the
++ * beginning of the current stop order.
++ */
++static inline void first_script(void) attribute((always_inline));
++static inline void first_script(void)
++{
++    list_t * pos;
++
++    list_for_each(pos, s_start) {
++      service_t * serv = getservice(pos);
++      list_t * tmp;
++
++      if (serv->attr.flags & SERV_DUPLET)
++          continue;                   /* Duplet */
++
++      if (!(serv->attr.flags & SERV_FIRST))
++          continue;
++
++      if (serv->attr.script == (char*)0)
++          continue;
++
++      list_for_each(tmp, s_start) {
++          service_t * cur = getservice(tmp);
++
++          if (cur->attr.flags & SERV_DUPLET)
++              continue;               /* Duplet */
++
++          if ((serv->start->lvl & cur->start->lvl) == 0)
++              continue;
++
++          if (cur == serv)
++              continue;
++
++          if (cur->attr.flags & SERV_FIRST)
++              continue;
++
++          rememberreq(serv, REQ_SHLD|REQ_KILL, cur->name);
++      }
++
++      setorder(serv->attr.script, 'K', 1, false);
++    }
++}
++
++/*
+  * Make the dependency files
+  */
+ static inline void makedep(void) attribute((always_inline));
+@@ -3274,6 +3320,11 @@
+     nonlsb_script();
+     /*
++     * Move the `$all' stop scripts to the very beginning
++     */
++    first_script();
++
++    /*
+      * Now generate for all scripts the dependencies
+      */
+     follow_all();
+Index: insserv/listing.c
+===================================================================
+--- insserv.orig/listing.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/listing.c  2009-09-26 22:35:39.000000000 +0200
+@@ -317,6 +317,7 @@
+     }
+     for (tmp = dir; tmp; tmp = getnextlink(l_list)) {
++      const typeof(attof(tmp)->flags) sflags = attof(tmp)->flags;
+       register boolean recursion = true;
+       handle_t * ptmp = (mode == 'K') ? &tmp->stopp : &tmp->start;
+       uchar  * order = &ptmp->deep;
+@@ -381,6 +382,7 @@
+       np_list_for_each(dent, l_list) {
+           dir_t * target = getlink(dent)->target;
+           handle_t * ptrg = (mode == 'K') ? &target->stopp : &target->start;
++          const typeof(attof(target)->flags) kflags = attof(target)->flags;
+           if ((peg->run.lvl & ptrg->run.lvl) == 0)
+               continue;                       /* Not same boot level */
+@@ -398,10 +400,18 @@
+               break;                          /* Loop detected, stop recursion */
+           }
+-          if ((mode == 'S') && (attof(tmp)->flags & SERV_ALL)) {
+-              warn("%s depends on %s and therefore on system facility `$all' which can not be true!\n",
+-                   target->script ? target->script : target->name, tmp->script ? tmp->script : tmp->name);
+-              continue;
++          if (mode == 'K') {
++              if (kflags & SERV_FIRST) {
++                  warn("Stopping %s depends on %s and therefore on system facility `$all' which can not be true!\n",
++                       tmp->script ? tmp->script : tmp->name, target->script ? target->script : target->name);
++                  continue;
++              }
++          } else {
++              if (sflags & SERV_ALL) {
++                  warn("Starting %s depends on %s and therefore on system facility `$all' which can not be true!\n",
++                       target->script ? target->script : target->name, tmp->script ? tmp->script : tmp->name);
++                  continue;
++              }
+           }
+           if (ptrg->deep >= deep)             /* Nothing new */
+@@ -847,7 +857,7 @@
+     list_for_each(tmp, d_start) {
+       maxorder = &maxstart;
+       guess_order(getdir(tmp), 'S');
+-      maxorder = &maxstart;
++      maxorder = &maxstop;
+       guess_order(getdir(tmp), 'K');
+     }
+ }
+Index: insserv/listing.h
+===================================================================
+--- insserv.orig/listing.h     2009-09-26 22:35:39.000000000 +0200
++++ insserv/listing.h  2009-09-26 22:35:39.000000000 +0200
+@@ -368,6 +368,7 @@
+ #define SERV_SCRIPT   0x0080
+ #define SERV_NOSTOP   0x0100
+ #define SERV_CMDLINE  0x0200
++#define SERV_FIRST    0x0400
+ /*
+  * Bits of the runlevels
diff --git a/debian/patches/96_hurd_no_at_funcs.patch b/debian/patches/96_hurd_no_at_funcs.patch
new file mode 100644 (file)
index 0000000..bcf2e75
--- /dev/null
@@ -0,0 +1,50 @@
+Purpose: Try to get insserv building on hurd, by avoiding the dummy *at
+         functions which exist in libc but always return an error.
+Status:  Not yet submitted upstream.
+
+---
+Index: insserv/listing.h
+===================================================================
+--- insserv.orig/listing.h     2009-09-27 15:45:38.000000000 +0200
++++ insserv/listing.h  2009-09-27 15:45:38.000000000 +0200
+@@ -307,7 +307,7 @@
+ #define xreset(ptr)   \
+       {char *restrict tmp = (char *restrict)ptr; if (ptr && *tmp) free(ptr);} ptr = NULL
+-#if defined(HAS_unlinkat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_unlinkat) && defined(_ATFILE_SOURCE) && !defined(__stub_unlinkat)
+ # define xremove(d,x) (__extension__ ({ if ((dryrun ? 0 : \
+       (unlinkat(d,x,0) != 0 && (errno != EISDIR || unlinkat(d,x,AT_REMOVEDIR) != 0)))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+@@ -319,7 +319,7 @@
+       else \
+       info(1, "remove service %s/%s%s\n", path, rcd, x); }))
+ #endif
+-#if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE) && !defined(__stub_symlinkat)
+ # define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlinkat(x, d, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+@@ -330,19 +330,19 @@
+       else \
+       info(1, "enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+ #endif
+-#if defined(HAS_fstatat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_fstatat) && defined(_ATFILE_SOURCE) && !defined(__stub_fstatat)
+ # define xstat(d,x,s) (__extension__ ({ fstatat(d,x,s, 0); }))
+ # define xlstat(d,x,s)        (__extension__ ({ fstatat(d,x,s, AT_SYMLINK_NOFOLLOW); }))
+ #else
+ # define xstat(d,x,s) (__extension__ ({ stat(x,s); }))
+ # define xlstat(d,x,s)        (__extension__ ({ lstat(x,s); }))
+ #endif
+-#if defined(HAS_readlinkat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_readlinkat) && defined(_ATFILE_SOURCE) && !defined(__stub_readlinkat)
+ # define xreadlink(d,x,b,l)   (__extension__ ({ readlinkat(d,x,b,l); }))
+ #else
+ # define xreadlink(d,x,b,l)   (__extension__ ({ readlink(x,b,l); }))
+ #endif
+-#if defined(HAS_openat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_openat) && defined(_ATFILE_SOURCE) && !defined(__stub_openat)
+ # define xopen(d,x,f) (__extension__ ({ openat(d,x,f); }))
+ #else
+ # define xopen(d,x,f) (__extension__ ({ open(x,f); }))
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644 (file)
index 0000000..4e4c68c
--- /dev/null
@@ -0,0 +1,22 @@
+10_nosuse.patch
+11_debian_conf.patch
+20_install_perms_fixup.patch
+21_tests_suite_new_functions.patch
+30_deterministic_order.patch
+40_badboy_segfault.patch
+50_symlink_in_initddir.patch
+#60_all_keyword_start_only.patch
+61_interactive_keyword.patch
+62_upstart_job.patch
+70_req_start_all_depends.patch 
+71_complete_makefile.patch
+80_manual_warnings.patch
+81_lessverbose.patch
+82_loop_exit_msg.patch
+90_no_runlevel_spec_for_debian.patch
+91_kfreebsd_nofadvice.patch
+92_m68k_alignment.patch
+93_hurd_no_path_max.patch
+94_v1_12_2.patch
+95_stop_all.patch
+96_hurd_no_at_funcs.patch
diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in
new file mode 100644 (file)
index 0000000..3b1150e
--- /dev/null
@@ -0,0 +1 @@
+[type: gettext/rfc822deb] insserv.templates
diff --git a/debian/po/cs.po b/debian/po/cs.po
new file mode 100644 (file)
index 0000000..4f4cd8f
--- /dev/null
@@ -0,0 +1,55 @@
+# Czech translation of insserv debconf messages.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the insserv package.
+# Miroslav Kure <kurem@debian.cz>, 2008
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-23 12:52+0100\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr "Povolit (nebo nechat povolené) zavádění založené na závislostech?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Povolíte-li zavádění založené na závislostech, budou skripty v /etc/rc*.d/ "
+"přeskládány na základě informací zapsaných v LSB hlavičkách těchto skriptů. "
+"(Pokud LSB informace chybí, použijí se výchozí hodnoty.) Všechny symbolické "
+"odkazy S* v rc0.d/ a rc6.d/ budou přejmenovány na K*, aby byly jejich názvy "
+"konzistentní se způsobem použití (volání s argumentem „stop“). Změna se "
+"provede pouze poté, co se ověří, že je převod bezpečný. Pokud je zavádění "
+"založené na závislostech povoleno, způsobí jeho vypnutí návrat do původního "
+"stavu."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Mějte prosím na paměti, že se jedná o experimentální vlastnost. Není "
+"zaručeno, že se pokus o návrat k původnímu systému zavádění podaří. V "
+"krajním případě bude možná nutné přeinstalovat celý systém."
diff --git a/debian/po/de.po b/debian/po/de.po
new file mode 100644 (file)
index 0000000..b20efd2
--- /dev/null
@@ -0,0 +1,62 @@
+# translation of insserv_1.11.0-8_de.po to German
+# Copyright (C) 2008, Erik Schanze <eriks@debian.org>
+# This file is distributed under the same license as the insserv package.
+#
+# Erik Schanze <eriks@debian.org>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv_1.11.0-8_de\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-05-04 00:19+0200\n"
+"Last-Translator: Erik Schanze <eriks@debian.org>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"Abhängigkeitsgestützte Reihenfolge beim Hochfahren aktivieren (oder "
+"aktiviert lassen)?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Wenn Sie hier zustimmen, werden alle Skripte im Verzeichnis /etc/rc*.d/ "
+"anhand der in jedem Skript enthaltenen Informationen über die Abhängigkeiten "
+"neu sortiert. Wenn diese Information fehlt, wird die Standardinformation "
+"über Abhängigkeiten benutzt. Es werden auch alle symbolischen Links »S*« in "
+"den Verzeichnissen rc0.d/ und rc6.d/ in symbolische Links »K*« umgewandelt, "
+"um sicher zu stellen, dass ihre Aufrufe (mit dem Argument »stop«) zu ihren "
+"Namen passen. Die Änderung wird nur vorgenommen, nachdem überprüft wurde, "
+"dass die Umwandlung sicher ist. Wenn Sie hier ablehnen, nachdem Sie schon "
+"einmal zugestimmt haben, wird versucht, die Änderungen zurückzunehmen."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Bitte beachten Sie, dass es sich um eine experimentelle "
+"Funktionalität handelt. Es gibt keine Garantie, dass man von einer "
+"abhängigkeitsgestützten zu einer nicht abhängigkeitsgestützten "
+"Reihenfolge des Hochfahrens sicher zurückzukehren kann. Eine "
+"Neuinstallation des Systems könnte erforderlich werden."
+
diff --git a/debian/po/es.po b/debian/po/es.po
new file mode 100644 (file)
index 0000000..7b3f573
--- /dev/null
@@ -0,0 +1,85 @@
+# insserv translation to spanish
+# Copyright (C) 2007 Software in the Public Interest, SPI Inc.
+# This file is distributed under the same license as the insserv package.
+#
+# Changes:
+# - Initial translation
+#      Steve Lord Flaubert , 2008
+#
+#
+#  Traductores, si no conoce el formato PO, merece la pena leer la 
+#  documentación de gettext, especialmente las secciones dedicadas a este
+#  formato, por ejemplo ejecutando:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+# Equipo de traducción al español, por favor lean antes de traducir
+# los siguientes documentos:
+#
+# - El proyecto de traducción de Debian al español
+#   http://www.debian.org/intl/spanish/
+#   especialmente las notas y normas de traducción en
+#   http://www.debian.org/intl/spanish/notas
+#
+# - La guía de traducción de po's de debconf:
+#   /usr/share/doc/po-debconf/README-trans
+#   o http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Si tiene dudas o consultas sobre esta traducción consulte con el último
+# traductor (campo Last-Translator) y ponga en copia a la lista de
+# traducción de Debian al español (<debian-l10n-spanish@lists.debian.org>)
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv 1.10.0-4\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-18 17:18-0500\n"
+"Last-Translator: Steve Lord Flaubert <stonescenter@gmail.com>\n"
+"Language-Team: Spanish <debian-l10n-spanish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"¿Activar (o mantener activada) la secuencia de arranque basada en "
+"dependencias?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Si escoge activar una secuencia de arranque basada en dependencias, los "
+"scripts en «/etc/rc*.d/» serán reordenados mediante información de "
+"dependencia proporcionadas por los comentarios de cabecera de LSB (o valores "
+"por omisión donde estos no estén presentes). Todos los enlaces simbólicos S* "
+"en «rc0.d/ y rc6.d/» serán convertidos en enlaces simbólicos K*, para "
+"asegurarse que la forma con que se usan (con el argumento «stop») coincidan "
+"con sus nombres. El cambio sólo se hará después de que se compruebe que la "
+"conversión es segura. Si está activo al desactivarlo se intentará revertir "
+"el cambio. "
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Por favor tenga en cuenta que esta característica es experimental. No está "
+"garantizado que se pueda revertir desde una secuencia de arranque basada en "
+"dependencias y puede necesitar la reinstalación del sistema."
diff --git a/debian/po/fi.po b/debian/po/fi.po
new file mode 100644 (file)
index 0000000..eb47065
--- /dev/null
@@ -0,0 +1,55 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-15 00:51+0200\n"
+"Last-Translator: Esko Arajärvi <edu@iki.fi>\n"
+"Language-Team: Finnish <debian-l10n-finnish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Finnish\n"
+"X-Poedit-Country: FINLAND\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"Aktivoidaanko (tai pidetäänkö aktivoituna) riippuvuuspohjainen "
+"käynnistyssekvenssi?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Jos riippuvuuspohjainen käynnistyssekvenssi aktivoidaan, hakemistoissa /etc/"
+"rc*.d/ olevien komentosarjojen käynnistysjärjestystä muutetaan LSB-"
+"kommenttiotsakkeissa annettujen riippuvuustietojen mukaan (tai säilytetään "
+"oletusjärjestyksessä, jos otsakkeita ei ole). Kaikki S*-tyypin symboliset "
+"linkit hakemistoissa rc0.d ja rc6.d muutetaan K*-tyypin symbolisiksi "
+"linkeiksi, sen varmistamiseksi, että niiden käyttötapa (argumentin ”stop” "
+"kanssa) täsmää niiden nimiin. Muutos tehdään vasta, kun on varmistettu, että "
+"se on turvallista tehdä. Jos riippuvuuspohjainen käynnistyssekvenssi "
+"poistetaan käytöstä, muutokset yritetään perua."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Tämä ominaisuus on kokeellinen. Riippuvuuspohjaisen käynnistyssekvenssin "
+"purkaminen ei välttämättä ole turvallista ja saattaa johtaa siihen, että "
+"järjestelmä on asennettava uudelleen."
diff --git a/debian/po/fr.po b/debian/po/fr.po
new file mode 100644 (file)
index 0000000..2924fae
--- /dev/null
@@ -0,0 +1,61 @@
+# Translation of insserv debconf templates to French
+# Copyright (C) 2008 Christian Perrier <bubulle@debian.org>
+# This file is distributed under the same license as the insserv package.
+#
+# Christian Perrier <bubulle@debian.org>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-13 07:22+0100\n"
+"Last-Translator: Christian Perrier <bubulle@debian.org>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"Faut-il activer (ou laisser activée) la gestion des dépendances dans la "
+"séquence de démarrage ?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Si vous choisissez d'activer la gestion des dépendances pour la séquence de "
+"démarrage, les scripts placés dans /etc/rc*.d/ seront remis dans un ordre "
+"qui utilise les informations de dépendances fournies par les en-têtes LSB "
+"(ou des valeurs par défaut si ceux-ci ne sont pas présents). Tous les liens "
+"symboliques de démarrage (liens S*) de rc0.d/ et rc6.d/ seront transformés "
+"en lien d'arrêt des services (liens K*) pour garantir que leur mode "
+"d'utilisation (avec le paramètre « stop ») correspond à leurs noms. Cette "
+"modification ne sera effectuée qu'après contrôle qu'elle peut se faire de "
+"façon sûre. Si vous désactivez la gestion des dépendances alors qu'elle est "
+"active, ces modifications seront abandonnées."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Veuillez noter que cette fonctionnalité est expérimentale. Le retour en "
+"arrière depuis une séquence de démarrage avec gestion des dépendances n'est "
+"pas entièrement garanti et un échec peut imposer la réinstallation de "
+"l'ensemble du système."
diff --git a/debian/po/gl.po b/debian/po/gl.po
new file mode 100644 (file)
index 0000000..729ef73
--- /dev/null
@@ -0,0 +1,56 @@
+# Galician translation of insserv's debconf templates
+# This file is distributed under the same license as the insserv package.
+# Jacobo Tarrio <jtarrio@debian.org>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-10 13:40+0000\n"
+"Last-Translator: Jacobo Tarrio <jtarrio@debian.org>\n"
+"Language-Team: Galician <proxecto@trasno.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"¿Activar (ou manter activada) a secuencia de inicio baseada en dependencias?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Se quere activar a secuencia de inicio baseada en dependencias hanse "
+"reordear os scripts de /etc/rc*.d/ empregando a información de depencencias "
+"fornecida nas cabeceiras LSB dos comentarios (ou empregando valores por "
+"defecto cando estas cabeceiras non estean presentes). Hanse convertir "
+"tódalas ligazóns S* de rc0.d/ e rc6.d/ en ligazóns K*, para asegurarse de "
+"que a maneira en que se empregan (co argumento \"stop\") coincida cos seus "
+"nomes. Só se ha facer o cambio despois de verificar que é seguro realizar a "
+"conversión. Ao desactivala cando estea activada hase tentar desfacer o "
+"cambio."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Teña en conta que esta característica é experimental. Non se pode garantir "
+"que reverter a secuencia de inicio baseada en dependencias sexa unha "
+"operación segura, e pode facer necesario reinstalar o sistema."
diff --git a/debian/po/it.po b/debian/po/it.po
new file mode 100644 (file)
index 0000000..3eb4e4f
--- /dev/null
@@ -0,0 +1,56 @@
+# Italian translation of the insserv debconf template
+# This file is distributed under the same license as the insserv package
+# Copyright (C) 2008 Free Software Foundation, Inc.
+# Luca Monducci <luca.mo@tiscali.it>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv 1.10.0\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-25 14:23+0100\n"
+"Last-Translator: Luca Monducci <luca.mo@tiscali.it>\n"
+"Language-Team: Italian <debian-l10n-italian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr "Attivare (o tenere attiva) la sequenza d'avvio basata su dipendenze?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Se si sceglie di attivare la sequenza di avvio basata sulle dipendenze, gli "
+"script in /etc/rc*.d/ verranno riordinati in base alle informazioni sulle "
+"dipendenze presenti nei commenti delle intestazioni LSB (o in base ai valori "
+"predefiniti in caso di mancanza di queste informazioni). Tutti i link "
+"simbolici S* in rc0.d/ e rc6.d/ verranno trasformati in link simbolici K* in "
+"modo che il loro utilizzo (con l'argomento \"stop\") sia coerente con il "
+"loro nome. La modifica verrà effettuata solo dopo aver verificato che la "
+"conversione sia sicura. Una volta attivata, la disattivazione cerca di "
+"ricreare la configurazione preesistente."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Notare che questa funzionalità è sperimentale. Non si garantisce che il "
+"ripristino della configurazione precedente funzioni correttamente e potrebbe "
+"richiedere la reinstallazione del sistema."
diff --git a/debian/po/ja.po b/debian/po/ja.po
new file mode 100644 (file)
index 0000000..9f004b6
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright (C) 2008 Petter Reinholdtsen <pere@debian.org>
+# This file is distributed under the same license as insserv package.
+# Hideki Yamane (Debian-JP) <henrich@debian.or.jp>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv 1.12.0-4\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-12-28 22:26+0900\n"
+"Last-Translator: Hideki Yamane (Debian-JP) <henrich@debian.or.jp>\n"
+"Language-Team: Japanese <debian-japanese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr "依存関係ベースでの起動シーケンスを有効に (あるいは有効にしたままに) しますか?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"依存関係ベースでの起動シーケンスを有効にした場合、LSB コメントヘッダ (あるいは"
+"現在まだ無いデフォルト設定) から提供される依存関係情報を使って、/etc/rc*.d/ 内"
+"のスクリプトの順番を再構成します。rc0.d/ と rc6.d/ にある全ての S* シンボリック"
+"リンクは、(引数 'stop' で) 使われているのが名前と一致しているのを確かめるため、"
+"K* シンボリックリンクへ変更されます。変更は変換しても安全なのが確認された後のみ"
+"実行されます。有効にした場合に無効にすると変更を元に戻そうと試みます。"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"この機能は実験的なものであることに注意ください。依存関係ベースでの起動シーケンス"
+"から元に戻すのは、安全が確保されていない上にシステムの再インストールが必要になる"
+"かもしれません。"
+
diff --git a/debian/po/nl.po b/debian/po/nl.po
new file mode 100644 (file)
index 0000000..9f55f10
--- /dev/null
@@ -0,0 +1,59 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-18 19:18+0100\n"
+"Last-Translator: Bart Cornelis <cobaco@skolelinux.no>\n"
+"Language-Team: debian-l10n-dutch <debian-l10n-dutch@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Dutch\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"Wilt u de op vereisten gebaseerde opstartvolgorde activeren (of geactiveerd "
+"laten)?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Wanneer u kiest om de op vereisten gebaseerde opstartvolgorde te activeren "
+"worden de scripts in /etc/rc*.d/ geordend op basis van de vereisten die "
+"voorzien zijn in de LSB-commentaar-kopteksten (of standaardwaarden wanneer "
+"deze afwezig zijn). Alle S*-koppelingen in rc0.d/ en rc6.d/ worden omgezet "
+"in K*-symbolische koppelingen; dit zorgt ervoor dat de manier waarop ze "
+"gebruikt worden (met het argument 'stop') gereflecteerd wordt in hun naam. "
+"Deze aanpassing wordt pas uitgevoerd eens nagegaan is dat deze omzetting "
+"veilig is. De-activatie probeert deze aanpassing ongedaan te maken (wanneer "
+"deze keuze actief was)."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Opgelet: deze functionaliteit is experimenteel. De veiligheid van teruggaan "
+"van de op vereisten gebaseerde opstartvolgorde naar de huidige situatie is "
+"niet gegarandeerd en kan de herinstallatie van het systeem vereisen."
diff --git a/debian/po/pt.po b/debian/po/pt.po
new file mode 100644 (file)
index 0000000..c0b0b99
--- /dev/null
@@ -0,0 +1,57 @@
+# translation of insserv debconf to Portuguese
+# Copyright (C) 2008 Américo Monteiro
+# This file is distributed under the same license as the insserv package.
+#
+# Américo Monteiro <a_monteiro@netcabo.pt>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv 1.10.0-4\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-12 00:09+0000\n"
+"Last-Translator: Américo Monteiro <a_monteiro@netcabo.pt>\n"
+"Language-Team: Portuguese <traduz@debianpt.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"Activar (ou manter activa) a sequência de arranque baseada em dependências?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Se você escolher activar a sequência de arranque baseada em dependências, os "
+"scripts em /etc/rc*.d/ serão reordenados usando informação disponibilizada "
+"pelos comentários de cabeçalho do LSB (ou pré-definições quando estes não "
+"estiverem presentes). Todos os symlinks S* em rc0.d/ e rc6.0 serão "
+"convertidos em symlinks K*, para garantir que a maneira que são usados (com "
+"o argumento 'stop') coincide com os seus nomes. A alteração só será feita "
+"após ter sido verificado que é seguro fazê-la. Desactivando-a quando activa "
+"irá tentar reverter a alteração."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Por favor note que esta funcionalidade é experimental. A tentativa de "
+"reverter de sequência de arranque baseada em dependências não é "
+"garantidamente segura, e poderá necessitar da re-instalação do sistema."
diff --git a/debian/po/ru.po b/debian/po/ru.po
new file mode 100644 (file)
index 0000000..fdbf7a9
--- /dev/null
@@ -0,0 +1,61 @@
+# translation of ru.po to Russian
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Yuri Kozlov <kozlov.y@gmail.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv 1.10.0-4\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-18 21:53+0300\n"
+"Last-Translator: Yuri Kozlov <kozlov.y@gmail.com>\n"
+"Language-Team: Russian <debian-l10n-russian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms:  nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+"Включить (или оставить включённым) порядок загрузки, основанный на "
+"зависимостях?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Если вы выберете включение порядка загрузки, основанного на зависимостях, то "
+"сценарии в /etc/rc*.d/ будут переупорядочены согласно информации о "
+"зависимостях, предоставляемых в LSB закомментированных заголовках (или "
+"согласно значениям по умолчанию, если их нет). Все символические ссылки S* в "
+"rc0.d/ и rc6.d/ будут обращены в символические ссылки K*, чтобы "
+"удостовериться, что то, для чего они используются (с параметром 'stop'), "
+"совпадает с их именами. Изменения выполнятся только после того, как будет "
+"проверено, что преобразование безопасно. При выключение порядка будет "
+"произведена попытка откатить сделанные изменения."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Обратите внимание, что это пока эксперимент. Возвращение назад с порядка "
+"загрузки, основанного на зависимостях не гарантируется и может потребоваться "
+"переустановка системы."
diff --git a/debian/po/sv.po b/debian/po/sv.po
new file mode 100644 (file)
index 0000000..c6aeb80
--- /dev/null
@@ -0,0 +1,57 @@
+# translation of insserv.po to swedish
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Martin Bagge <brother@bsnet.se>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-10-26 23:53+0100\n"
+"Last-Translator: Martin Bagge <brother@bsnet.se>\n"
+"Language-Team: swedish <debian-l10n-swedish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr "Aktivera beroendebaserad uppstartssekvens?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Om du aktiverar beroendebaserad uppstartssekvens kommer att innebära "
+"förändringar i ordningen för skripten i /etc/rc*.d/ - denna förändring "
+"baseras på information från LSB-huvuden eller standardvärden om LSB-"
+"information saknas. Alla S*-skript i rc0.d/ och rc6.d/ kommer att ändras "
+"till K* så att namnen blir rätt när de används med argumentet 'stop'. "
+"Förändringar kommer endast att genomföras efter att en kontroll har kommit "
+"fram till att det är en säker förändring. Vid av avaktivering av "
+"beroendebaserad uppstartssekvens kommer förändringarna att bli ogjorda i "
+"möjligaste mån."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Observera att denna funktion ännu är helt experimentiell. Att återställa "
+"från beroendebaserad uppstartssekvens är långt ifrån garanterat riskfri och "
+"kan medföra att systemet måste installeras om."
diff --git a/debian/po/templates.pot b/debian/po/templates.pot
new file mode 100644 (file)
index 0000000..a4925cd
--- /dev/null
@@ -0,0 +1,45 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
diff --git a/debian/po/vi.po b/debian/po/vi.po
new file mode 100644 (file)
index 0000000..4d07377
--- /dev/null
@@ -0,0 +1,55 @@
+# Vietnamese translation for INS Serv.
+# Copyright © 2008 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: insserv 1.10.0-4\n"
+"Report-Msgid-Bugs-To: pere@debian.org\n"
+"POT-Creation-Date: 2008-02-17 13:56+0100\n"
+"PO-Revision-Date: 2008-02-12 23:06+1030\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: LocFactoryEditor 1.7b3\n"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid "Enable (or keep enabled) the dependency-based boot sequence?"
+msgstr "Bật (hoặc cứ bật) dãy khởi động dựa vào quan hệ phụ thuộc không?"
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"If you choose to enable the dependency-based boot sequence the scripts in /"
+"etc/rc*.d/ will be reordered using dependency information provided by LSB "
+"comment headers (or defaults where these are not present). All S* symlinks "
+"in rc0.d/ and rc6.d/ will be turned into K* symlinks, to make sure the way "
+"they are used (with the argument 'stop') matches their names. The change "
+"will only be done after it is verified that it is safe to convert. Disabling "
+"it when enabled will try to revert the change."
+msgstr ""
+"Bật tùy chọn này thì các văn lệnh trong thư mục « /etc/rc*.d/ » sẽ được sắp "
+"xếp lại tùy theo thông tin về quan hệ phụ thuộc mà được cung cấp bởi phần "
+"đầu chú thích LSB (không có thì dùng các giá trị mặc định). Mọi liên kết mềm "
+"« S* » đều trong hai thư mục « rc0.d/ » và « rc6.d/ » sẽ được chuyển đổi "
+"sang liên kết mềm « K* », để đảm bảo cách dùng chúng tương ứng với tên nó. "
+"Thay đổi này sẽ chỉ xảy ra một khi thẩm tra tiến trình chuyển đổi sẽ chạy an "
+"toàn. Sau khi bật tùy chọn này, tắt nó sẽ hoàn nguyên thay đổi."
+
+#. Type: boolean
+#. Description
+#: ../insserv.templates:2001
+msgid ""
+"Please note that this feature is experimental. Attempting to revert from "
+"dependency-based boot sequencing is not guaranteed to be safe, and may "
+"require the reinstallation of the system."
+msgstr ""
+"Ghi chú rằng tính năng này vẫn còn thực nghiệm. Không thể đảm bảo tính an "
+"toàn khi thử hoàn nguyên khỏi chức năng tạo dãy dựa vào quan hệ phụ thuộc: "
+"nó có thể cần thiết cài đặt lại hệ thống."
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..7de562e
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+PACKAGE = insserv
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS = -g -O0
+else
+       CFLAGS = -g -O2
+endif
+
+#CFLAGS += -DDEBUG=1
+
+INSTALL = install
+INSTALL_DATA = $(INSTALL) -m644
+DESTDIR = $(CURDIR)/debian/$(PACKAGE)
+
+pkgdatadir = /usr/share/$(PACKAGE)
+sbindir = /usr/sbin
+
+include /usr/share/quilt/quilt.make
+
+build: build-stamp
+
+build-stamp: $(QUILT_STAMPFN)
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE) COPTS="$(CFLAGS)"
+
+       chmod a+rx debian/run-testsuite
+       debian/run-testsuite
+
+       touch build-stamp
+
+clean:
+       dh_testdir
+       rm -f build-stamp
+
+       # Add here commands to clean up after the build process.
+       $(MAKE) clean
+
+       # Remove patches after doing 'make clean', to allow patches to adjust the clean target
+       $(MAKE) -f debian/rules unpatch
+
+       dh_clean 
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k 
+       dh_installdirs
+
+       # Add here commands to install the package into debian/$(PACKAGE).
+       $(MAKE) install COPTS="$(CFLAGS)" DESTDIR=$(DESTDIR)
+
+       # Install overrides if present
+       for data in debian/overrides/* ; do \
+               test -f $$data || continue ; \
+               $(INSTALL_DATA) $$data $(DESTDIR)$(pkgdatadir)/overrides/. ;\
+       done
+
+       $(INSTALL) debian/check-initd-order $(DESTDIR)$(pkgdatadir)/.
+       $(INSTALL) debian/check-archive-initd-scripts \
+               $(DESTDIR)$(pkgdatadir)/.
+       $(INSTALL) debian/seq-changes $(DESTDIR)$(pkgdatadir)/.
+       $(INSTALL) debian/make-testsuite $(DESTDIR)$(pkgdatadir)/.
+       $(INSTALL) debian/update-bootsystem-insserv $(DESTDIR)$(sbindir)/.
+       $(INSTALL) debian/update-rc.d-insserv $(DESTDIR)$(sbindir)/.
+
+       # Install bash(1) completion
+       $(INSTALL_DATA) debian/bash-completion $(DESTDIR)/etc/bash_completion.d/insserv
+
+       dh_lintian
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs CHANGES
+       dh_installdocs
+       dh_installexamples
+       dh_installdebconf
+#      dh_install
+       dh_installman
+       dh_link
+       dh_strip
+       dh_compress
+       dh_fixperms
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
+
+.PHONY: phony
diff --git a/debian/run-testsuite b/debian/run-testsuite
new file mode 100644 (file)
index 0000000..7791bac
--- /dev/null
@@ -0,0 +1,2178 @@
+#!/bin/bash
+
+basedir=$(dirname $0)
+. $basedir/../tests/suite
+
+if head -1 debian/changelog | grep -q UNRELEASED ; then
+    severity=check
+else
+    severity=test
+fi
+
+update_conf() {
+set +C
+cat <<'EOF' > $insconf
+$local_fs       +mountall +umountfs
+$network        +networking +ifupdown
+$named          +named +dnsmasq +lwresd +bind9 $network
+$remote_fs      $local_fs +mountnfs +mountnfs-bootclean +umountnfs +sendsigs
+$syslog         +syslog +sysklogd
+$portmap        portmap
+$time           hwclock
+<interactive>   udev mountdevsubfs checkroot checkfs console-screen
+EOF
+set -C
+}
+##########################################################################
+test_normal_sequence() {
+echo
+echo "info: test normal boot sequence scripts, and their order"
+echo
+
+insertscript mountkernfs.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          mountkernfs
+# Required-Start:
+# Required-Stop:
+# Should-Start:      glibc
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript mountdevsubfs.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          mountdevsubfs mountvirtfs
+# Required-Start:    mountkernfs
+# Required-Stop:
+# Should-Start:      udev
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript checkroot.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          checkroot
+# Required-Start:    mountdevsubfs
+# Required-Stop:
+# Should-Start:      keymap hwclockfirst
+# Should-stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript ifupdown-clean <<'EOF'
+### BEGIN INIT INFO
+# Provides:          ifupdown-clean
+# Required-Start:    checkroot
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript ifupdown <<'EOF'
+### BEGIN INIT INFO
+# Provides:          ifupdown
+# Required-Start:    ifupdown-clean
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript checkfs.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          checkfs
+# Required-Start:    checkroot
+# Required-Stop:
+# Should-Start:      lvm cryptdisks
+# Should-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript mountall.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          mountall
+# Required-Start:    checkfs
+# Required-Stop:
+# Should-Start:      lvm
+# Should-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript mountnfs.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          mountnfs
+# Required-Start:    $local_fs
+# Required-Stop:
+# Should-Start:      $network
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript beforenfs <<'EOF'
+### BEGIN INIT INFO
+# Provides:          beforenfs
+# Required-Start:    $local_fs
+# Required-Stop:
+# X-Start-Before:    mountnfs
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript hwclock.sh <<'EOF'
+### BEGIN INIT INFO
+# Provides:          hwclock
+# Required-Start:    mountdevsubfs
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript killprocs <<'EOF'
+### BEGIN INIT INFO
+# Provides:          killprocs
+# Required-Start:    $local_fs
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript single <<'EOF'
+### BEGIN INIT INFO
+# Provides:          single
+# Required-Start:    $local_fs killprocs $all
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript needlocalfs <<'EOF'
+### BEGIN INIT INFO
+# Provides:          needlocalfs
+# Required-Start:    $local_fs
+# Required-Stop:     $local_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insertscript needallfs <<'EOF'
+### BEGIN INIT INFO
+# Provides:          needallfs
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insertscript sysklogd <<'EOF'
+### BEGIN INIT INFO
+# Provides:          syslog
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insertscript reboot <<'EOF'
+### BEGIN INIT INFO
+# Provides:          reboot
+# Required-Start:
+# Required-Stop:
+# Default-Start:
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript halt <<'EOF'
+### BEGIN INIT INFO
+# Provides:          halt
+# Required-Start:
+# Required-Stop:
+# Default-Start:
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+insertscript umountroot <<'EOF'
+### BEGIN INIT INFO
+# Provides:          umountroot
+# Required-Start:
+# Required-Stop:
+# Should-Stop:       halt reboot
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript umountfs <<'EOF'
+### BEGIN INIT INFO
+# Provides:          umountfs
+# Required-Start:
+# Required-Stop:     umountroot
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript umountnfs <<'EOF'
+### BEGIN INIT INFO
+# Provides:          umountnfs
+# Required-Start:
+# Required-Stop:     umountfs
+# Should-Stop:       $network $portmap nfs-common
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript needallfs2 <<'EOF'
+### BEGIN INIT INFO
+# Provides:          needallfs2
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# X-Start-Before:    needallfs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insertscript kexec <<'EOF'
+### BEGIN INIT INFO
+# Provides:             kexec
+# Required-Start:
+# Required-Stop:        reboot
+# X-Stop-After:         umountroot
+# Default-Start:
+# Default-Stop:         6
+### END INIT INFO
+EOF
+
+insertscript networking <<'EOF'
+### BEGIN INIT INFO
+# Provides:          networking
+# Required-Start:    mountkernfs ifupdown $local_fs
+# Required-Stop:     ifupdown $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript nolsbheader <<'EOF'
+EOF
+
+list_rclinks
+
+check_order S mountkernfs.sh mountdevsubfs.sh
+check_order S ifupdown-clean ifupdown
+check_order S ifupdown-clean ifupdown
+check_order S mountall.sh mountnfs.sh
+check_order S mountall.sh beforenfs
+check_order S beforenfs mountnfs.sh
+
+check_order 0 needallfs umountnfs
+check_order 0 umountroot halt
+
+check_order 1 killprocs single
+check_order 1 needallfs killprocs
+
+check_order 2 needlocalfs needallfs
+check_order 2 needlocalfs nolsbheader
+check_order 2 sysklogd nolsbheader
+check_order 2 needallfs2 needallfs
+
+check_order 6 needallfs umountnfs
+check_order 6 nolsbheader umountnfs
+check_order 6 umountfs umountroot
+check_order 6 umountnfs networking
+check_order 6 networking ifupdown
+check_order 6 umountnfs umountfs
+check_order 6 umountroot reboot
+check_order 6 umountroot kexec
+check_order 6 kexec reboot
+}
+##########################################################################
+test_override_files() {
+echo
+echo "info: test if override files replace headers in the file"
+echo
+
+initdir_purge
+
+# Two scripts with a loop between them
+insertscript base <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          base
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript mover <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          mover
+# Required-Start:    base
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+check_order S base mover
+
+mkdir -p $overridedir
+cat <<'EOF' > $overridedir/mover
+### BEGIN INIT INFO
+# Provides:          mover
+# Required-Start:
+# Required-Stop:
+# X-Start-Before:    base
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insserv_reg mover
+
+list_rclinks
+
+# Make sure the override file moved mover before base
+check_order S mover base
+rm -rf $overridedir
+}
+##########################################################################
+test_override_loop() {
+echo
+echo "info: testing to insert scripts with a loop, and the effect of an override file"
+echo
+
+initdir_purge
+
+# Two scripts with a loop between them
+if insertscript loop1 <<'EOF' ; then
+### BEGIN INIT INFO
+# Provides:          loop1
+# Required-Start:    loop2
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+    error "inserting script with missing dependencies did not fail"
+fi
+
+insertscript loop2 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          loop2
+# Required-Start:    loop1
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+# Test if override file can be used to break the loop
+mkdir -p $overridedir
+cat <<'EOF' > $overridedir/loop1
+### BEGIN INIT INFO
+# Provides:          loop1
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+check_script_not_present S loop1
+check_script_not_present S loop2
+
+insserv_reg loop1 || true
+insserv_reg loop2 || true
+
+check_order S loop1 loop2
+rm -rf $overridedir
+}
+##########################################################################
+
+test_override_remove() {
+echo
+echo "info: Try to reproduce BTS #540866"
+echo
+
+initdir_purge
+
+addscript testscript <<'EOF'
+### BEGIN INIT INFO
+# Provides:          testscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+mkdir -p ${overridedir}/.
+cat >${overridedir}/testscript <<'EOF'
+### BEGIN INIT INFO
+# Provides:          testscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insserv_reg testscript
+
+list_rclinks
+
+check_script_not_present 3 testscript
+
+echo info: Trying to remove the script
+
+insserv_del testscript
+
+list_rclinks
+
+check_script_not_present 3 testscript
+}
+
+##########################################################################
+test_long_loop() {
+echo
+echo "info: testing to insert scripts with a longer loop, making sure it fail"
+echo
+
+initdir_purge
+
+# Three scripts with a loop between them, make sure introducing the
+# loop fail, as it will make insserv generate a unstable and broken
+# boot and shutdown sequence.
+insertscript loop1 <<'EOF'
+### BEGIN INIT INFO
+# Provides:          loop1
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript loop2 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          loop2
+# Required-Start:    loop1
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+if insertscript loop3 <<'EOF' ; then
+### BEGIN INIT INFO
+# Provides:          loop3
+# Required-Start:    loop2
+# Required-Stop:
+# X-Start-Before:    loop1
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+    error "inserting script causing a loop did not fail"
+fi
+}
+##########################################################################
+test_combined_loop() {
+# Test real loop in the combined start and stop sequence.  There is no
+# loop in the start sequence, and no loop in the stop sequence, but in
+# the combined graph insserv is creating internally, there is a loop.
+# This make sense, as scripts need to be installed in dependency
+# order, and there is no way to install these scripts that make sure
+# both start and stop dependencies are fulfilled.
+echo
+echo "info: test handling of loops in the combination of start and stop sequences"
+echo
+
+initdir_purge
+
+insertscript startfirst <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startfirst
+# Required-Start:
+# Required-Stop:     startsecond
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript startsecond <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startsecond
+# Required-Start:    startfirst
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+test_order S startfirst startsecond
+test_order 6 startsecond startfirst
+}
+##########################################################################
+test_fake_loop() {
+# Test another fake loop.  This one should work, as it is possible to
+# install the two scripts in sequence because one of the dependencies
+# are optional.  It does not with insserv today.
+echo
+echo "info: test handling of 'fake' loops in the combination of start and stop sequences"
+echo
+
+initdir_purge
+
+insertscript startfirst_stopfirst <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startfirst_stopfirst
+# Required-Start:
+# Required-Stop:
+# Should-Stop:       startsecond_stoplast
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript startsecond_stoplast <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startsecond_stoplast
+# Required-Start:    startfirst_stopfirst
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_order S startfirst_stopfirst startsecond_stoplast
+check_order 6 startfirst_stopfirst startsecond_stoplast
+}
+##########################################################################
+test_fake_loop_reverse() {
+# Test another fake loop using reverse dependencies to document that
+# it can happen based on information provided in one package only.
+# This should work, as it is possible to install the two scripts in
+# sequence because one of the dependencies are optional.  It does not
+# with insserv today.  Note thought that the generated order is
+# different from the one above.
+
+echo
+echo "info: test handling of 'fake' loops using reverse depends"
+echo
+
+initdir_purge
+
+insertscript startfirst_stopfirst <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startfirst_stopfirst
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript startsecond_stoplast <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startsecond_stoplast
+# Required-Start:    startfirst_stopfirst
+# Required-Stop:
+# X-Stop-After:      startfirst_stopfirst
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+# #458582
+check_order S startfirst_stopfirst startsecond_stoplast
+check_order 6 startfirst_stopfirst startsecond_stoplast 
+}
+##########################################################################
+test_badscript() {
+echo
+echo "info: test if bad script in init.d/ with no symlinks in rc*.d/ make problems"
+echo
+
+initdir_purge
+
+addscript sitelocal <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          duplicate
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript distroglobal <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          dublicate
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present S distroglobal
+}
+##########################################################################
+test_onlystart() {
+echo
+echo "info: check that it work to insert scripts with only start runlevels"
+echo
+
+initdir_purge
+
+insertscript onlystart <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          onlystart
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present 2 onlystart
+check_script_present 3 onlystart
+check_script_present 4 onlystart
+check_script_present 5 onlystart
+
+check_script_not_present 0 onlystart
+check_script_not_present 1 onlystart
+check_script_not_present 6 onlystart
+}
+##########################################################################
+test_onlystop() {
+echo
+echo "info: check that it work to insert scripts with only stop runlevels"
+echo
+# This test check that the common way to update the runlevels used by
+# a given script is working.  It simulates these calls to update-rc.d:
+#  update-rc.d oldscript default
+#  update-rc.d -f oldscript remove
+#  update-rc.d oldscript start 20 2 3 4 5 . stop 20 1 .
+
+initdir_purge
+
+insertscript onlystop <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          onlystop
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present 0 onlystop
+check_script_present 6 onlystop
+
+check_script_not_present 1 onlystop
+check_script_not_present 2 onlystop
+check_script_not_present 3 onlystop
+check_script_not_present 4 onlystop
+check_script_not_present 5 onlystop
+check_script_not_present S onlystop
+}
+##########################################################################
+test_removal() {
+echo
+echo "info: test if script removal removes all symlinks."
+echo
+# This test check that the common way to update the runlevels used by
+# a given script is working.  It simulates these calls to update-rc.d:
+#  update-rc.d oldscript default
+#  update-rc.d -f oldscript remove
+#  update-rc.d oldscript start 20 2 3 4 5 . stop 20 1 .
+
+initdir_purge
+
+insertscript oldscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          oldscript
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+# Check that the problematic symlinks are presend, as well as one that
+# is OK.
+check_script_present 0 oldscript
+check_script_present 1 oldscript
+check_script_present 3 oldscript
+check_script_present 6 oldscript
+
+set +C
+addscript oldscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          oldscript
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 4 5
+# Default-Stop:      1
+### END INIT INFO
+EOF
+set -C
+
+# Remove old symlinks
+insserv_del oldscript
+# Insert new ones, this time without runlevel 0 and 6
+insserv_reg oldscript
+
+list_rclinks
+
+check_script_not_present 0 oldscript
+check_script_present 1 oldscript
+check_script_present 2 oldscript
+check_script_not_present 3 oldscript
+check_script_not_present 6 oldscript
+}
+
+##########################################################################
+test_segfault_virtfac() {
+echo
+echo "info: detect segfault caused by script providing virtual facility."
+echo
+
+initdir_purge
+
+insertscript badheaderscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          $syslog
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+# Problem is only triggered if there are start or stop symlinks for
+# the script present.
+mkdir -p $initddir/../rc2.d
+ln -s ../init.d/badheaderscript $initddir/../rc2.d/S02badheaderscript
+
+# This one segfaults
+insertscript okscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          okscript
+# Required-Start:    $syslog
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present 2 okscript
+}
+##########################################################################
+test_incorrect_startscripts() {
+echo
+echo "info: Check if insserv add start symlinks for scripts that"
+echo "info: currently do not have them. #492526"
+echo
+
+initdir_purge
+
+insertscript disablestartscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          disablestartscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+list_rclinks
+
+check_script_present 2 disablestartscript
+check_script_present 5 disablestartscript
+check_script_not_present S disablestartscript
+check_script_present 1 disablestartscript
+
+rm $initddir/../rc{2,3,4,5}.d/S??disablestartscript
+
+# Update symlinks, see if it add start symlinks
+insserv_reg .
+
+list_rclinks
+
+check_script_not_present 2 disablestartscript
+check_script_not_present 3 disablestartscript
+check_script_not_present 4 disablestartscript
+check_script_not_present 5 disablestartscript
+check_script_not_present S disablestartscript
+check_script_present 0 disablestartscript
+check_script_present 1 disablestartscript
+}
+##########################################################################
+test_incorrect_stopscripts() {
+echo
+echo "info: Check if insserv add stop symlinks for scripts that"
+echo "info: currently do not have them."
+echo
+
+initdir_purge
+
+insertscript disablestopscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          disablestopscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+list_rclinks
+
+check_script_present 2 disablestopscript
+check_script_present 5 disablestopscript
+check_script_not_present S disablestopscript
+check_script_present 1 disablestopscript
+
+rm $initddir/../rc{0,1}.d/K??disablestopscript
+
+# Update symlinks, see if it add stop symlinks
+insserv_reg .
+
+list_rclinks
+
+check_script_present 2 disablestopscript
+check_script_present 5 disablestopscript
+check_script_not_present S disablestopscript
+check_script_not_present 0 disablestopscript
+check_script_not_present 1 disablestopscript
+}
+##########################################################################
+test_newbug_keepoldorder() {
+echo
+echo "info: Verify that introducing a loop in a working system do"
+echo "info: not change the order of the scripts currently on disk."
+echo
+
+initdir_purge
+
+insertscript mountall <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          mountall
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript needlocal <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          needlocal
+# Required-Start:    $local_fs
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript needremote <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          needremote
+# Required-Start:    $remote_fs needlocal
+# Required-Stop:     $remote_fs needlocal
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+insertscript needboth <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          needboth
+# Required-Start:    needlocal needremote
+# Required-Stop:     needlocal needremote
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_order S mountall needlocal
+check_order S mountall needremote
+check_order S mountall needboth
+check_order S needlocal needremote
+check_order S needlocal needboth
+check_order S needremote needboth
+
+# Then introduce buggy dependencies in an existing script
+set +C
+addscript needboth <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          needboth
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# X-Start-Before:    $local_fs
+# Default-Start:     S
+# Default-Stop:      6
+### END INIT INFO
+EOF
+set -C
+
+echo "info: calling insserv after introducing a bug in script needboth"
+insserv_reg needboth || true
+
+list_rclinks
+
+# The severity of this test should be fatal, below is explanation about how
+# new (1.11.10) and old (1.11.0) insserv version behaviour changed in this
+# test.
+#
+# Hmm ... with this I've found out that the old insserv will
+# run on a loop and therefore exit.  This loop was caused
+# by the system facility $local_fs make the old insserv
+# to do an exit ... now the problem is that the new insserv
+# expands all system facility to their real requirements.
+# This leads to the new behaviour as there is no node during
+# the sorting algorithm which would cause such a loop.
+#
+# In other words: that the old insserv hasn't changed the
+# order was simply a side effect of having a ghost node
+# whereas the new insserv does not use such nodes anymore.
+#
+# If you would remove the `X-Start-Before: $local_fs' the
+# old insserv will also change the boot order.
+
+${severity}_order S mountall needlocal
+${severity}_order S mountall needremote
+${severity}_order S mountall needboth
+${severity}_order S needlocal needremote
+${severity}_order S needlocal needboth
+${severity}_order S needremote needboth
+}
+##########################################################################
+test_start_before() {
+echo
+echo "info: Verify that X-start-before work as it should."
+echo
+
+initdir_purge
+
+insertscript startlast <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startlast
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript startfirst <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          startfirst
+# Required-Start:
+# Required-Stop:
+# X-Start-Before:    startlast
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_order S startfirst startlast
+}
+##########################################################################
+test_stop_after() {
+echo
+echo "info: Verify that X-stop-after work as it should."
+echo
+
+initdir_purge
+
+insertscript stopfirst <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          stopfirst
+# Required-Start:
+# Required-Stop:
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insertscript stopafter <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          stopafter
+# Required-Start:
+# Required-Stop:
+# X-Stop-After:      stopfirst
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_order 0 stopfirst stopafter
+}
+##########################################################################
+test_adding_start() {
+echo
+echo "info: Make sure that adding start levels do not change an existing installation."
+echo
+
+initdir_purge
+
+insertscript addstartscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          addstartscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:
+# Default-Stop:      1
+### END INIT INFO
+EOF
+
+check_script_present 1 addstartscript
+
+check_script_not_present S addstartscript
+check_script_not_present 0 addstartscript
+check_script_not_present 2 addstartscript
+check_script_not_present 3 addstartscript
+check_script_not_present 4 addstartscript
+check_script_not_present 5 addstartscript
+check_script_not_present 6 addstartscript
+
+# Then change runlevel in existing script
+set +C
+addscript addstartscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          addstartscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      1
+### END INIT INFO
+EOF
+set -C
+
+# Update script after changing the header
+insserv_reg addstartscript || true
+
+list_rclinks
+
+check_script_present 1 addstartscript
+
+check_script_not_present S addstartscript
+check_script_not_present 0 addstartscript
+check_script_not_present 2 addstartscript
+check_script_not_present 3 addstartscript
+check_script_not_present 4 addstartscript
+check_script_not_present 5 addstartscript
+check_script_not_present 6 addstartscript
+}
+##########################################################################
+test_removing_start() {
+echo
+echo "info: Make sure that removing start levels do not change an existing installation."
+echo
+
+initdir_purge
+
+insertscript remstartscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          remstartscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+check_script_present 0 remstartscript
+check_script_present 1 remstartscript
+check_script_present 2 remstartscript
+check_script_present 3 remstartscript
+check_script_present 4 remstartscript
+check_script_present 5 remstartscript
+check_script_present 6 remstartscript
+
+# Then change runlevel in existing script
+set +C
+addscript remstartscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          remstartscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+set -C
+
+# Update script after changing the header
+insserv_reg remstartscript || true
+
+list_rclinks
+
+check_script_present 2 remstartscript
+check_script_present 3 remstartscript
+check_script_present 4 remstartscript
+check_script_present 5 remstartscript
+}
+##########################################################################
+test_adding_stop() {
+echo
+echo "info: Make sure that adding stop levels do not change an existing installation."
+echo
+
+initdir_purge
+
+insertscript addstopscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          addstopscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+check_script_present S addstopscript
+check_script_not_present 0 addstopscript
+check_script_not_present 1 addstopscript
+check_script_not_present 2 addstopscript
+check_script_not_present 3 addstopscript
+check_script_not_present 4 addstopscript
+check_script_not_present 5 addstopscript
+check_script_not_present 6 addstopscript
+
+# Then change runlevel in existing script
+set +C
+addscript addstopscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          addstopscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:      0
+### END INIT INFO
+EOF
+set -C
+
+# Update script after changing the header
+insserv_reg addstopscript || true
+
+list_rclinks
+
+check_script_present S addstopscript
+check_script_not_present 0 addstopscript
+check_script_not_present 1 addstopscript
+check_script_not_present 2 addstopscript
+check_script_not_present 3 addstopscript
+check_script_not_present 4 addstopscript
+check_script_not_present 5 addstopscript
+check_script_not_present 6 addstopscript
+}
+##########################################################################
+test_removing_stop() {
+echo
+echo "info: Make sure that removing stop levels do not change an existing installation."
+echo
+
+initdir_purge
+
+insertscript remstopscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          remstopscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+check_script_present S remstopscript
+check_script_present 0 remstopscript
+check_script_present 6 remstopscript
+
+check_script_not_present 1 remstopscript
+check_script_not_present 2 remstopscript
+check_script_not_present 3 remstopscript
+check_script_not_present 4 remstopscript
+check_script_not_present 5 remstopscript
+
+# Then change runlevel in existing script
+set +C
+addscript remstopscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          remstopscript
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+set -C
+
+# Update script after changing the header
+insserv_reg remstopscript || true
+
+list_rclinks
+
+check_script_present 0 remstopscript
+check_script_present 6 remstopscript
+}
+##########################################################################
+test_duplicate_provides() {
+echo
+echo "info: test two initscripts providing same facility."
+echo "info: Not sure if this should fail or not."
+echo
+
+initdir_purge
+
+addscript one <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          samefac
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+addscript two <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          samefac
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insserv_reg one || true
+insserv_reg two || true
+
+list_rclinks
+
+check_script_present S one
+${severity}_script_not_present S two
+}
+##########################################################################
+test_bogus_facility() {
+echo
+echo "info: test insertion of script requiring a virtual facility that doesn't exist"
+echo
+
+initdir_purge
+
+addscript needbogusvirtual <<'EOF'
+### BEGIN INIT INFO
+# Provides:          needbogusvirtual
+# Required-Start:    $bogusvirtualfacility
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insserv_reg needbogusvirtual || true
+
+list_rclinks
+
+test_script_not_present S needbogusvirtual
+}
+##########################################################################
+test_insserv_conf_d() {
+echo
+echo "info: test that /etc/insserv.conf.d/ is used"
+echo
+
+initdir_purge
+rm -rf ${insconf}.d
+mkdir -p ${insconf}.d
+
+# add a base service, to ensure check_order() is accurate
+insertscript dummy <<'EOF'
+### BEGIN INIT INFO
+# Provides:          dummy
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+cat <<'EOF' > ${insconf}.d/facone
+$commvirtfac       +facone
+EOF
+
+insertscript facone <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          facone
+# Required-Start:    dummy
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+cat <<'EOF' > ${insconf}.d/factwo
+$commvirtfac       +factwo
+EOF
+
+insertscript factwo <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          factwo
+# Required-Start:    dummy
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+addscript service <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          service
+# Required-Start:    $commvirtfac
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insserv_reg service || true
+
+list_rclinks
+
+check_script_present S service
+check_order S facone service
+check_order S factwo service
+
+rm -rf ${insconf}.d
+}
+##########################################################################
+test_broken_header() {
+echo
+echo "info: test insertion of script missing Required-{Start,Stop} fields"
+echo
+
+initdir_purge
+
+addscript badheader <<'EOF'
+### BEGIN INIT INFO
+# Provides:          badheader
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insserv_reg badheader || true
+
+list_rclinks
+
+test_script_present 0 badheader
+test_script_present 1 badheader
+test_script_present 2 badheader
+test_script_present 3 badheader
+test_script_present 4 badheader
+test_script_present 5 badheader
+test_script_present 6 badheader
+}
+##########################################################################
+test_noprovides_header() {
+echo
+echo "info: test insertion of script missing Provides fields"
+echo
+
+initdir_purge
+
+addscript badheader <<'EOF'
+### BEGIN INIT INFO
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+EOF
+
+insserv_reg badheader || true
+
+list_rclinks
+
+test_script_present 0 badheader
+test_script_present 1 badheader
+test_script_present 2 badheader
+test_script_present 3 badheader
+test_script_present 4 badheader
+test_script_present 5 badheader
+test_script_present 6 badheader
+}
+##########################################################################
+test_no_default_start() {
+echo
+echo "info: test insertion of script missing Default-Start field"
+echo
+
+initdir_purge
+
+addscript nodefstart <<'EOF'
+### BEGIN INIT INFO
+# Provides:          nodefstart
+# Required-Start:
+# Required-Stop:
+# Default-Stop:      0 6
+### END INIT INFO
+EOF
+
+insserv_reg nodefstart || true
+
+list_rclinks
+
+check_script_present 0 nodefstart
+check_script_present 6 nodefstart
+
+check_script_not_present 2 nodefstart
+check_script_not_present 3 nodefstart
+check_script_not_present 4 nodefstart
+check_script_not_present 5 nodefstart
+}
+##########################################################################
+test_no_default_stop() {
+echo
+echo "info: test insertion of script missing Default-Stop field"
+echo
+
+initdir_purge
+
+addscript nodefstop <<'EOF'
+### BEGIN INIT INFO
+# Provides:          nodefstop
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+### END INIT INFO
+EOF
+
+insserv_reg nodefstop || true
+
+list_rclinks
+
+check_script_present 2 nodefstop
+check_script_present 3 nodefstop
+check_script_present 4 nodefstop
+check_script_present 5 nodefstop
+
+check_script_not_present 0 nodefstop
+check_script_not_present 1 nodefstop
+check_script_not_present 6 nodefstop
+}
+##########################################################################
+test_initd_symlink() {
+echo
+echo "info: test that a symlink in /etc/init.d/ to another script does not cause problems"
+echo
+
+initdir_purge
+
+addscript symlinked <<'EOF'
+### BEGIN INIT INFO
+# Provides:          symlinked
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      1
+### END INIT INFO
+EOF
+
+addscript outsider <<'EOF'
+### BEGIN INIT INFO
+# Provides:          outsider
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      1
+### END INIT INFO
+EOF
+
+#addscript halt <<'EOF'
+### BEGIN INIT INFO
+# Provides:          halt
+# Required-Start:
+# Required-Stop:
+# Default-Start:
+# Default-Stop:      0 6
+### END INIT INFO
+#EOF
+
+# Now make an illegal symlink to see if it causes problems, #485045
+ln -s symlinked ${initddir}/symlink
+
+insserv_reg symlinked || true
+insserv_reg symlink || true
+
+check_script_present 1 symlinked
+check_script_present 2 symlinked
+check_script_present 3 symlinked
+check_script_present 4 symlinked
+check_script_present 5 symlinked
+check_script_not_present 1 symlink
+check_script_not_present 2 symlink
+check_script_not_present 3 symlink
+check_script_not_present 4 symlink
+check_script_not_present 5 symlink
+
+# Add a /etc/init.d/reboot -> halt symlink, to make sure the SUSE case
+# is not broken with stricter symlink sanity checking
+#ln -s halt ${initddir}/reboot
+
+#insserv_reg reboot || true
+
+#check_script_present 0 reboot
+#check_script_present 6 reboot
+
+# Move outsider to a location other than /etc/init.d/ and create a symlink
+# to it. insserv should register it without problems.
+mv ${initddir}/outsider ${initddir}/../
+ln -s ../outsider ${initddir}/outsidelink
+
+insserv_reg outsidelink || true
+
+list_rclinks
+
+check_script_present 1 outsidelink
+check_script_present 2 outsidelink
+check_script_present 3 outsidelink
+check_script_present 4 outsidelink
+check_script_present 5 outsidelink
+
+rm -f ${initddir}/../outsider
+}
+##########################################################################
+test_deterministic_order() {
+echo
+echo "info: test two or more initscripts providing same facility, making sure"
+echo "info: that the first script can be registered with insserv, but others fail." 
+echo
+
+initdir_purge
+
+addscript abc <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          service
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+addscript xyz <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          service
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+addscript hjk <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          service
+# Required-Start:
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insserv_reg xyz || true
+insserv_reg hjk || true
+insserv_reg abc || true
+
+list_rclinks
+
+# #494514
+check_script_present S xyz
+check_script_not_present S abc
+check_script_not_present S hjk
+}
+##########################################################################
+test_all_keyword() {
+echo
+echo "info: test behaviour of a script depending on another with the \$all keyword"
+echo "info: #491391"
+echo
+
+initdir_purge
+
+# Insert a few scripts to flesh out $initdir
+for script in one two three
+do
+insertscript $script <<EOF || true
+### BEGIN INIT INFO
+# Provides:          $script
+# Required-Start:    \$remote_fs
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+done
+
+insertscript four <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          four
+# Required-Start:    $remote_fs
+# Required-Stop:
+# Should-Start:      one two three
+# Should-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript rmnologin <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          rmnologin
+# Required-Start:    $remote_fs $all
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+
+# This version of bootchart LSB info is not the best, but it does reveal
+# an interesting and unexpected behaviour.
+insertscript bootchart <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          bootchart
+# Required-Start:    $remote_fs rmnologin
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present 5 rmnologin
+check_script_present 5 bootchart
+test_order 5 rmnologin bootchart
+
+echo
+echo "info: now add \$all keyword to bootchart script and reinsert"
+echo
+
+remscript bootchart
+# This information looks correct, but due to the way all_links() works two or
+# more scripts with keyword $all in Required-Start start at same sequence, but
+# do start after all other scripts
+addscript bootchart <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          bootchart
+# Required-Start:    $all rmnologin
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insserv_reg bootchart || true
+
+list_rclinks
+check_script_present 5 bootchart
+test_order 5 rmnologin bootchart
+
+echo
+echo "info: add yet another script depending on \$all"
+echo
+insertscript all <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          all
+# Required-Start:    $all
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+check_script_present 5 all
+}
+##########################################################################
+test_early_all() {
+echo
+echo "info: Check that start dependency on \$all only affect the start"
+echo "sequence. BTS #485307"
+
+echo
+
+initdir_purge
+
+# Insert a few scripts to flesh out $initdir
+insertscript early <<EOF || true
+### BEGIN INIT INFO
+# Provides:          early
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+insertscript center <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          center
+# Required-Start:    early
+# Required-Stop:     early
+# Default-Start:     2
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+insertscript late <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          late
+# Required-Start:    center
+# Required-Stop:     center
+# Default-Start:     2
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+# This script should start early and stop before all other scripts
+insertscript zcomplex <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          zcompex
+# Required-Start:    early
+# X-Start-Before:    center
+# Required-Stop:     $all
+# Default-Start:     2
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present 2 early
+check_script_present 2 zcomplex
+check_order 2 early zcomplex
+check_order 2 zcomplex center
+check_order 0 zcomplex late
+check_order 0 zcomplex early
+}
+##########################################################################
+test_script_in_runlevel() {
+echo
+echo "info: add a regular file where only symlinks are expected (#493202)"
+echo
+
+initdir_purge
+
+# Create a regular file in runlevel directory where only symlinks are expected
+mkdir $initddir/../rcS.d
+touch $initddir/../rcS.d/S06badboy
+
+insertscript goodboy <<'EOF'
+### BEGIN INIT INFO
+# Provides:          goodboy
+# Required-Start:    $remote_fs
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present S goodboy
+
+rm $initddir/../rcS.d/S06badboy
+}
+##########################################################################
+test_x_interactive() {
+echo
+echo "info: Check if X-Interactive header work"
+echo "BTS #458224"
+echo
+  
+initdir_purge
+
+# Insert a few scripts to flesh out $initdir
+insertscript first <<EOF || true
+### BEGIN INIT INFO
+# Provides:          first
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+# This test if X-Interactive work with existing scripts when a new
+# script is inserted.
+insertscript alone1 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          alone1
+# Required-Start:    first
+# Required-Stop:     first
+# Default-Start:     2
+# Default-Stop:      0
+# X-Interactive:     true
+### END INIT INFO
+EOF
+
+insertscript after <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          after
+# Required-Start:    first
+# Required-Stop:     first
+# Default-Start:     2
+# Default-Stop:      0
+### END INIT INFO
+EOF
+
+# This test if X-Interactive work with new scripts too.  The code
+# paths in insserv are different for the two cases.
+insertscript alone2 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          alone2
+# Required-Start:    first
+# Required-Stop:     first
+# Default-Start:     2
+# Default-Stop:      0
+# X-Interactive:     true
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_script_present 2 first
+check_script_present 2 after
+check_script_present 2 alone1
+check_script_present 2 alone2
+check_order 2 first after
+check_order 2 first alone1
+check_order 2 first alone2
+${severity}_order 2 alone1 after # This ordering is not guaranteed
+${severity}_order 2 alone2 after # This ordering is not guaranteed
+}
+##########################################################################
+
+test_insserv_conf_makefile() {
+echo
+echo "info: test how recursive /etc/insserv.conf settings show up"
+echo "info: in .depend.boot.  BTS #534526."
+echo
+
+initdir_purge
+
+list_rclinks
+
+# If $local_fs only depend on the mountall script, the test work.
+# Only the last script in $local_fs make it to the dependency file.
+set +C
+cat <<'EOF' > $insconf
+$local_fs       +mountall +nonexisting
+$remote_fs      $local_fs
+EOF
+set -C
+
+insertscript mountall <<'EOF'
+### BEGIN INIT INFO
+# Provides:          mountall
+# Required-Start:
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript dbus <<'EOF'
+### BEGIN INIT INFO
+# Provides:          dbus
+# Required-Start:
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript hal <<'EOF'
+### BEGIN INIT INFO
+# Provides:          hal
+# Required-Start:    $remote_fs dbus
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+if ! grep -q "^hal: mountall dbus" ${initddir}/.depend.start ; then
+    msg="hal should depend on dbus and mountall in .depend.start:"
+    if [ test = "$severity" ] ; then
+        warning "$msg"
+    else
+        error "$msg"
+    fi
+    grep  "^hal: " ${initddir}/.depend.start | sed 's/^/  /'
+fi
+
+update_conf
+}
+
+#########################
+
+test_insserv_virt_loop() {
+echo
+echo "info: test insserv handle virtual facilities depending on itself."
+echo
+
+initdir_purge
+
+list_rclinks
+
+# If $local_fs depend on itself, the error is triggered.
+set +C
+cat <<'EOF' > $insconf
+$local_fs       +mountall $local_fs
+EOF
+set -C
+
+# This used to hang and use unlimited amount of memory.  Now return
+# error instead.
+insertscript testscript <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          testscript
+# Required-Start:    $local_fs
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+update_conf
+}
+
+##########################################################################
+test_local_virtual() {
+echo
+echo "info: Test if home made virtual facilities work as they should."
+echo
+
+initdir_purge
+
+mkdir $insconf.d
+
+insertscript test1 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          test1
+# Required-Start:    $mail-transport-agent
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+insertscript test2 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          test2
+# Required-Start:    $mail-transport-agent
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+set +C
+cat <<'EOF' > $insconf.d/test3
+$mail-transport-agent       test3
+EOF
+insertscript test3 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          test3
+# Required-Start:
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+cat <<'EOF' > $insconf.d/test4
+$mail-transport-agent       +test4
+EOF
+set -C
+insertscript test4 <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          test4
+# Required-Start:    test3
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+list_rclinks
+
+check_order 1 test3 test1
+check_order 1 test3 test2
+check_order 1 test4 test1
+check_order 1 test4 test2
+
+}
+##########################################################################
+test_insserv_upstart() {
+echo
+echo "info: test if insserv handle upstart jobs properly."
+echo
+
+initdir_purge
+
+list_rclinks
+
+# This used to hang and use unlimited amount of memory.  Now return
+# error instead.
+upstartdir=${tmpdir}/etc/init
+
+upstartjob="${tmpdir}/lib/init/upstart-job"
+
+# Add upstart config
+oldconf="$insconf"
+insconf="$insconf -u $upstartjob"
+
+# Dummy entry
+mkdir -p $(dirname $upstartjob)
+cat > $upstartjob <<EOF
+#!/bin/sh
+cat <<END
+### BEGIN INIT INFO
+# Provides:          upstart-test
+# Required-Start:    
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+END
+EOF
+chmod a+x $upstartjob
+
+insert_upstart_job() {
+    name=$1
+    mkdir -p $upstartdir
+    cat > $upstartdir/$name
+    ln -s $upstartjob $initddir/$name
+    insserv_reg $name
+}
+
+# XXX Someone that understand upstart need to fill in sensible stuff
+# here
+insert_upstart_job upstart-test <<EOF || true
+exec /bin/foo --opt -xyz foo bar
+EOF
+
+insertscript test <<'EOF' || true
+### BEGIN INIT INFO
+# Provides:          test
+# Required-Start:    upstart-test
+# Required-Stop:
+# Default-Start:     1
+# Default-Stop:
+### END INIT INFO
+EOF
+
+
+list_rclinks
+
+# Undo upstart config
+insconf="$oldconf"
+}
+
+##########################################################################
+
+test_normal_sequence
+test_override_files
+test_override_loop
+test_override_remove
+test_long_loop
+test_combined_loop             # 1 non-fatal test failing
+test_fake_loop
+test_fake_loop_reverse
+test_badscript
+test_onlystart
+test_onlystop
+test_removal
+test_segfault_virtfac
+test_incorrect_startscripts
+test_incorrect_stopscripts
+test_newbug_keepoldorder       # 3 non-fatal tests failing
+test_start_before
+test_stop_after
+test_adding_start
+test_removing_start
+test_adding_stop
+test_removing_stop
+test_duplicate_provides
+test_bogus_facility            # 1 non-fatal test failing
+test_insserv_conf_d
+test_broken_header
+test_noprovides_header
+test_no_default_start
+test_no_default_stop
+test_initd_symlink
+test_deterministic_order
+test_all_keyword
+test_early_all
+test_script_in_runlevel
+test_x_interactive
+test_insserv_conf_makefile
+test_insserv_virt_loop
+test_local_virtual
+test_insserv_upstart
diff --git a/debian/seq-changes b/debian/seq-changes
new file mode 100644 (file)
index 0000000..4610bec
--- /dev/null
@@ -0,0 +1,54 @@
+#! /bin/bash
+# Script from Frans Pop
+
+set -e
+
+if [ -z "$1" ]; then
+       echo "Usage: insserv-seq-changes /var/lib/insserv/<old bootscripts tarball>"
+       exit 1
+fi
+
+oldtar="$(tar tzf $1)"
+for i in S $(seq 0 6); do
+       echo "Runlevel $i"
+       new="$(cd /etc/rc$i.d; ls -1 [KS]* | sort | nl)"
+       old="$(echo "$oldtar" | grep "^rc$i.d/[KS]" | cut -d/ -f2 | sort | nl)"
+       case $i in
+           S|0|6)
+               old="$(echo "$old" | sed -r "s/[KS][0-9]+//")"
+               new="$(echo "$new" | sed -r "s/[KS][0-9]+//")"
+               ;;
+           *)
+               old="$(echo "$old" | sed -r "s/([KS])[0-9]+/\1_/")"
+               new="$(echo "$new" | sed -r "s/([KS])[0-9]+/\1_/")"
+               ;;
+       esac
+       echo "$new" | while read num cmd; do
+               oldnum=$(echo "$old" | grep "[[:space:]]$cmd$" | awk '{print $1}')
+               if [ "$oldnum" ]; then
+                       diff=$(($num - $oldnum))
+               else
+                       oldnum="---"
+                       diff=""
+               fi
+               if [ ${#cmd} -ge 16 ]; then
+                       echo -e "$cmd\t$num\t$oldnum\t$diff"
+               elif [ ${#cmd} -ge 8 ]; then
+                       echo -e "$cmd\t\t$num\t$oldnum\t$diff"
+               else
+                       echo -e "$cmd\t\t\t$num\t$oldnum\t$diff"
+               fi
+       done
+       echo "$old"  | while read num cmd; do
+               if ! echo "$new" | grep -q "[[:space:]]$cmd$"; then
+                       if [ ${#cmd} -ge 16 ]; then
+                               echo -e "$cmd\t---\t$oldnum"
+                       elif [ ${#cmd} -ge 8 ]; then
+                               echo -e "$cmd\t\t---\t$oldnum"
+                       else
+                               echo -e "$cmd\t\t\t---\t$oldnum"
+                       fi
+               fi
+       done
+       echo
+done
diff --git a/debian/update-bootsystem-insserv b/debian/update-bootsystem-insserv
new file mode 100644 (file)
index 0000000..5b20a17
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen
+# Date: 2009-08-04
+#
+# Transition script only to be used by sysv-rc version 2.87dsf-2 if
+# insserv is upgraded without sysv-rc being upgraded too.
+
+set -e
+
+case "$1" in
+    enable|'')
+       exit 0
+       ;;
+    check)
+       exit 1
+       ;;
+    *)
+       echo "error: Unknown argument '$1'"
+       exit 1
+       ;;
+esac
+
+exit 0
diff --git a/debian/update-rc.d-insserv b/debian/update-rc.d-insserv
new file mode 100644 (file)
index 0000000..1853251
--- /dev/null
@@ -0,0 +1,593 @@
+#! /usr/bin/perl
+#
+# update-rc.d  Update the links in /etc/rc[0-9S].d/
+#
+
+use strict;
+use warnings;
+
+my $initd = "/etc/init.d";
+my $etcd  = "/etc/rc";
+my $notreally = 0;
+
+# Save last action to this directory
+my $archive = "/var/lib/update-rc.d";
+
+# Print usage message and die.
+
+sub usage {
+       print STDERR "update-rc.d: error: @_\n" if ($#_ >= 0);
+       print STDERR <<EOF;
+usage: update-rc.d [-n] [-f] <basename> remove
+       update-rc.d [-n] <basename> defaults [NN | SS KK]
+       update-rc.d [-n] <basename> start|stop NN runlvl [runlvl] [...] .
+       update-rc.d [-n] <basename> disable|enable [S|2|3|4|5]
+               -n: not really
+               -f: force
+
+The disable|enable API is not stable and might change in the future.
+EOF
+       exit (1);
+}
+
+# Dependency based boot sequencing is the default, but upgraded
+# systems might keep the legacy ordering until the sysadm choose to
+# migrate to the new ordering method.  sysv-rc version 2.87dsf-2 will
+# remove /var/lib/insserv/using-insserv and this divert, thus transfering
+# the responsibility for dependency based update-rc.d to sysv-rc.
+if ( -f "/var/lib/insserv/using-insserv" && ! -f "/etc/init.d/.legacy-bootordering" ) {
+    info("using dependency based boot sequencing");
+    exit insserv_updatercd(@ARGV);
+}
+
+# Check out options.
+my $force;
+
+my @orig_argv = @ARGV;
+
+while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
+       shift @ARGV;
+       if (/^-n$/) { $notreally++; next }
+       if (/^-f$/) { $force++; next }
+       if (/^-h|--help$/) { &usage; }
+       &usage("unknown option");
+}
+
+sub save_last_action {
+    my ($script, @arguments) = @_;
+
+    return if $notreally;
+
+    open(FILE, ">", "$archive/${script}.new") || die "unable to write to $archive/${script}.new";
+    print FILE join(" ","update-rc.d",@arguments), "\n";
+    close(FILE);
+    rename "$archive/${script}.new", "$archive/${script}";
+}
+
+sub remove_last_action {
+    my ($script) = @_;
+    unlink "$archive/$script";
+}
+
+# Action.
+
+&usage() if ($#ARGV < 1);
+my $bn = shift @ARGV;
+
+unless ($bn =~ m/[a-zA-Z0-9+.-]+/) {
+    print STDERR "update-rc.d: illegal character in name '$bn'\n";
+    exit (1);
+}
+
+if ($ARGV[0] ne 'remove') {
+    if (! -f "$initd/$bn") {
+       print STDERR "update-rc.d: $initd/$bn: file does not exist\n";
+       exit (1);
+    }
+    &parse_lsb_header("$initd/$bn");
+    &cmp_args_with_defaults($bn, $ARGV[0], @ARGV);
+} elsif (-f "$initd/$bn") {
+    if (!$force) {
+       printf STDERR "update-rc.d: $initd/$bn exists during rc.d purge (use -f to force)\n";
+       exit (1);
+    }
+}
+
+my @startlinks;
+my @stoplinks;
+
+$_ = $ARGV[0];
+if    (/^remove$/)       { &checklinks ("remove"); remove_last_action($bn); }
+elsif (/^defaults$/)     { &defaults (@ARGV); &makelinks; save_last_action($bn, @orig_argv); }
+elsif (/^(start|stop)$/) { &startstop (@ARGV); &makelinks; save_last_action($bn, @orig_argv); }
+elsif (/^(dis|en)able$/) { &toggle (@ARGV); &makelinks; save_last_action($bn, @orig_argv); }
+else                     { &usage; }
+
+exit (0);
+
+sub info {
+    print STDOUT "update-rc.d: @_\n";
+}
+
+sub warning {
+    print STDERR "update-rc.d: warning: @_\n";
+}
+
+sub error {
+    print STDERR "update-rc.d: error: @_\n";
+    exit (1);
+}
+
+sub error_code {
+    my $rc = shift;
+    print STDERR "update-rc.d: error: @_\n";
+    exit ($rc);
+}
+
+# Check if there are links in /etc/rc[0-9S].d/ 
+# Remove if the first argument is "remove" and the links 
+# point to $bn.
+
+sub is_link () {
+    my ($op, $fn, $bn) = @_;
+    if (! -l $fn) {
+       warning "$fn is not a symbolic link\n";
+       return 0;
+    } else {
+       my $linkdst = readlink ($fn);
+       if (! defined $linkdst) {
+           die ("update-rc.d: error reading symbolic link: $!\n");
+       }
+       if (($linkdst ne "../init.d/$bn") && ($linkdst ne "$initd/$bn")) {
+           warning "$fn is not a link to ../init.d/$bn or $initd/$bn\n";
+           return 0;
+       }
+    }
+    return 1;
+}
+
+sub checklinks {
+    my ($i, $found, $fn, $islnk);
+
+    print " Removing any system startup links for $initd/$bn ...\n"
+       if (defined $_[0] && $_[0] eq 'remove');
+
+    $found = 0;
+
+    foreach $i (0..9, 'S') {
+       unless (chdir ("$etcd$i.d")) {
+           next if ($i =~ m/^[789S]$/);
+           die("update-rc.d: chdir $etcd$i.d: $!\n");
+       }
+       opendir(DIR, ".");
+       my $saveBN=$bn;
+       $saveBN =~ s/\+/\\+/g;
+       foreach $_ (readdir(DIR)) {
+           next unless (/^[SK]\d\d$saveBN$/);
+           $fn = "$etcd$i.d/$_";
+           $found = 1;
+           $islnk = &is_link ($_[0], $fn, $bn);
+           next unless (defined $_[0] and $_[0] eq 'remove');
+           if (! $islnk) {
+               print "   $fn is not a link to ../init.d/$bn; not removing\n"; 
+               next;
+           }
+           print "   $etcd$i.d/$_\n";
+           next if ($notreally);
+           unlink ("$etcd$i.d/$_") ||
+               die("update-rc.d: unlink: $!\n");
+       }
+       closedir(DIR);
+    }
+    $found;
+}
+
+sub parse_lsb_header {
+    my $initdscript = shift;
+    my %lsbinfo;
+    my $lsbheaders = "Provides|Required-Start|Required-Stop|Default-Start|Default-Stop";
+    open(INIT, "<$initdscript") || die "error: unable to read $initdscript";
+    while (<INIT>) {
+        chomp;
+        $lsbinfo{'found'} = 1 if (m/^\#\#\# BEGIN INIT INFO\s*$/);
+        last if (m/\#\#\# END INIT INFO\s*$/);
+        if (m/^\# ($lsbheaders):\s*(\S?.*)$/i) {
+       $lsbinfo{lc($1)} = $2;
+        }
+    }
+    close(INIT);
+
+    # Check that all the required headers are present
+    if (!$lsbinfo{found}) {
+       printf STDERR "update-rc.d: warning: $initdscript missing LSB information\n";
+       printf STDERR "update-rc.d: see <http://wiki.debian.org/LSBInitScripts>\n";
+    } else {
+        for my $key (split(/\|/, lc($lsbheaders))) {
+            if (!exists $lsbinfo{$key}) {
+                warning "$initdscript missing LSB keyword '$key'\n";
+            }
+        }
+    }
+}
+
+
+# Process the arguments after the "enable" or "disable" keyword.
+
+sub toggle {
+    my @argv = @_;
+    my ($action, %lvls, @start, @stop, @xstartlinks);
+
+    if (!&checklinks) {
+       print " System start/stop links for $initd/$bn do not exist.\n";
+       exit (0);
+    }
+
+    $action = $argv[0];
+    if ($#argv > 1) {
+       while ($#argv > 0 && shift @argv) {
+           if ($argv[0] =~ /^[S2-5]$/) {
+               $lvls{$argv[0]}++;
+           } else {
+               &usage ("expected 'S' '2' '3' '4' or '5'");
+           }
+       }
+    } else {
+       $lvls{$_}++ for ('S', '2', '3', '4', '5');
+    }
+
+    push(@start, glob($etcd . '[2-5S].d/[KS][0-9][0-9]' . $bn));
+
+    foreach (@start) {
+       my $islink = &is_link (undef, $_, $bn);
+       next if !$islink;
+
+       next unless my ($lvl, $sk, $seq) = m/^$etcd([2-5S])\.d\/([SK])([0-9]{2})$bn$/;
+       $startlinks[$lvl] = $sk . $seq;
+
+       if ($action eq 'disable' and $sk eq 'S' and $lvls{$lvl}) {
+           $xstartlinks[$lvl] = 'K' . sprintf "%02d", (100 - $seq);
+       } elsif ($action eq 'enable' and $sk eq 'K' and $lvls{$lvl}) {
+           $xstartlinks[$lvl] = 'S' . sprintf "%02d", -($seq - 100);
+       } else {
+           $xstartlinks[$lvl] = $sk . $seq;
+       }
+    }
+
+    push(@stop, glob($etcd . '[016].d/[KS][0-9][0-9]' . $bn));
+
+    foreach (@stop) {
+       my $islink = &is_link (undef, $_, $bn);
+       next if !$islink;
+
+       next unless my ($lvl, $sk, $seq) = m/^$etcd([016])\.d\/([SK])([0-9]{2})$bn$/;
+       $stoplinks[$lvl] = $sk . $seq;
+    }
+
+    if ($action eq 'disable') {
+       print " Disabling system startup links for $initd/$bn ...\n";
+    } elsif ($action eq 'enable') {
+       print " Enabling system startup links for $initd/$bn ...\n";
+    }
+
+    &checklinks ("remove");
+    @startlinks = @xstartlinks;
+
+    1;
+}
+
+# Process the arguments after the "defaults" keyword.
+
+sub defaults {
+    my @argv = @_;
+    my ($start, $stop) = (20, 20);
+
+    &usage ("defaults takes only one or two codenumbers") if ($#argv > 2);
+    $start = $stop = $argv[1] if ($#argv >= 1);
+    $stop  =         $argv[2] if ($#argv >= 2);
+    &usage ("codenumber must be a number between 0 and 99")
+       if ($start !~ /^\d\d?$/ || $stop  !~ /^\d\d?$/);
+
+    $start = sprintf("%02d", $start);
+    $stop  = sprintf("%02d", $stop);
+
+    $stoplinks[$_]  = "K$stop"  for (0, 1, 6);
+    $startlinks[$_] = "S$start" for (2, 3, 4, 5);
+
+    1;
+}
+
+# Process the arguments after the start or stop keyword.
+
+sub startstop {
+    my @argv = @_;
+    my($letter, $NN, $level);
+
+    while ($#argv >= 0) {
+       if    ($argv[0] eq 'start') { $letter = 'S'; }
+       elsif ($argv[0] eq 'stop')  { $letter = 'K'; }
+       else {
+           &usage("expected start|stop");
+       }
+
+       if ($argv[1] !~ /^\d\d?$/) {
+           &usage("expected NN after $argv[0]");
+       }
+       $NN = sprintf("%02d", $argv[1]);
+
+       if ($argv[-1] ne '.') {
+           &usage("start|stop arguments not terminated by \".\"");
+       }
+
+       shift @argv; shift @argv;
+       $level = shift @argv;
+       do {
+           if ($level !~ m/^[0-9S]$/) {
+               &usage(
+                      "expected runlevel [0-9S] (did you forget \".\" ?)");
+           }
+           if (! -d "$etcd$level.d") {
+               print STDERR
+                   "update-rc.d: $etcd$level.d: no such directory\n";
+               exit(1);
+           }
+           $level = 99 if ($level eq 'S');
+           $startlinks[$level] = "$letter$NN" if ($letter eq 'S');
+           $stoplinks[$level]  = "$letter$NN" if ($letter eq 'K');
+       } while (($level = shift @argv) ne '.');
+    }
+    1;
+}
+
+# Create the links.
+
+sub makelinks {
+    my($t, $i);
+    my @links;
+
+    if (&checklinks) {
+       print " System start/stop links for $initd/$bn already exist.\n";
+       return 0;
+    }
+    print " Adding system startup for $initd/$bn ...\n";
+
+    # nice unreadable perl mess :)
+
+    for($t = 0; $t < 2; $t++) {
+       @links = $t ? @startlinks : @stoplinks;
+       for($i = 0; $i <= $#links; $i++) {
+           my $lvl = $i;
+           $lvl = 'S' if ($i == 99);
+           next if (!defined $links[$i] or $links[$i] eq '');
+           print "   $etcd$lvl.d/$links[$i]$bn -> ../init.d/$bn\n";
+           next if ($notreally);
+           symlink("../init.d/$bn", "$etcd$lvl.d/$links[$i]$bn")
+               || die("update-rc.d: symlink: $!\n");
+       }
+    }
+
+    1;
+}
+
+## Dependency based
+sub insserv_updatercd {
+    my @args = @_;
+    my @opts;
+    my $scriptname;
+    my $action;
+    my $notreally = 0;
+
+    my @orig_argv = @args;
+
+    while($#args >= 0 && ($_ = $args[0]) =~ /^-/) {
+        shift @args;
+        if (/^-n$/) { push(@opts, $_); $notreally++; next }
+        if (/^-f$/) { push(@opts, $_); next }
+        if (/^-h|--help$/) { &usage; }
+        usage("unknown option");
+    }
+
+    usage("not enough arguments") if ($#args < 1);
+
+    $scriptname = shift @args;
+    $action = shift @args;
+    if ("remove" eq $action) {
+        if ( -f "/etc/init.d/$scriptname" ) {
+            my $rc = system("insserv", @opts, "-r", $scriptname) >> 8;
+            if (0 == $rc && !$notreally) {
+                remove_last_action($scriptname);
+            }
+            error_code($rc, "insserv rejected the script header") if $rc;
+            exit $rc;
+        } else {
+            # insserv removes all dangling symlinks, no need to tell it
+            # what to look for.
+            my $rc = system("insserv", @opts) >> 8;
+            if (0 == $rc && !$notreally) {
+                remove_last_action($scriptname);
+            }
+            error_code($rc, "insserv rejected the script header") if $rc;
+            exit $rc;
+        }
+    } elsif ("defaults" eq $action || "start" eq $action ||
+             "stop" eq $action) {
+        # All start/stop/defaults arguments are discarded so emit a
+        # message if arguments have been given and are in conflict
+        # with Default-Start/Default-Stop values of LSB comment.
+        cmp_args_with_defaults($scriptname, $action, @args);
+
+        if ( -f "/etc/init.d/$scriptname" ) {
+            my $rc = system("insserv", @opts, $scriptname) >> 8;
+            if (0 == $rc && !$notreally) {
+                save_last_action($scriptname, @orig_argv);
+            }
+            error_code($rc, "insserv rejected the script header") if $rc;
+            exit $rc;
+        } else {
+            error("initscript does not exist: /etc/init.d/$scriptname");
+        }
+    } elsif ("disable" eq $action || "enable" eq $action) {
+        insserv_toggle($notreally, $action, $scriptname, @args);
+        # Call insserv to resequence modified links
+        my $rc = system("insserv", @opts, $scriptname) >> 8;
+        if (0 == $rc && !$notreally) {
+            save_last_action($scriptname, @orig_argv);
+        }
+        error_code($rc, "insserv rejected the script header") if $rc;
+        exit $rc;
+    } else {
+        usage();
+    }
+}
+
+sub parse_def_start_stop {
+    my $script = shift;
+    my (%lsb, @def_start_lvls, @def_stop_lvls);
+
+    open my $fh, '<', $script or error("unable to read $script");
+    while (<$fh>) {
+        chomp;
+        if (m/^### BEGIN INIT INFO$/) {
+            $lsb{'begin'}++;
+        }
+        elsif (m/^### END INIT INFO$/) {
+            $lsb{'end'}++;
+            last;
+        }
+        elsif ($lsb{'begin'} and not $lsb{'end'}) {
+            if (m/^# Default-Start:\s*(\S?.*)$/) {
+                @def_start_lvls = split(' ', $1);
+            }
+            if (m/^# Default-Stop:\s*(\S?.*)$/) {
+                @def_stop_lvls = split(' ', $1);
+            }
+        }
+    }
+    close($fh);
+
+    return (\@def_start_lvls, \@def_stop_lvls);
+}
+
+sub lsb_header_for_script {
+    my $name = shift;
+
+    foreach my $file ("/etc/insserv/overrides/$name", "/etc/init.d/$name",
+                      "/usr/share/insserv/overrides/$name") {
+        return $file if -s $file;
+    }
+
+    error("cannot find a LSB script for $name");
+}
+
+sub cmp_args_with_defaults {
+    my ($name, $act) = (shift, shift);
+    my ($lsb_start_ref, $lsb_stop_ref, $arg_str, $lsb_str);
+    my (@arg_start_lvls, @arg_stop_lvls, @lsb_start_lvls, @lsb_stop_lvls);
+
+    ($lsb_start_ref, $lsb_stop_ref) = parse_def_start_stop("/etc/init.d/$name");
+    @lsb_start_lvls = @$lsb_start_ref;
+    @lsb_stop_lvls  = @$lsb_stop_ref;
+    return if (!@lsb_start_lvls and !@lsb_stop_lvls);
+
+    if ($act eq 'defaults') {
+        @arg_start_lvls = (2, 3, 4, 5);
+        @arg_stop_lvls  = (0, 1, 6);
+    } elsif ($act eq 'start' or $act eq 'stop') {
+        my $start = $act eq 'start' ? 1 : 0;
+        my $stop = $act eq 'stop' ? 1 : 0;
+
+        # The legacy part of this program passes arguments starting with
+        # "start|stop NN x y z ." but the insserv part gives argument list
+        # starting with sequence number (ie. strips off leading "start|stop")
+        # Start processing arguments immediately after the first seq number.
+        my $argi = $_[0] eq $act ? 2 : 1;
+
+        while (defined $_[$argi]) {
+            my $arg = $_[$argi];
+
+            # Runlevels 0 and 6 are always stop runlevels
+            if ($arg eq 0 or $arg eq 6) {
+               $start = 0; $stop = 1; 
+            } elsif ($arg eq 'start') {
+                $start = 1; $stop = 0; $argi++; next;
+            } elsif ($arg eq 'stop') {
+                $start = 0; $stop = 1; $argi++; next;
+            } elsif ($arg eq '.') {
+                next;
+            }
+            push(@arg_start_lvls, $arg) if $start;
+            push(@arg_stop_lvls, $arg) if $stop;
+        } continue {
+            $argi++;
+        }
+    }
+
+    if ($#arg_start_lvls != $#lsb_start_lvls or
+        join("\0", sort @arg_start_lvls) ne join("\0", sort @lsb_start_lvls)) {
+        $arg_str = @arg_start_lvls ? "@arg_start_lvls" : "none";
+        $lsb_str = @lsb_start_lvls ? "@lsb_start_lvls" : "none";
+        warning "$name start runlevel arguments ($arg_str) do not match",
+                "LSB Default-Start values ($lsb_str)";
+    }
+    if ($#arg_stop_lvls != $#lsb_stop_lvls or
+        join("\0", sort @arg_stop_lvls) ne join("\0", sort @lsb_stop_lvls)) {
+        $arg_str = @arg_stop_lvls ? "@arg_stop_lvls" : "none";
+        $lsb_str = @lsb_stop_lvls ? "@lsb_stop_lvls" : "none";
+        warning "$name stop runlevel arguments ($arg_str) do not match",
+                "LSB Default-Stop values ($lsb_str)";
+    }
+}
+
+sub insserv_toggle {
+    my ($dryrun, $act, $name) = (shift, shift, shift);
+    my (@toggle_lvls, $start_lvls, $stop_lvls, @symlinks);
+    my $lsb_header = lsb_header_for_script($name);
+
+    # Extra arguments to disable|enable action are runlevels. If none
+    # given parse LSB info for Default-Start value.
+    if ($#_ >= 0) {
+        @toggle_lvls = @_;
+    } else {
+        ($start_lvls, $stop_lvls) = parse_def_start_stop($lsb_header);
+        @toggle_lvls = @$start_lvls;
+        if ($#toggle_lvls < 0) {
+            error("$name Default-Start contains no runlevels, aborting.");
+        }
+    }
+
+    # Find symlinks in rc.d directories. Refuse to modify links in runlevels
+    # not used for normal system start sequence.
+    for my $lvl (@toggle_lvls) {
+        if ($lvl !~ /^[S2345]$/) {
+            warning("$act action will have no effect on runlevel $lvl");
+            next;
+        }
+        push(@symlinks, $_) for glob("/etc/rc$lvl.d/[SK][0-9][0-9]$name");
+    }
+
+    if (!@symlinks) {
+        error("no runlevel symlinks to modify, aborting!");
+    }
+
+    # Toggle S/K bit of script symlink.
+    for my $cur_lnk (@symlinks) {
+        my $sk;
+        my @new_lnk = split(//, $cur_lnk);
+
+        if ("disable" eq $act) {
+            $sk = rindex($cur_lnk, '/S') + 1;
+            next if $sk < 1;
+            $new_lnk[$sk] = 'K';
+        } else {
+            $sk = rindex($cur_lnk, '/K') + 1;
+            next if $sk < 1;
+            $new_lnk[$sk] = 'S';
+        }
+
+        if ($dryrun) {
+            printf("rename(%s, %s)\n", $cur_lnk, join('', @new_lnk));
+            next;
+        }
+
+        rename($cur_lnk, join('', @new_lnk)) or error($!);
+    }
+}
diff --git a/debian/update-rc.d-insserv.8 b/debian/update-rc.d-insserv.8
new file mode 100644 (file)
index 0000000..3e62e77
--- /dev/null
@@ -0,0 +1,14 @@
+.\" Copyright 2008,2009 Petter Reinholdtsen
+.\" May be distributed under the GNU General Public License
+.TH "update-bootsystem-insserv" "8" "28 July 2009" "Petter Reinholdtsen" ""
+.SH "NAME"
+update\-rc.d\-insserv \- obsolete
+.SH "DESCRIPTION"
+.B update\-rc.d\-insserv
+is an obsolete implementation of the update-rc.d interface for the dependency
+based boot sequencing system insserv.  The implementation was moved into the
+sysv-rc update-rc.d implementation.
+.SH "SEE ALSO"
+update\-rc.d(8), insserv(8), update-bootsystem-insserv(8)
+.SH "AUTHOR"
+Petter Reinholdtsen, <pere@hungry.com>
diff --git a/debian/watch b/debian/watch
new file mode 100644 (file)
index 0000000..e47cd30
--- /dev/null
@@ -0,0 +1,6 @@
+# Run the "uscan" command to check for upstream updates and more.
+# See uscan(1) for format
+
+version=2
+
+ftp://ftp.suse.com/pub/projects/init/insserv-(.*).tar.gz debian uupdate
diff --git a/init-functions b/init-functions
new file mode 100644 (file)
index 0000000..ba21100
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Define init LSB shell functions
+#
+
+#
+# Source SuSE's rc functions
+#
+. /etc/rc.status
+
+#
+# Be sure that  start_daemon, killproc, and
+# pidofproc will be script functions.
+#
+function start_daemon ()
+{
+    /sbin/start_daemon ${1+"$@"}
+}
+
+function killproc ()
+{
+    /sbin/killproc ${1+"$@"}
+}
+
+function pidofproc ()
+{
+    /sbin/pidofproc ${1+"$@"}
+}
+
+#
+# Logging of succes messages
+#
+function log_success_msg ()
+{
+    echo -en "$@"
+    echo -e  "$rc_done"
+}
+
+#
+# Logging of failure messages
+#
+function log_failure_msg ()
+{
+    echo -en "$@"
+    echo -e  "$rc_failed"
+}
+
+#
+# Logging of warn messages
+#
+function log_warning_msg ()
+{
+    echo -en "$@"
+    echo -e  "${stat}${attn} warning${norm}"
+}
+
diff --git a/insserv-1.12.0.lsm b/insserv-1.12.0.lsm
new file mode 100644 (file)
index 0000000..7699a30
--- /dev/null
@@ -0,0 +1,15 @@
+Begin3
+Title:         insserv tool for boot scripts
+Version:       1.12.0
+Entered-date:  30JUL08
+Description:   Used for enabling of installed boot scripts
+               by scanning comment headers which are LSB conform.
+Keywords:      boot service control, LSB
+Author:                Werner Fink <werner@suse.de>
+Maintained-by: Werner Fink <werner@suse.de>
+Primary-site:  sunsite.unc.edu /pub/Linux/system/daemons/init
+               @UNKNOWN insserv-1.12.0.tar.gz
+Alternate-site:        ftp.suse.com /pub/projects/init
+Platforms:     Linux with System VR2 or higher boot scheme
+Copying-policy:        GPL
+End
diff --git a/insserv.8.in b/insserv.8.in
new file mode 100644 (file)
index 0000000..3e79a5f
--- /dev/null
@@ -0,0 +1,443 @@
+.\"
+.\" Copyright 2000-2008 Werner Fink
+.\" Copyright 2000-2003 SuSE GmbH Nuernberg, Germany
+.\" Copyright 2007 SuSE Linux Products GmbH Nuernberg, Germany
+.\" Copyright 2008 SuSE Linux Products GmbH Nuernberg, Germany
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+@@BEGIN_SUSE@@
+.TH INSSERV 8 "Jul 29, 2008" "Version 1.11" "The SuSE boot concept"
+.UC 8
+.OS SuSE Linux
+@@ELSE_SUSE@@
+.TH INSSERV 8 "Jul 29, 2008" "Version 1.11"
+.UC 8
+.OS Debian
+@@END_SUSE@@
+.SH NAME
+insserv \- Enable an installed system init script
+.SH SYNOPSIS
+.\"
+.B insserv
+.RB [ \-v ]
+.RB [ \-c\ <config> ]
+.RB [ \-p\ <path> ]
+.RB [ \-d ]
+.RB [ \-f ]
+.RI [[ / ] path/to/init.d/ ] script \ ...
+.PP
+.B insserv
+.RB [ \-v ]
+.RB [ \-c\ <config> ]
+.RB [ \-p\ <path> ]
+@@BEGIN_SUSE@@
+.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2>\ ... ]
+@@ELSE_SUSE@@
+.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2>\ ... ] ,stop=<lvl1> [ ,<lvl2>\ ... ]]
+@@END_SUSE@@
+.PP
+.B insserv
+.RB [ \-v ]
+.RB [ \-c\ <config> ]
+.RB [ \-p\ <path> ]
+.B \-r
+.RB [ \-d ]
+.RB [ \-f ]
+.RI [[ / ] path/to/init.d/ ] script \ ...
+.PP
+.B insserv
+.B \-h
+.PP
+@@BEGIN_SUSE@@
+.RB /usr/lib/lsb/install_initd
+.RI [[ / ] path/to/init.d/script ]
+.PP
+.RB /usr/lib/lsb/remove_initd
+.RI [[ / ] path/to/init.d/script ]
+@@END_SUSE@@
+.SH DESCRIPTION
+.B insserv
+enables an installed system init script (`boot script')
+by reading the comment header of the script, e.g.:
+.sp 1
+.in +1l
+.nf
+ ### BEGIN INIT INFO
+ # Provides:          boot_facility_1 [ boot_facility_2 ...]
+ # Required-Start:    boot_facility_1 [ boot_facility_2 ...]
+ # Required-Stop:     boot_facility_1 [ boot_facility_2 ...]
+ # Should-Start:      boot_facility_1 [ boot_facility_2 ...]
+ # Should-Stop:       boot_facility_1 [ boot_facility_2 ...]
+ # X-Start-Before:    boot_facility_1 [ boot_facility_2 ...]
+ # X-Stop-After:      boot_facility_1 [ boot_facility_2 ...]
+ # Default-Start:     run_level_1 [ run_level_2 ...]
+ # Default-Stop:      run_level_1 [ run_level_2 ...]
+ # Short-Description: single_line_description
+ # Description:       multiline_description
+ ### END INIT INFO
+.fi
+.in -1l
+.sp 1
+and calculating the dependencies between all scripts.
+@@BEGIN_SUSE@@
+Please note, that the
+.B Default\-Stop
+are ignored in SuSE Linux, because the SuSE boot script concept
+uses a differential link scheme (see
+.IR init.d (7)).
+@@ELSE_SUSE@@
+Please be aware that the line
+.sp 1
+.in +1l
+.nf
+ # Required-Stop:  boot_facility_1 [ boot_facility_2 ...]
+.fi
+.in -1l
+.sp 1
+declares facilities which must be available during shutdown of the service
+declared in the
+.B Provides
+tag.  Same holds true for
+.sp 1
+.in +1l
+.nf
+ # Should-Stop:    boot_facility_1 [ boot_facility_2 ...]
+.fi
+.in -1l
+.sp 1
+which declares facilities which should be available during shutdown of
+the service declared in the 
+.B Provides
+tag. In both cases the script system should avoid stopping services
+which are declared by these two Stop tags until the script including
+these tags is stopped.
+@@END_SUSE@@
+.PP
+The optional
+.B X\-Start\-Before
+keyword implies that the script using this keyword
+should be started
+.B before
+the specified service names.
+Wereas the optional
+.B X\-Stop\-After
+keyword implies that the script using this keyword
+should be stopped
+.B after
+the specified service names. Both implies that those
+services now depend on the specifying script. 
+With known dependencies and runlevel(s)
+.B insserv
+sets and reorders the corresponding symbolic links
+of the concerned runlevels
+@@BEGIN_SUSE@@
+directories (see \fI init.d\fR (7)).
+@@ELSE_SUSE@@
+directories.
+@@END_SUSE@@
+Known runlevels are:
+.sp 1
+.in +1l
+.nf
+ \fB0\fR\   used for System halt
+ \fB1\fR\   used for single user mode
+ \fB2\fR\   used for local multiuser without remote network
+ \fB3\fR\   used for full multiuser with network
+ \fB4\fR\   reserved for local use
+ \fB5\fR\   used for full multiuser with network and xdm
+ \fB6\fR\   used for System reboot
+@@BEGIN_SUSE@@
+ \fBS\fR\   used during boot into single user mode
+ \fBB\fR\   used during boot before any other runlevel
+@@ELSE_SUSE@@
+ \fBS\fR\   used during boot before any other runlevel
+@@END_SUSE@@
+.fi
+.in -1l
+.sp 1
+.PP
+.B insserv
+scans for
+.B System Facilities
+in the configuration file
+.I /etc/insserv.conf
+and each file in the directory
+.IR /etc/insserv.conf.d/ .
+Each line which begins with
+.B $
+and a following name defines a system facility
+accordingly to the Linux Standard Base Specification (LSB),
+All names followed by such a system facility
+will declare the required dependencies of the facility.
+Here is an example for
+.IR /etc/insserv.conf :
+.sp 1
+.in +1l
+.nf
+ # All local filesystems are mounted
+ # (done during boot phase)
+ $local_fs       boot
+
+ # Low level networking
+ $network        network route
+
+ # Named is operational
+ $named          named
+
+ # All remote filesystems are mounted
+ # (in some cases /usr may be remote).
+ $remote_fs      $local_fs nfs
+
+ # System logger is operational
+ $syslog         syslog
+
+ # All network daemons are running
+ $netdaemons     portmap inetd
+
+ # Services which need to be interactive
+ <interactive>   boot.crypto
+.fi
+.in -1l
+.sp 1
+Names starting with a `+' sign are marked as optional.
+If the service with the name after the plus sign is
+available it will be used, if not available it is
+ignored silently.  Words beginning with
+.B <
+and ending with
+.B >
+are keywords.  Currently
+.B <interactive>
+is the only know keyword for marking a service
+as an interactive one, e.g. a service which requires
+a passphrase or password input during boot
+or runlevel change.
+.P
+Beside the defined
+.B System Facilities
+in the configuration file
+.IR /etc/insserv.conf ,
+.B insserv
+also knows the special facility
+.BR $all .
+This facility indicates that a service should be inserted
+at the end of all services.  Clearly all services using
+this facility will be grouped into one starting order.
+.\"
+.SH OPTIONS
+Currently there exists nine options for
+.BR insserv .
+.TP
+.BR \-v ,\  \-\-verbose
+Write out what is currently going on.
+.TP
+.BR \-c\ <config> ,\  \-\-config\ <config>
+Specify path to the insserv.conf file and the insserv.conf.d
+directory.  Useful for testing.
+.TP
+.BR \-o\ <path> ,\  \-\-override\ <path>
+Path to replace existing LSB comment headers with the comment
+headers found in this path (default path is
+.IR /etc/insserv/overrides/ ).
+.TP
+.BR \-p\ <path> ,\  \-\-path\ <path>
+Specify path to init.d directory.  Useful for testing.
+.TP
+.BR \-n ,\  \-\-dryrun
+Do not update symlinks.
+.TP
+.BR \-r ,\  \-\-remove
+Remove the listed scripts from all runlevels.
+.TP
+.BR \-d ,\  \-\-default
+Use default runlevels a defined in the scripts.
+This may restore an edited runlevel link scheme.
+.TP
+.BR \-f ,\  \-\-force
+Ignore if a required service is missed.
+.TP
+.BR \-h ,\  \-\-help
+Print out short usage message.
+.PP
+But you may use the argument syntax described in the
+following section.
+.SH ARGUMENTS
+.TP
+.RI [[ / ] path/to/init.d/ ]
+Relative or absolute path to the init scripts base directory.
+@@BEGIN_SUSE@@
+For the SuSE Linux boot concept, this defaults to
+@@ELSE_SUSE@@
+This defaults to
+@@END_SUSE@@
+.I /etc/init.d/
+in compliance with the LSB specification.
+In this case
+.B insserv
+does not add or remove a script to the runlevels
+declared in the script headers, but may re\-order the
+runlevels if the order of the currently enabled scripts
+has changed (see option
+.BR \-d ).
+Note that if a relative path is used
+.B insserv
+has to be called from the root directory.
+.TP
+.RI [[ / ] path/to/init.d/ ] script\ ...
+List of scripts which have to be added to
+the runlevels. If a path is used it
+should point to the absolute or relative
+location of the boot scripts.
+.B insserv
+checks for the existence of these scripts.
+For the runlevels the information found in
+the script is used.
+.TP
+.RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2> ]]\ ...
+List of scripts which have to be added to
+the specified runlevels to be started with.
+You may use this extension to override the default values
+for start and stop runlevels of the script.
+Note that
+.BR <lvl1> ,\  <lvl2> ,\ ...
+are the known runlevels explained above.
+The extension
+.IR ,stop=<lvl1> [ ,<lvl2> ]]
+is possible
+@@BEGIN_SUSE@@
+is possible but ignored on SuSE Linux.
+@@ELSE_SUSE@@
+is also possible.
+@@END_SUSE@@
+.TP
+.RI \fB\-r\fR\ [[ / ] path/to/init.d/ ] script\ ...
+List of scripts which should be removed from
+the runlevels. If a path is used it
+should point to the absolute or relative
+location of the boot scripts.
+.B insserv
+checks for the existence of these scripts.
+.\"
+.SH OVERRIDES
+Beside using the extensions
+.IR ,start=<lvl1> [ ,<lvl2> ]]
+and
+.IR ,stop=<lvl1> [ ,<lvl2> ]]
+it is possible to use override files replace a LSB comment header
+or simple provide a missing LSB comment header.  This can be done
+by placing a file with the new LSB comment header using the same
+name as the boot or init script in the directory
+.IR /etc/insserv/overrides/ .
+.\"
+.SH EXIT CODES
+The exit codes have the following conditions:
+.RS 7
+.IP 0 5
+Service was successfully installed or removed
+.IP 1 5
+Service was not installed or removed
+.RE
+.RS 5
+.SH NOTE
+Please be aware that the following patterns of
+boot script file names will be not accepted by
+.BR insserv:
+.sp 1
+.in +1l
+.nf
+@@BEGIN_SUSE@@
+        *.local
+@@END_SUSE@@
+        *.dpkg*
+        *.rpm*
+        *.ba*
+        *.old
+        *.new
+        *.org
+        *.orig
+        *.save
+        *.swp
+        *.core
+        *~
+.fi
+.in -1l
+.sp 1
+with the wildcard character
+.BR * .
+Beside this all boot script file names beginning with one
+of the following characters
+.sp 1
+.in +1l
+.nf
+        $.#%_+-\\*[]^:()~
+.fi
+.in -1l
+.sp 1
+will be ignored.
+.SH BUGS
+Boot script sometimes misses comments.
+.SH FILES
+.TP
+.I /etc/insserv.conf
+configuration file for
+.B insserv
+which defines the LSB System Facilities.
+.TP
+.I /etc/insserv.conf.d/
+directory for further configuration files for declaring
+LSB System Facilities.
+.TP
+.I /etc/insserv/overrides/
+path to replace existing LSB comment headers with the comment
+headers found in this path.
+.TP
+.I /etc/init.d/
+path to the
+@@BEGIN_SUSE@@
+SuSE
+@@END_SUSE@@
+init script base directory as
+required by the Linux Standard Base Specification (LSB).
+.PP
+.IR /etc/init.d/.depend.boot ,
+.br
+.IR /etc/init.d/.depend.start ,
+.br
+.I  /etc/init.d/.depend.stop
+.in +7
+The
+.BR make (1)
+like dependency files produced by
+.B insserv
+for
+.IR booting ", " starting ", and " stopping
+with the help of
+.BR startpar (8).
+.in -7
+
+.\"
+.SH SEE ALSO
+@@BEGIN_SUSE@@
+.BR init.d (7),
+@@END_SUSE@@
+.BR init (7),
+@@BEGIN_SUSE@@
+.BR startproc (8),
+.BR checkproc (8),
+.BR killproc (8),
+@@END_SUSE@@
+.BR startpar (8).
+.SH COPYRIGHT
+2000\-2008 Werner Fink,
+.br
+2000\-2003 SuSE GmbH Nuernberg, Germany,
+.br
+2007 SuSE Linux Products GmbH Nuernberg, Germany.
+.br
+2008 SuSE Linux Products GmbH Nuernberg, Germany.
+.SH AUTHOR
+Werner Fink <feedback@suse.de>
diff --git a/insserv.c b/insserv.c
new file mode 100644 (file)
index 0000000..8b647ee
--- /dev/null
+++ b/insserv.c
@@ -0,0 +1,3461 @@
+/*
+ * insserv(.c)
+ *
+ * Copyright 2000-2008 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
+ *                                 2003 SuSE Linux AG, Germany.
+ *                                 2004 SuSE LINUX AG, Germany.
+ *                            2005-2008 SUSE LINUX Products GmbH, Germany.
+ * Copyright 2005,2008 Petter Reinholdtsen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#define MINIMAL_MAKE   1       /* Remove disabled scripts from .depend.boot,
+                                * .depend.start, .depend.halt, and .depend.stop */
+#define MINIMAL_RULES  1       /* ditto */
+
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/syscall.h>
+#include <dirent.h>
+#include <regex.h>
+#include <errno.h>
+#include <limits.h>
+#include <getopt.h>
+#if defined(USE_RPMLIB) && (USE_RPMLIB > 0)
+# include <rpm/rpmlib.h>
+# include <rpm/rpmmacro.h>
+#endif /* USE_RPMLIB */
+#include "listing.h"
+
+#ifdef SUSE
+# define DEFAULT_START_LVL     "3 5"
+# define DEFAULT_STOP_LVL      "3 5"
+# define USE_KILL_IN_BOOT      1
+# define USE_COMPAT_EMPTY      1
+static inline void oneway(char *restrict stop) attribute((always_inline,nonnull(1)));
+static inline void oneway(char *restrict stop)
+{
+    char * ptr = stop;
+    while ((ptr = strpbrk(ptr, "016sS")))
+       *ptr++ = ' ';
+}
+#else /* not SUSE, but Debian */
+# define DEFAULT_START_LVL     "2 3 4 5"
+# define DEFAULT_STOP_LVL      "0 1 6"
+# define DEFAULT_DEPENDENCY    "$remote_fs $syslog"
+# undef  USE_KILL_IN_BOOT
+# undef  USE_COMPAT_EMPTY
+#endif /* not SUSE, but Debian */
+
+#ifndef  INITDIR
+# define INITDIR       "/etc/init.d"
+#endif
+#ifndef  OVERRIDEDIR
+# define OVERRIDEDIR   "/etc/insserv/overrides"
+#endif
+#ifndef  INSCONF
+# define INSCONF       "/etc/insserv.conf"
+#endif
+
+/*
+ * For a description of regular expressions see regex(7).
+ */
+#define COMM           "^#[[:blank:]]*"
+#define VALUE          ":[[:blank:]]*([[:print:]]*)"
+/* The second substring contains our value (the first is all) */
+#define SUBNUM         2
+#define SUBNUM_SHD     3
+#define START          "[-_]+start"
+#define STOP           "[-_]+stop"
+
+/* The main regular search expressions */
+#define PROVIDES       COMM "provides" VALUE
+#define REQUIRED       COMM "required"
+#define SHOULD         COMM "(x[-_]+[a-z0-9_-]*)?should"
+#define BEFORE         COMM "(x[-_]+[a-z0-9_-]*)?start[-_]+before"
+#define AFTER          COMM "(x[-_]+[a-z0-9_-]*)?stop[-_]+after"
+#define DEFAULT                COMM "default"
+#define REQUIRED_START  REQUIRED START VALUE
+#define REQUIRED_STOP  REQUIRED STOP  VALUE
+#define SHOULD_START   SHOULD   START VALUE
+#define SHOULD_STOP    SHOULD   STOP  VALUE
+#define START_BEFORE   BEFORE   VALUE
+#define STOP_AFTER     AFTER    VALUE
+#define DEFAULT_START  DEFAULT  START VALUE
+#define DEFAULT_STOP   DEFAULT  STOP  VALUE
+#define DESCRIPTION    COMM "description" VALUE
+
+/* System facility search within /etc/insserv.conf */
+#define EQSIGN         "([[:blank:]]*[=:][[:blank:]]*|[[:blank:]]+)"
+#define CONFLINE       "^(\\$[a-z0-9_-]+)" EQSIGN "([[:print:]]*)"
+#define CONFLINE2      "^(<[a-z0-9_-]+>)"  EQSIGN "([[:print:]]*)"
+#define SUBCONF                2
+#define SUBCONFNUM     4
+
+/* The root file system */
+static char *root;
+
+/* The main line buffer if unique */
+static char buf[LINE_MAX];
+
+/* When to be verbose */
+static boolean verbose = false;
+
+/* When to be verbose */
+static boolean dryrun = false;
+
+/* When paths set do not add root if any */
+static boolean set_override = false;
+static boolean set_insconf = false;
+
+/* Search results points here */
+typedef struct lsb_struct {
+    char *provides;
+    char *required_start;
+    char *required_stop;
+    char *should_start;
+    char *should_stop;
+    char *start_before;
+    char *stop_after;
+    char *default_start;
+    char *default_stop;
+    char *description;
+} attribute((aligned(sizeof(char*)))) lsb_t;
+
+/* Search results points here */
+typedef struct reg_struct {
+    regex_t prov;
+    regex_t req_start;
+    regex_t req_stop;
+    regex_t shl_start;
+    regex_t shl_stop;
+    regex_t start_bf;
+    regex_t stop_af;
+    regex_t def_start;
+    regex_t def_stop;
+    regex_t desc;
+} attribute((aligned(sizeof(regex_t)))) reg_t;
+
+typedef struct creg_struct {
+    regex_t isysfaci;
+    regex_t isactive;
+} attribute((aligned(sizeof(regex_t)))) creg_t;
+
+static lsb_t script_inf;
+static reg_t reg;
+static creg_t creg;
+static char empty[1] = "";
+
+/* Delimeters used for spliting results with strsep(3) */
+const char *const delimeter = " ,;\t";
+
+/*
+ * push and pop directory changes: pushd() and popd()
+ */
+typedef struct pwd_struct {
+    list_t     deep;
+    char       *pwd;
+} __align pwd_t;
+#define getpwd(list)   list_entry((list), struct pwd_struct, deep)
+
+static list_t pwd = { &pwd, &pwd }, * topd = &pwd;
+
+static void pushd(const char *restrict const path) attribute((nonnull(1)));
+static void pushd(const char *restrict const path)
+{
+    pwd_t *restrict dir;
+
+    if (posix_memalign((void*)&dir, sizeof(void*), alignof(pwd_t)) == 0) {
+       if (!(dir->pwd = getcwd((char*)0, 0)))
+           goto err;
+       insert(&dir->deep, topd->prev);
+       if (chdir(path) < 0)
+           goto err;
+       return;
+    }
+err:
+    error ("pushd() can not change to directory %s: %s\n", path, strerror(errno));
+}
+
+static void popd(void)
+{
+    pwd_t * dir;
+
+    if (list_empty(topd))
+       goto out;
+    dir = getpwd(topd->prev);
+    if (chdir(dir->pwd) < 0)
+       error ("popd() can not change directory %s: %s\n", dir->pwd, strerror(errno));
+    delete(topd->prev);
+    free(dir->pwd);
+    free(dir);
+out:
+    return;
+}
+
+/*
+ * Linked list of system facilities services and their replacment
+ */
+typedef struct string {
+    int *restrict ref;
+    char       *name;
+} __align string_t;
+
+typedef struct repl {
+    list_t     r_list;
+    string_t    r[1];
+} __align repl_t;
+#define getrepl(arg)   list_entry((arg), struct repl, r_list)
+
+typedef struct faci {
+    list_t      list;
+    list_t    replace;
+    char       *name;
+} __align faci_t;
+#define getfaci(arg)   list_entry((arg), struct faci, list)
+
+static list_t sysfaci = { &sysfaci, &sysfaci }, *sysfaci_start = &sysfaci;
+
+/*
+ * Remember requests for required or should services and expand `$' token
+ */
+static void rememberreq(service_t *restrict serv, uint bit,
+                       const char *restrict required) attribute((noinline,nonnull(1,3)));
+static void rememberreq(service_t * restrict serv, uint bit, const char * restrict required)
+{
+    const char type = (bit & REQ_KILL) ? 'K' : 'S';
+    const char * token;
+    char * tmp = strdupa(required);
+    list_t * ptr, * list;
+    ushort old = bit;
+
+    if (!tmp)
+       error("%s", strerror(errno));
+
+    while ((token = strsep(&tmp, delimeter)) && *token) {
+       service_t * req, * here, * need;
+       boolean found = false;
+
+       bit = old;
+
+       switch(*token) {
+       case '+':
+           /* This is an optional token */
+           token++;
+           bit &= ~REQ_MUST;
+           bit |=  REQ_SHLD;
+       default:
+           req = addservice(token);
+           if (bit & REQ_KILL) {
+               req  = getorig(req);
+               list = &req->sort.rev;
+               here = req;
+               need = serv;
+           } else {
+               serv = getorig(serv);
+               list = &serv->sort.req;
+               here = serv;
+               need = req;
+           }
+           np_list_for_each(ptr, list) {
+               if (!strcmp(getreq(ptr)->serv->name, need->name)) {
+                   getreq(ptr)->flags |= bit;
+                   found = true;
+                   break;
+               }
+           }
+           if (!found) {
+               req_t *restrict this;
+               if (posix_memalign((void*)&this, sizeof(void*), alignof(req_t)) != 0)
+                   error("%s", strerror(errno));
+               memset(this, 0, alignof(req_t));
+               insert(&this->list, list->prev);
+               this->flags = bit;
+               this->serv = need;
+           }
+           /* Expand requested services for sorting */
+           requires(here, need, type);
+           break;
+       case '$':
+           if (strcasecmp(token, "$all") == 0) {
+               serv->attr.flags |= SERV_ALL;
+               break;
+           }
+           /* Expand the `$' token recursively down */
+           list_for_each(ptr, sysfaci_start) {
+               if (!strcmp(token, getfaci(ptr)->name)) {
+                   list_t * lst;
+                   np_list_for_each(lst, &getfaci(ptr)->replace)
+                       rememberreq(serv, bit, getrepl(lst)->r[0].name);
+                   break;
+               }
+           }
+           break;
+       }
+    }
+}
+
+static void reversereq(service_t *restrict serv, uint bit,
+                      const char *restrict list) attribute((noinline,nonnull(1,3)));
+static void reversereq(service_t *restrict serv, uint bit, const char *restrict list)
+{
+    const char * token;
+    char * tmp = strdupa(list);
+    ushort old = bit;
+
+    if (!tmp)
+       error("%s", strerror(errno));
+
+    while ((token = strsep(&tmp, delimeter)) && *token) {
+       service_t * rev;
+       list_t * ptr;
+
+       bit = old;
+
+       switch (*token) {
+       case '+':
+           token++;
+           bit &= ~REQ_MUST;
+           bit |=  REQ_SHLD;
+       default:
+           rev = addservice(token);
+           rememberreq(rev, bit, serv->name);
+           break;
+       case '$':
+           list_for_each(ptr, sysfaci_start) {
+               if (!strcmp(token, getfaci(ptr)->name)) {
+                   list_t * lst;
+                   np_list_for_each(lst, &getfaci(ptr)->replace)
+                       reversereq(serv, bit, getrepl(lst)->r[0].name);
+                   break;
+               }
+           }
+           break;
+       }
+    }
+}
+
+/*
+ * Check required services for name
+ */
+static boolean chkrequired(service_t *restrict serv) attribute((nonnull(1)));
+static boolean chkrequired(service_t *restrict serv)
+{
+    boolean ret = true;
+    list_t * pos;
+
+    if (!serv)
+       goto out;
+    serv = getorig(serv);
+
+    np_list_for_each(pos, &serv->sort.req) {
+       req_t *req = getreq(pos);
+       service_t * must;
+
+       if ((req->flags & REQ_MUST) == 0)
+           continue;
+       must = req->serv;
+       must = getorig(must);
+
+       if ((must->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) == 0) {
+           warn("Service %s has to be enabled to start service %s\n",
+                req->serv->name, serv->name);
+           ret = false;
+       }
+    }
+#if 0
+    if (serv->attr.flags & (SERV_CMDLINE|SERV_ENABLED))
+       goto out;
+    np_list_for_each(pos, &serv->sort.rev) {
+       req_t *rev = getreq(pos);
+       service_t * must;
+
+       if ((rev->flags & REQ_MUST) == 0)
+           continue;
+       must = rev->serv;
+       must = getorig(must);
+
+       if (must->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) {
+           warn("Service %s has to be enabled to stop service %s\n",
+                serv->name, rev->serv->name);
+           ret = false;
+       }
+    }
+#endif
+out:
+    return ret;
+}
+
+/*
+ * Check dependencies for name as a service
+ */
+static boolean chkdependencies(service_t *restrict serv) attribute((nonnull(1)));
+static boolean chkdependencies(service_t *restrict serv)
+{
+    const char * const name = serv->name;
+    boolean ret = true;
+    list_t * ptr;
+
+    list_for_each(ptr, s_start) {
+       service_t * cur = getservice(ptr);
+       list_t * pos;
+
+       if (!cur)
+           continue;
+
+       if ((cur->attr.flags & SERV_ENABLED) == 0)
+           continue;
+
+       if (cur->attr.flags & SERV_DUPLET)
+           continue;
+
+       if (list_empty(&cur->sort.req))
+           continue;
+
+       np_list_for_each(pos, &cur->sort.req) {
+           req_t *req = getreq(pos);
+           const ushort flags = req->serv->attr.flags;
+
+           if (!(req->flags & REQ_MUST))
+               continue;
+
+           if (strcmp(req->serv->name, name) != 0)
+               continue;
+
+           if ((cur->attr.flags & SERV_CMDLINE) && (flags & SERV_CMDLINE))
+               continue;
+
+           warn("Service %s has to be enabled to start service %s\n",
+                name, cur->name);
+           ret = false;
+       }
+    }
+    return ret;
+}
+
+/*
+ * This helps us to work out the current symbolic link structure
+ */
+static inline service_t * current_structure(const char *const restrict this, const char order,
+                                    const int runlvl, const char type) attribute((always_inline,nonnull(1)));
+static inline service_t * current_structure(const char *const this, const char order,
+                                    const int runlvl, const char type)
+{
+    service_t * serv = addservice(this);
+    level_t * run;
+    ushort here = map_runlevel_to_lvl(runlvl);
+
+    if (type == 'K') {
+       run = serv->stopp;
+       if (!serv->attr.korder)
+           serv->attr.korder = 99;
+       if (serv->attr.korder > order)
+           serv->attr.korder = order;
+#ifdef SUSE
+       /* This because SuSE boot script concept uses a differential link scheme. */
+       here &= ~LVL_ONEWAY;
+#endif /* SUSE */
+    } else {
+       run = serv->start;
+       if (serv->attr.sorder < order)
+           serv->attr.sorder = order;
+    }
+    run->lvl |= here;
+
+    return serv;
+}
+
+static void setlsb(const char *restrict const name) attribute((unused));
+static void setlsb(const char *restrict const name)
+{
+    service_t * serv = findservice(name);
+    if (serv)
+       serv->attr.flags &= ~SERV_NOTLSB;
+}
+
+/*
+ * This helps us to set none LSB conform scripts to required
+ * max order, therefore we set a dependency to the first
+ * lsb conform service found in current link scheme.
+ */
+static inline void nonlsb_script(void) attribute((always_inline));
+static inline void nonlsb_script(void)
+{
+    list_t * pos;
+
+    list_for_each(pos, s_start) {
+       if (getservice(pos)->attr.flags & SERV_NOTLSB) {
+           service_t * req, * srv = getservice(pos);
+           list_t * tmp;
+           uchar max;
+
+           max = 0;
+           req = (service_t*)0;
+           list_for_each(tmp, s_start) {
+               service_t * cur = getservice(tmp);
+               if (cur->attr.flags & SERV_NOTLSB)
+                   continue;
+               if ((cur->attr.flags & SERV_ENABLED) == 0)
+                   continue;
+               if (!cur->attr.sorder)
+                   continue;
+               if ((srv->start->lvl & cur->start->lvl) == 0)
+                   continue;
+               if (cur->attr.sorder >= srv->attr.sorder)
+                   continue;
+               if (max < cur->attr.sorder) {
+                   max = cur->attr.sorder;
+                   req = cur;
+               }
+           }
+
+           if (req)
+               requires(srv, req, 'S');
+
+           max = 99;
+           req = (service_t*)0;
+           list_for_each(tmp, s_start) {
+               service_t * cur = getservice(tmp);
+               if (cur->attr.flags & SERV_NOTLSB)
+                   continue;
+               if ((cur->attr.flags & SERV_ENABLED) == 0)
+                   continue;
+               if (!cur->attr.korder)
+                   continue;
+               if ((srv->stopp->lvl & cur->stopp->lvl) == 0)
+                   continue;
+               if (cur->attr.korder <= srv->attr.korder)
+                   continue;
+               if (max > cur->attr.korder) {
+                   max = cur->attr.korder;
+                   req = cur;
+               }
+           }
+
+           if (req)
+               requires(req, srv, 'K');
+       }
+    }
+}
+
+/*
+ * This helps us to get interactive scripts to be the only service
+ * within on start or stop service group. Remaining problem is that
+ * if required scripts are missed the order can be wrong.
+ */
+static inline void active_script(void) attribute((always_inline));
+static inline void active_script(void)
+{
+    list_t * pos;
+    int deep = 1;
+
+    for (deep = 0; deep < 100; deep++) {
+       list_for_each(pos, s_start) {
+           service_t * serv = getservice(pos);
+           list_t * tmp;
+
+           if (serv->attr.script == (char*)0)
+               continue;
+
+           if ((serv->attr.flags & SERV_INTRACT) == 0)
+               continue;
+
+           serv->attr.sorder = getorder(serv->attr.script, 'S');
+
+           if (serv->attr.sorder != deep)
+               continue;
+
+           if (serv->attr.flags & SERV_DUPLET)
+               continue;               /* Duplet */
+
+           list_for_each(tmp, s_start) {
+               service_t * cur = getservice(tmp);
+               const char * script;
+
+               if (getorig(cur) == serv)
+                   continue;
+
+               if ((serv->start->lvl & cur->start->lvl) == 0)
+                   continue;
+
+               /*
+                * Use real script name for getorder()/setorder()
+                */
+               if (cur->attr.script == (char*)0)
+                   continue;
+               script = cur->attr.script;
+
+               cur->attr.sorder = getorder(script, 'S');
+
+               if (cur->attr.sorder != deep)
+                   continue;
+               /*
+                * Increase order of members of the same start
+                * group and recalculate dependency order (`true')
+                */
+               setorder(script, 'S', ++cur->attr.sorder, true);
+           }
+       }
+    }
+}
+
+/*
+ * Last but not least the `$all' scripts will be set to the
+ * end of the current start order.
+ */
+static inline void all_script(void) attribute((always_inline));
+static inline void all_script(void)
+{
+    list_t * pos;
+
+    list_for_each(pos, s_start) {
+       service_t * serv = getservice(pos);
+       list_t * tmp;
+       int neworder;
+
+       if (serv->attr.flags & SERV_DUPLET)
+           continue;                   /* Duplet */
+
+       if (!(serv->attr.flags & SERV_ALL))
+           continue;
+
+       if (serv->attr.script == (char*)0)
+           continue;
+
+       neworder = 0;
+       list_for_each(tmp, s_start) {
+           service_t * cur = getservice(tmp);
+
+           if (cur->attr.flags & SERV_DUPLET)
+               continue;               /* Duplet */
+
+           if ((serv->start->lvl & cur->start->lvl) == 0)
+               continue;
+
+           if (cur->attr.script == (char*)0)
+               continue;
+
+           if (cur == serv)
+               continue;
+
+           if (cur->attr.flags & SERV_ALL)
+               continue;
+
+           cur->attr.sorder = getorder(cur->attr.script, 'S');
+
+           if (cur->attr.sorder > neworder)
+               neworder = cur->attr.sorder;
+       }
+       neworder++;
+
+       if      (neworder > MAX_DEEP)
+           neworder = maxstart;
+       else if (neworder > maxstart)
+           maxstart = neworder;
+
+       setorder(serv->attr.script, 'S', neworder, false);
+    }
+}
+
+/*
+ * Make the dependency files
+ */
+static inline void makedep(void) attribute((always_inline));
+static inline void makedep(void)
+{
+    FILE *boot, *start, *stop, *out;
+#ifdef USE_KILL_IN_BOOT
+    FILE *halt;
+#endif /* USE_KILL_IN_BOOT */
+    const char *target;
+    service_t *serv;
+
+    if (dryrun) {
+#ifdef USE_KILL_IN_BOOT
+       info("dryrun, not creating .depend.boot, .depend.start, .depend.halt, and .depend.stop\n");
+#else  /* not USE_KILL_IN_BOOT */
+       info("dryrun, not creating .depend.boot, .depend.start, and .depend.stop\n");
+#endif /* not USE_KILL_IN_BOOT */
+       return;
+    }
+    if (!(boot  = fopen(".depend.boot",  "w"))) {
+       warn("fopen(.depend.stop): %s\n", strerror(errno));
+       return;
+    }
+
+    if (!(start = fopen(".depend.start", "w"))) {
+       warn("fopen(.depend.start): %s\n", strerror(errno));
+       fclose(boot);
+       return;
+    }
+
+    info("creating .depend.boot\n");
+    info("creating .depend.start\n");
+
+    lsort('S');                                        /* Sort into start order, set new sorder */
+
+    target = (char*)0;
+    fprintf(boot, "TARGETS =");
+    while ((serv = listscripts(&target, 'S', LVL_BOOT))) {
+       if (!serv)
+           continue;
+#if defined(MINIMAL_MAKE) && (MINIMAL_MAKE != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+#endif /* MINIMAL_MAKE */
+       fprintf(boot, " %s", target);
+    }
+    fputc('\n', boot);
+
+    target = (char*)0;
+    fprintf(start, "TARGETS =");
+    while ((serv = listscripts(&target, 'S', LVL_ALL))) {      /* LVL_ALL: nearly all but not BOOT */
+       if (!serv)
+           continue;
+#if defined(MINIMAL_MAKE) && (MINIMAL_MAKE != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+#endif /* MINIMAL_MAKE */
+       fprintf(start, " %s", target);
+    }
+    fputc('\n', start);
+
+    fprintf(boot,  "INTERACTIVE =");
+    fprintf(start, "INTERACTIVE =");
+
+    target = (char*)0;
+    while ((serv = listscripts(&target, 'S', LVL_BOOT|LVL_ALL))) {
+       if (!serv)
+           continue;
+#if defined(MINIMAL_MAKE) && (MINIMAL_MAKE != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+#endif /* not MINIMAL_MAKE */
+
+       if (list_empty(&serv->sort.req))
+           continue;
+
+       if (serv->start->lvl & LVL_BOOT)
+           out = boot;
+       else
+           out = start;
+
+       if (serv->attr.flags & SERV_INTRACT)
+           fprintf(out, " %s", target);
+    }
+    fputc('\n', boot);
+    fputc('\n', start);
+
+    target = (char*)0;
+    while ((serv = listscripts(&target, 'S', LVL_BOOT|LVL_ALL))) {
+       boolean mark;
+       list_t * pos;
+
+       if (!serv)
+           continue;
+#if defined(MINIMAL_RULES) && (MINIMAL_RULES != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+#endif /* not MINIMAL_RULES */
+
+       if (list_empty(&serv->sort.req))
+           continue;
+
+       if (serv->start->lvl & LVL_BOOT)
+           out = boot;
+       else
+           out = start;
+
+       mark = false;
+       if (serv->attr.flags & SERV_ALL) {
+           list_for_each(pos, s_start) {
+               service_t * dep = getservice(pos);
+               const char * name;
+
+               if (!dep)
+                   continue;
+
+               if (dep->attr.flags & SERV_DUPLET)
+                   continue;                   /* Duplet */
+
+#if defined(MINIMAL_RULES) && (MINIMAL_RULES != 0)
+               if (dep->attr.ref <= 0)
+                   continue;
+#endif /* not MINIMAL_RULES */
+
+               /*
+                * No self dependcies or from the last
+                */
+               if (dep == serv || (dep->attr.flags & SERV_ALL))
+                   continue;
+
+               if ((serv->start->lvl & dep->start->lvl) == 0)
+                   continue;
+
+               if ((name = dep->attr.script) == (char*)0)
+                   continue;
+
+               if (!mark) {
+                   fprintf(out, "%s:", target);
+                   mark = true;
+               }
+               fprintf(out, " %s", name);
+           }
+       } else {
+           np_list_for_each(pos, &serv->sort.req) {
+               req_t * req = getreq(pos);
+               service_t * dep = req->serv;
+               const char * name;
+
+               if (!dep)
+                   continue;
+
+               if (dep->attr.flags & SERV_DUPLET)
+                   continue;
+
+#if defined(MINIMAL_RULES) && (MINIMAL_RULES != 0)
+               if (dep->attr.ref <= 0)
+                   continue;
+#endif /* not MINIMAL_RULES */
+
+               /*
+                * No self dependcies or from the last
+                */
+               if (dep == serv || (dep->attr.flags & SERV_ALL))
+                   continue;
+
+               if ((serv->start->lvl & dep->start->lvl) == 0)
+                   continue;
+
+               if ((name = dep->attr.script) == (char*)0)
+                   continue;
+
+               if (!mark) {
+                   fprintf(out, "%s:", target);
+                   mark = true;
+               }
+               fprintf(out, " %s", name);
+           }
+       }
+       if (mark) fputc('\n', out);
+    }
+
+    fclose(boot);
+    fclose(start);
+
+    if (!(stop  = fopen(".depend.stop",  "w"))) {
+       warn("fopen(.depend.stop): %s\n", strerror(errno));
+       return;
+    }
+
+#ifdef USE_KILL_IN_BOOT
+    if (!(halt = fopen(".depend.halt", "w"))) {
+       warn("fopen(.depend.start): %s\n", strerror(errno));
+       fclose(stop);
+       return;
+    }
+
+    info("creating .depend.halt\n");
+#endif /* USE_KILL_IN_BOOT */
+    info("creating .depend.stop\n");
+
+    lsort('K');                                        /* Sort into stop order, set new korder */
+
+    target = (char*)0;
+    fprintf(stop, "TARGETS =");
+    while ((serv = listscripts(&target, 'K', LVL_NORM))) {     /* LVL_NORM: nearly all but not BOOT and not SINGLE */
+       if (!serv)
+           continue;
+#if defined(MINIMAL_MAKE) && (MINIMAL_MAKE != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+#endif /* MINIMAL_MAKE */
+       fprintf(stop, " %s", target);
+    }
+    fputc('\n', stop);
+
+#ifdef USE_KILL_IN_BOOT
+    target = (char*)0;
+    fprintf(halt, "TARGETS =");
+    while ((serv = listscripts(&target, 'K', LVL_BOOT))) {
+       if (!serv)
+           continue;
+# if defined(MINIMAL_MAKE) && (MINIMAL_MAKE != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+# endif /* MINIMAL_MAKE */
+       fprintf(halt, " %s", target);
+    }
+    fputc('\n', halt);
+#endif /* USE_KILL_IN_BOOT */
+
+    target = (char*)0;
+    while ((serv = listscripts(&target, 'K', (LVL_NORM|LVL_BOOT)))) {
+       boolean mark;
+       list_t * pos;
+
+       if (!serv)
+           continue;
+#if defined(MINIMAL_RULES) && (MINIMAL_RULES != 0)
+       if (serv->attr.ref <= 0)
+           continue;
+#endif /* not MINIMAL_RULES */
+
+       if (list_empty(&serv->sort.rev))
+           continue;
+
+       if (serv->stopp->lvl & LVL_BOOT)
+#ifdef USE_KILL_IN_BOOT
+           out = halt;
+       else
+#else  /* not USE_KILL_IN_BOOT */
+           continue;
+#endif /* not USE_KILL_IN_BOOT */
+       out = stop;
+
+       mark = false;
+       np_list_for_each(pos, &serv->sort.rev) {
+           req_t * rev = getreq(pos);
+           service_t * dep = rev->serv;
+           const char * name;
+
+           if (!dep)
+               continue;
+
+           if (dep->attr.flags & (SERV_DUPLET|SERV_NOSTOP))
+               continue;                       /* Duplet or no stop link */
+
+#if defined(MINIMAL_RULES) && (MINIMAL_RULES != 0)
+           if (dep->attr.ref <= 0)
+               continue;
+#endif /* not MINIMAL_RULES */
+
+           if ((serv->stopp->lvl & dep->stopp->lvl) == 0)
+               continue;
+
+           if ((name = dep->attr.script) == (char*)0)
+               continue;
+
+           if (!mark) {
+               fprintf(out, "%s:", target);
+               mark = true;
+           }
+           fprintf(out, " %s", name);
+       }
+       if (mark) fputc('\n', out);
+    }
+
+#ifdef USE_KILL_IN_BOOT
+    fclose(halt);
+#endif /* USE_KILL_IN_BOOT */
+    fclose(stop);
+}
+
+/*
+ * Internal logger
+ */
+char *myname = (char*)0;
+static void _logger (const char *restrict const fmt, va_list ap);
+static void _logger (const char *restrict const fmt, va_list ap)
+{
+    extension char buf[strlen(myname)+2+strlen(fmt)+1];
+    strcat(strcat(strcpy(buf, myname), ": "), fmt);
+    vfprintf(stderr, buf, ap);
+    return;
+}
+
+/*
+ * Cry and exit.
+ */
+void error (const char *restrict const fmt, ...)
+{
+    static char called;
+    va_list ap;
+    if (called++)
+       exit (1);
+    va_start(ap, fmt);
+    _logger(fmt, ap);
+    va_end(ap);
+    popd();
+    exit (1);
+}
+
+/*
+ * Warn the user.
+ */
+void warn (const char *restrict const fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    _logger(fmt, ap);
+    va_end(ap);
+    return;
+}
+
+/*
+ * Print message when verbose is enabled
+ */
+void info(const char *fmt, ...) {
+    va_list ap;
+    if (!verbose)
+       goto out;
+    va_start(ap, fmt);
+    _logger(fmt, ap);
+    va_end(ap);
+out:
+    return;
+}
+
+/*
+ *  Check for script in list.
+ */
+static int curr_argc = -1;
+static inline boolean chkfor(const char *restrict const script,
+                            char **restrict const list, const int cnt) attribute((nonnull(1,2)));
+static inline boolean chkfor(const char *restrict const script, char **restrict const list, const int cnt)
+{
+    boolean isinc = false;
+    register int c = cnt;
+
+    curr_argc = -1;
+    while (c--) {
+       if (*script != *list[c])
+           continue;
+       if (!strcmp(script, list[c])) {
+           isinc = true;
+           curr_argc = c;
+           break;
+       }
+    }
+    return isinc;
+}
+
+/*
+ * Open a runlevel directory, if it not
+ * exists than create one.
+ */
+static DIR * openrcdir(const char *restrict const rcpath) attribute((nonnull(1)));
+static DIR * openrcdir(const char *restrict const rcpath)
+{
+   DIR * rcdir;
+   struct stat st;
+   int dfd;
+
+    if (stat(rcpath, &st) < 0) {
+       if (errno == ENOENT) {
+           info("creating directory '%s'\n", rcpath);
+           if (!dryrun)
+               mkdir(rcpath, (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH));
+       } else
+           error("can not stat(%s): %s\n", rcpath, strerror(errno));
+    }
+
+    if ((rcdir = opendir(rcpath)) == (DIR*)0) {
+       if (dryrun)
+           warn ("can not opendir(%s): %s\n", rcpath, strerror(errno));
+       else
+           error("can not opendir(%s): %s\n", rcpath, strerror(errno));
+    }
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+    else if ((dfd = dirfd(rcdir)) != 0) {
+       (void)posix_fadvise(dfd, 0, 0, POSIX_FADV_WILLNEED);
+       (void)posix_fadvise(dfd, 0, 0, POSIX_FADV_SEQUENTIAL);
+    }
+#endif
+    return rcdir;
+}
+
+/*
+ * Wrapper for regcomp(3)
+ */
+static inline void regcompiler(regex_t *restrict preg,
+                              const char *restrict regex,
+                              int cflags) attribute((always_inline,nonnull(1,2)));
+static inline void regcompiler(regex_t *restrict preg, const char *restrict regex, int cflags)
+{
+    register int ret = regcomp(preg, regex, cflags);
+    if (ret) {
+       regerror(ret, preg, buf, sizeof (buf));
+       regfree (preg);
+       error("%s\n", buf);
+    }
+    return;
+}
+
+/*
+ * Wrapper for regexec(3)
+ */
+static inline boolean regexecutor(regex_t *restrict preg,
+                                 const char *restrict string,
+                                 size_t nmatch, regmatch_t pmatch[], int eflags) attribute((nonnull(1,2)));
+static inline boolean regexecutor(regex_t *preg, const char *string,
+       size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+    register int ret = regexec(preg, string, nmatch, pmatch, eflags);
+    if (ret > REG_NOMATCH) {
+       regerror(ret, preg, buf, sizeof (buf));
+       regfree (preg);
+       warn("%s\n", buf);
+    }
+    return (ret ? false : true);
+}
+
+/*
+ * The script scanning engine.
+ * We have to alloc the regular expressions first before
+ * calling scan_script_defaults().  After the last call
+ * of scan_script_defaults() we may free the expressions.
+ */
+static inline void scan_script_regalloc(void) attribute((always_inline));
+static inline void scan_script_regalloc(void)
+{
+    regcompiler(&reg.prov,      PROVIDES,       REG_EXTENDED|REG_ICASE);
+    regcompiler(&reg.req_start, REQUIRED_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.req_stop,  REQUIRED_STOP,  REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.shl_start, SHOULD_START,   REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.shl_stop,  SHOULD_STOP,    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.start_bf,  START_BEFORE,   REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.stop_af,   STOP_AFTER,     REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.def_start, DEFAULT_START,  REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.def_stop,  DEFAULT_STOP,   REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+    regcompiler(&reg.desc,      DESCRIPTION,    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+}
+
+static inline void scan_script_reset(void) attribute((always_inline));
+static inline void scan_script_reset(void)
+{
+    xreset(script_inf.provides);
+    xreset(script_inf.required_start);
+    xreset(script_inf.required_stop);
+    xreset(script_inf.should_start);
+    xreset(script_inf.should_stop);
+    xreset(script_inf.start_before);
+    xreset(script_inf.stop_after);
+    xreset(script_inf.default_start);
+    xreset(script_inf.default_stop);
+    xreset(script_inf.description);
+}
+
+#define FOUND_LSB_HEADER   0x01
+#define FOUND_LSB_DEFAULT  0x02
+#define FOUND_LSB_OVERRIDE 0x04
+
+static int o_flags = O_RDONLY;
+
+static uchar scan_lsb_headers(const int dfd, const char *restrict const path,
+                             const boolean cache, const boolean ignore) attribute((nonnull(2)));
+static uchar scan_lsb_headers(const int dfd, const char *restrict const path,
+                             const boolean cache, const boolean ignore)
+{
+    regmatch_t subloc[SUBNUM_SHD+1], *val = &subloc[SUBNUM-1], *shl = &subloc[SUBNUM_SHD-1];
+    char *begin = (char*)0, *end = (char*)0;
+    char *pbuf = buf;
+    FILE *script;
+    uchar ret = 0;
+    int fd;
+
+#define provides       script_inf.provides
+#define required_start script_inf.required_start
+#define required_stop  script_inf.required_stop
+#define should_start   script_inf.should_start
+#define should_stop    script_inf.should_stop
+#define start_before   script_inf.start_before
+#define stop_after     script_inf.stop_after
+#define default_start  script_inf.default_start
+#define default_stop   script_inf.default_stop
+#define description    script_inf.description
+
+    info("Loading %s\n", path);
+
+    if ((fd = xopen(dfd, path, o_flags)) < 0 || (script = fdopen(fd, "r")) == (FILE*)0)
+       error("fopen(%s): %s\n", path, strerror(errno));
+
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+    (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
+#define COMMON_ARGS    buf, SUBNUM, subloc, 0
+#define COMMON_SHD_ARGS        buf, SUBNUM_SHD, subloc, 0
+    while (fgets(buf, sizeof(buf), script)) {
+
+       /* Skip scanning above from LSB magic start */
+       if (!begin) {
+           if ( (begin = strstr(buf, "### BEGIN INIT INFO")) ) {
+               /* Let the latest LSB header override the one found earlier */
+               scan_script_reset();
+           }
+           continue;
+       }
+
+       if (!provides       && regexecutor(&reg.prov,      COMMON_ARGS) == true) {
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               provides = xstrdup(pbuf+val->rm_so);
+           } else
+               provides = empty;
+       }
+       if (!required_start && regexecutor(&reg.req_start, COMMON_ARGS) == true) {
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               required_start = xstrdup(pbuf+val->rm_so);
+           } else
+               required_start = empty;
+       }
+       if (!required_stop  && regexecutor(&reg.req_stop,  COMMON_ARGS) == true) {
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               required_stop = xstrdup(pbuf+val->rm_so);
+           } else
+               required_stop = empty;
+       }
+       if (!should_start && regexecutor(&reg.shl_start,   COMMON_SHD_ARGS) == true) {
+           if (shl->rm_so < shl->rm_eo) {
+               *(pbuf+shl->rm_eo) = '\0';
+               should_start = xstrdup(pbuf+shl->rm_so);
+           } else
+               should_start = empty;
+       }
+       if (!should_stop  && regexecutor(&reg.shl_stop,    COMMON_SHD_ARGS) == true) {
+           if (shl->rm_so < shl->rm_eo) {
+               *(pbuf+shl->rm_eo) = '\0';
+               should_stop = xstrdup(pbuf+shl->rm_so);
+           } else
+               should_stop = empty;
+       }
+       if (!start_before && regexecutor(&reg.start_bf,    COMMON_SHD_ARGS) == true) {
+           if (shl->rm_so < shl->rm_eo) {
+               *(pbuf+shl->rm_eo) = '\0';
+               start_before = xstrdup(pbuf+shl->rm_so);
+           } else
+               start_before = empty;
+       }
+       if (!stop_after  && regexecutor(&reg.stop_af,      COMMON_SHD_ARGS) == true) {
+           if (shl->rm_so < shl->rm_eo) {
+               *(pbuf+shl->rm_eo) = '\0';
+               stop_after = xstrdup(pbuf+shl->rm_so);
+           } else
+               stop_after = empty;
+       }
+       if (!default_start  && regexecutor(&reg.def_start, COMMON_ARGS) == true) {
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               default_start = xstrdup(pbuf+val->rm_so);
+           } else
+               default_start = empty;
+       }
+#ifndef SUSE
+       if (!default_stop   && regexecutor(&reg.def_stop,  COMMON_ARGS) == true) {
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               default_stop = xstrdup(pbuf+val->rm_so);
+           } else
+               default_stop = empty;
+       }
+#endif
+       if (!description    && regexecutor(&reg.desc,      COMMON_ARGS) == true) {
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               description = xstrdup(pbuf+val->rm_so);
+           } else
+               description = empty;
+       }
+
+       /* Skip scanning below from LSB magic end */
+       if ((end = strstr(buf, "### END INIT INFO")))
+           break;
+    }
+#undef COMMON_ARGS
+#undef COMMON_SHD_ARGS
+
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+    if (cache) {
+       off_t deep = ftello(script);
+       (void)posix_fadvise(fd, 0, deep, POSIX_FADV_WILLNEED);
+       (void)posix_fadvise(fd, deep, 0, POSIX_FADV_DONTNEED);
+    } else
+       (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
+#endif
+
+    fclose(script);
+
+    if (begin && end)
+       ret |= FOUND_LSB_HEADER;
+
+    if (begin && !end) {
+       char *name = basename(path);
+       if (*name == 'S' || *name == 'K')
+           name += 3;
+       warn("Script %s is broken: missing end of LSB comment.\n", name);
+       if (!ignore)
+           error("exiting now!\n");
+    }
+
+    if (begin && end && (!provides || (provides == empty) ||
+#ifdef SUSE
+                        !required_start || !required_stop || !default_start
+#else  /* not SUSE */
+                        !required_start || !required_stop || !default_start || !default_stop
+#endif /* not SUSE */
+       ))
+    {
+       char *name = basename(path);
+       if (*name == 'S' || *name == 'K')
+           name += 3;
+       warn("Script %s is broken: incomplete LSB comment.\n", name);
+       if (!provides)
+           warn("missing `Provides:' entry: please add.\n");
+       if (provides == empty)
+           warn("missing valid name for `Provides:' please add.\n");
+       if (!required_start)
+           warn("missing `Required-Start:' entry: please add even if empty.\n");
+       if (!required_stop)
+           warn("missing `Required-Stop:'  entry: please add even if empty.\n");
+       if (!default_start)
+           warn("missing `Default-Start:'  entry: please add even if empty.\n");
+#ifndef SUSE
+       if (!default_stop)
+           warn("missing `Default-Stop:'   entry: please add even if empty.\n");
+#endif
+    }
+
+#undef provides
+#undef required_start
+#undef required_stop
+#undef should_start
+#undef should_stop
+#undef start_before
+#undef stop_after
+#undef default_start
+#undef default_stop
+#undef description
+    return ret;
+}
+
+/*
+ * Follow symlinks, return the basename of the file pointed to by
+ * symlinks or the basename of the current path if no symlink.
+ */
+static char * scriptname(int dfd, const char *restrict const path, char **restrict first) attribute((malloc,nonnull(2)));
+static char * scriptname(int dfd, const char *restrict const path, char **restrict first)
+{
+    uint deep = 0;
+    char linkbuf[PATH_MAX+1];
+    char *script = xstrdup(path);
+
+    strncpy(linkbuf, script, sizeof(linkbuf)-1);
+    linkbuf[PATH_MAX] = '\0';
+
+    do {
+        struct stat st;
+       int linklen;
+
+       if (deep++ > MAXSYMLINKS) {
+           errno = ELOOP;
+           warn("Can not determine script name for %s: %s\n", path, strerror(errno));
+           break;
+       }
+
+       if (xlstat(dfd, script, &st) < 0) {
+           warn("Can not stat %s: %s\n", script, strerror(errno));
+           break;
+       }
+
+       if (!S_ISLNK(st.st_mode))
+           break;
+
+       if ((linklen = xreadlink(dfd, script, linkbuf, sizeof(linkbuf)-1)) < 0)
+           break;
+       linkbuf[linklen] = '\0';
+
+       if (linkbuf[0] != '/') {        /* restore relative links */
+           const char *lastslash;
+
+           if ((lastslash = strrchr(script, '/'))) {
+               size_t dirname_len = lastslash - script + 1;
+
+               if (dirname_len + linklen > PATH_MAX)
+                   linklen = PATH_MAX - dirname_len;
+
+               memmove(&linkbuf[dirname_len], &linkbuf[0], linklen + 1);
+               memcpy(&linkbuf[0], script, dirname_len);
+           }
+       }
+
+       free(script);
+       script = xstrdup(linkbuf);
+
+       if (deep == 1 && first)
+           *first = xstrdup(basename(linkbuf));
+
+    } while (1);
+
+    free(script);
+    script = xstrdup(basename(linkbuf));
+
+    return script;
+}
+
+static uchar load_overrides(const char *restrict const dir,
+                           const char *restrict const name,
+                           const boolean cache, const boolean ignore) attribute((nonnull(1,2)));
+static uchar load_overrides(const char *restrict const dir,
+                           const char *restrict const name,
+                           const boolean cache, const boolean ignore)
+{
+    uchar ret = 0;
+    char fullpath[PATH_MAX+1];
+    struct stat statbuf;
+    int n;
+
+    n = snprintf(&fullpath[0], sizeof(fullpath), "%s%s/%s", (root && !set_override) ? root : "", dir, name);
+    if (n >= (int)sizeof(fullpath) || n < 0)
+       error("snprintf(): %s\n", strerror(errno));
+
+    if (stat(fullpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
+        ret = scan_lsb_headers(-1, fullpath, cache, ignore);
+    if (ret & FOUND_LSB_HEADER)
+       ret |= FOUND_LSB_OVERRIDE;
+    return ret;
+}
+
+static uchar scan_script_defaults(int dfd, const char *const restrict path,
+                                 const char *const restrict override_path,
+                                 char **restrict first,
+                                 const boolean cache, const boolean ignore) attribute((nonnull(2,3)));
+static uchar scan_script_defaults(int dfd, const char *restrict const path,
+                                 const char *restrict const override_path,
+                                 char **restrict first,
+                                 const boolean cache, const boolean ignore)
+{
+    char * name = scriptname(dfd, path, first);
+    uchar ret = 0;
+
+    if (!name)
+       return ret;
+
+    /* Reset old results */
+    scan_script_reset();
+
+#ifdef SUSE
+    /* Common script ... */
+    if (!strcmp(name, "halt")) {
+       ret |= (FOUND_LSB_HEADER|FOUND_LSB_DEFAULT);
+       goto out;
+    }
+
+    /* ... and its link */
+    if (!strcmp(name, "reboot")) {
+       ret |= (FOUND_LSB_HEADER|FOUND_LSB_DEFAULT);
+       goto out;
+    }
+
+    /* Common script for single mode */
+    if (!strcmp(name, "single")) {
+       ret |= (FOUND_LSB_HEADER|FOUND_LSB_DEFAULT);
+       goto out;
+    }
+#endif /* SUSE */
+
+    /* Replace with headers from the script itself */
+    ret |= scan_lsb_headers(dfd, path, cache, ignore);
+
+    /* Load values if the override file exist */
+    if ((ret & FOUND_LSB_HEADER) == 0)
+       ret |= load_overrides("/usr/share/insserv/overrides", name, cache, ignore);
+    else
+       ret |= FOUND_LSB_DEFAULT;
+
+    /*
+     * Allow host-specific overrides to replace the content in the
+     * init.d scripts
+     */
+    ret |= load_overrides(override_path, name, cache, ignore);
+#ifdef SUSE
+out:
+#endif /* SUSE */
+    free(name);
+    return ret;
+}
+
+static inline void scan_script_regfree() attribute((always_inline));
+static inline void scan_script_regfree()
+{
+    regfree(&reg.prov);
+    regfree(&reg.req_start);
+    regfree(&reg.req_stop);
+    regfree(&reg.shl_start);
+    regfree(&reg.shl_stop);
+    regfree(&reg.start_bf);
+    regfree(&reg.stop_af);
+    regfree(&reg.def_start);
+    regfree(&reg.def_stop);
+    regfree(&reg.desc);
+}
+
+static struct {
+    char *location;
+    const ushort lvl;
+    const ushort seek;
+    const char key;
+} attribute((aligned(sizeof(char*)))) runlevel_locations[] = {
+#ifdef SUSE    /* SuSE's SystemV link scheme */
+    {"rc0.d/",    LVL_HALT,   LVL_NORM, '0'},
+    {"rc1.d/",    LVL_ONE,    LVL_NORM, '1'}, /* runlevel 1 switch over to single user mode */
+    {"rc2.d/",    LVL_TWO,    LVL_NORM, '2'},
+    {"rc3.d/",    LVL_THREE,  LVL_NORM, '3'},
+    {"rc4.d/",    LVL_FOUR,   LVL_NORM, '4'},
+    {"rc5.d/",    LVL_FIVE,   LVL_NORM, '5'},
+    {"rc6.d/",    LVL_REBOOT, LVL_NORM, '6'},
+    {"rcS.d/",    LVL_SINGLE, LVL_NORM, 'S'}, /* runlevel S is for single user mode */
+    {"boot.d/",   LVL_BOOT,   LVL_BOOT, 'B'}, /* runlevel B is for system initialization */
+#else          /* not SUSE (actually, Debian) */
+    {"../rc0.d/", LVL_HALT,   LVL_NORM, '0'},
+    {"../rc1.d/", LVL_ONE,    LVL_NORM, '1'}, /* runlevel 1 switch over to single user mode */
+    {"../rc2.d/", LVL_TWO,    LVL_NORM, '2'},
+    {"../rc3.d/", LVL_THREE,  LVL_NORM, '3'},
+    {"../rc4.d/", LVL_FOUR,   LVL_NORM, '4'},
+    {"../rc5.d/", LVL_FIVE,   LVL_NORM, '5'},
+    {"../rc6.d/", LVL_REBOOT, LVL_NORM, '6'},
+    {"../rcS.d/", LVL_BOOT,   LVL_BOOT, 'S'}, /* runlevel S is for system initialization */
+               /* On e.g. Debian there exist no boot.d */
+#endif         /* not SUSE */
+};
+
+#define RUNLEVLES (int)(sizeof(runlevel_locations)/sizeof(runlevel_locations[0]))
+
+int map_has_runlevels(void)
+{
+    return RUNLEVLES;
+}
+
+char map_runlevel_to_key(const int runlevel)
+{
+    if (runlevel >= RUNLEVLES) {
+       warn("Wrong runlevel %d\n", runlevel);
+    }
+    return runlevel_locations[runlevel].key;
+}
+
+ushort map_key_to_lvl(const char key)
+{
+    int runlevel;
+    const char uckey = toupper(key);
+    for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
+       if (uckey == runlevel_locations[runlevel].key)
+           return runlevel_locations[runlevel].lvl;
+    }
+    warn("Wrong runlevel key '%c'\n", uckey);
+    return 0;
+}
+
+const char *map_runlevel_to_location(const int runlevel)
+{
+    if (runlevel >= RUNLEVLES) {
+       warn("Wrong runlevel %d\n", runlevel);
+    }
+    return runlevel_locations[runlevel].location;
+}
+
+ushort map_runlevel_to_lvl(const int runlevel)
+{
+    if (runlevel >= RUNLEVLES) {
+       warn("Wrong runlevel %d\n", runlevel);
+    }
+    return runlevel_locations[runlevel].lvl;
+}
+
+ushort map_runlevel_to_seek(const int runlevel)
+{
+    return runlevel_locations[runlevel].seek;
+}
+
+/*
+ * Two helpers for runlevel bits and strings.
+ */
+ushort str2lvl(const char *restrict lvl)
+{
+    char * token, *tmp = strdupa(lvl);
+    ushort ret = 0;
+
+    if (!tmp)
+       error("%s", strerror(errno));
+
+    while ((token = strsep(&tmp, delimeter))) {
+       if (!*token || strlen(token) != 1)
+           continue;
+       if (!strpbrk(token, "0123456sSbB"))
+           continue;
+
+        ret |= map_key_to_lvl(*token);
+    }
+
+    return ret;
+}
+
+char * lvl2str(const ushort lvl)
+{
+    char * ptr, * last;
+    char str[20];
+    int num;
+    uint bit = 0x001;
+
+    last = ptr = &str[0];
+    memset(ptr, '\0', sizeof(str));
+    for (num = 0; num < RUNLEVLES; num++) {
+       if (bit & lvl) {
+           if (ptr > last)
+               *ptr++ = ' ';
+           last = ptr;
+           if (LVL_NORM & bit)
+               *ptr++ = num + 48;
+#ifdef SUSE
+           else if (LVL_SINGLE & bit)
+               *ptr++ = 'S';
+           else if (LVL_BOOT & bit)
+               *ptr++ = 'B';
+#else  /* not SUSE */
+           else if (LVL_BOOT & bit)
+               *ptr++ = 'S';
+#endif /* not SUSE */
+           else
+               error("Wrong runlevel %d\n", num);
+       }
+       bit <<= 1;
+    }
+    if (strlen(str) == 0)
+       return (char*)0;
+    return xstrdup(str);
+}
+
+/*
+ * Scan current service structure
+ */
+static void scan_script_locations(const char *const restrict path,
+                                 const char *const restrict override_path,
+                                 const boolean ignore) attribute((nonnull(1,2)));
+static void scan_script_locations(const char *const path, const char *const override_path,
+                                 const boolean ignore)
+{
+    int runlevel;
+
+    pushd(path);
+    for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
+       const char * rcd = (char*)0;
+       struct stat st_script;
+       struct dirent *d;
+       DIR  * rcdir;
+       char * token;
+       int dfd;
+
+       rcd = map_runlevel_to_location(runlevel);
+
+       rcdir = openrcdir(rcd);         /* Creates runlevel directory if necessary */
+       if (rcdir == (DIR*)0)
+           break;
+       if ((dfd = dirfd(rcdir)) < 0) {
+           closedir(rcdir);
+           break;
+       }
+       pushd(rcd);
+
+       while ((d = readdir(rcdir)) != (struct dirent*)0) {
+           char * name = (char *)0;
+           char * ptr = d->d_name;
+           service_t * first;
+           char * begin;               /* Remember address of ptr handled by strsep() */
+           char order;
+           uchar lsb;
+           char type;
+
+           if (*ptr != 'S' && *ptr != 'K')
+               continue;
+           type = *ptr;
+           ptr++;
+
+           if (strspn(ptr, "0123456789") < 2)
+               continue;
+           order = atoi(ptr);
+           ptr += 2;
+
+           if (xstat(dfd, d->d_name, &st_script) < 0) {
+               xremove(dfd, d->d_name);        /* dangling sym link */
+               continue;
+           }
+
+           lsb = scan_script_defaults(dfd, d->d_name, override_path, &name, true, ignore);
+           if (!script_inf.provides || script_inf.provides == empty)
+               script_inf.provides = xstrdup(ptr);
+
+#ifndef SUSE
+           if (!lsb) {
+               script_inf.required_start = xstrdup(DEFAULT_DEPENDENCY);
+               script_inf.required_stop  = xstrdup(DEFAULT_DEPENDENCY);
+           }
+#endif /* not SUSE */
+
+           first = (service_t*)0;
+           begin = script_inf.provides;
+           while ((token = strsep(&begin, delimeter)) && *token) {
+               service_t * service;
+
+               if (*token == '$') {
+                   warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
+                   continue;
+               }
+               if (*token == '#') {
+                   warn("script %s provides facility %s with comment sign, skipped!\n", d->d_name, token);
+                   continue;
+               }
+
+               service = current_structure(token, order, runlevel, type);
+
+               if (first)
+                   nickservice(first, service);
+               else
+                   first = service;
+
+               if (!makeprov(service, name))
+                   continue;
+
+               ++service->attr.ref;                    /* May enabled in several levels */
+
+               if (service->attr.flags & SERV_KNOWN)
+                   continue;
+               service->attr.flags |= (SERV_KNOWN|SERV_ENABLED);
+
+               if (!lsb)
+                   service->attr.flags |= SERV_NOTLSB;
+
+               if ((lsb & FOUND_LSB_HEADER) == 0) {
+                   if ((lsb & (FOUND_LSB_DEFAULT|FOUND_LSB_OVERRIDE)) == 0)
+                     warn("warning: script '%s' missing LSB tags and overrides\n", d->d_name);
+                   else
+                       warn("warning: script '%s' missing LSB tags\n", d->d_name);
+               }
+
+               if (script_inf.required_start && script_inf.required_start != empty) {
+                   rememberreq(service, REQ_MUST, script_inf.required_start);
+#ifdef USE_COMPAT_EMPTY
+                   if (!script_inf.required_stop || script_inf.required_stop == empty)
+                       script_inf.required_stop = xstrdup(script_inf.required_start);
+#endif /* USE_COMPAT_EMPTY */
+               }
+               if (script_inf.should_start && script_inf.should_start != empty) {
+                   rememberreq(service, REQ_SHLD, script_inf.should_start);
+#ifdef USE_COMPAT_EMPTY
+                   if (!script_inf.should_stop || script_inf.should_stop == empty)
+                       script_inf.should_stop = xstrdup(script_inf.should_start);
+#endif /* USE_COMPAT_EMPTY */
+               }
+               if (script_inf.start_before && script_inf.start_before != empty) {
+                   reversereq(service, REQ_SHLD, script_inf.start_before);
+#ifdef USE_COMPAT_EMPTY
+                   if (!script_inf.stop_after || script_inf.stop_after == empty)
+                       script_inf.stop_after = xstrdup(script_inf.start_before);
+#endif /* USE_COMPAT_EMPTY */
+               }
+               if (script_inf.required_stop && script_inf.required_stop != empty) {
+                   rememberreq(service, REQ_MUST|REQ_KILL, script_inf.required_stop);
+               }
+               if (script_inf.should_stop && script_inf.should_stop != empty) {
+                   rememberreq(service, REQ_SHLD|REQ_KILL, script_inf.should_stop);
+               }
+               if (script_inf.stop_after && script_inf.stop_after != empty) {
+                   reversereq(service, REQ_SHLD|REQ_KILL, script_inf.stop_after);
+               }
+           }
+
+           if (name) 
+               xreset(name);
+
+           scan_script_reset();
+
+       }       /* while ((token = strsep(&begin, delimeter)) && *token) */
+
+       popd();
+       closedir(rcdir);
+    }
+    popd();
+    return;
+}
+
+/*
+ * The /etc/insserv.conf scanning engine.
+ */
+static void scan_conf_file(const char *restrict file) attribute((nonnull(1)));
+static void scan_conf_file(const char *restrict file)
+{
+    regmatch_t subloc[SUBCONFNUM], *val = (regmatch_t*)0;
+    FILE *conf;
+
+    info("Loading %s\n", file);
+
+    do {
+       const char * fptr = file;
+       if (*fptr == '/')
+           fptr++;
+       /* Try relativ location first */
+       if ((conf = fopen(fptr, "r")))
+           break;
+       /* Try absolute location */
+       if ((conf = fopen(file, "r")))
+           break;
+       goto err;
+    } while (1);
+
+    while (fgets(buf, sizeof(buf), conf)) {
+       char *pbuf = &buf[0];
+       if (*pbuf == '#')
+           continue;
+       if (*pbuf == '\n')
+           continue;
+       if (regexecutor(&creg.isysfaci, buf, SUBCONFNUM, subloc, 0) == true) {
+           char * virt = (char*)0, * real = (char*)0;
+           val = &subloc[SUBCONF - 1];
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               virt = pbuf+val->rm_so;
+           }
+           val = &subloc[SUBCONFNUM - 1];
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               real = pbuf+val->rm_so;
+           }
+           if (virt) {
+               list_t * ptr;
+               boolean found = false;
+               list_for_each(ptr, sysfaci_start) {
+                   if (!strcmp(getfaci(ptr)->name, virt)) {
+                       found = true;
+                       if(real) {
+                           list_t * r_list = &getfaci(ptr)->replace;
+                           char * token;
+                           while ((token = strsep(&real, delimeter))) {
+                               repl_t *restrict subst;
+                               string_t * r;
+                               if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+                                   error("%s", strerror(errno));
+                               insert(&subst->r_list, r_list->prev);
+                               r = &subst->r[0];
+                               if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
+                                   error("%s", strerror(errno));
+                               *r->ref = 1;
+                               r->name = ((char*)(r->ref))+alignof(typeof(r->ref));
+                               strcpy(r->name, token);
+                           }
+                       }
+                       break;
+                   }
+               }
+               if (!found) {
+                   faci_t *restrict this;
+                   if (posix_memalign((void*)&this, sizeof(void*), alignof(faci_t)) != 0)
+                       error("%s", strerror(errno));
+                   else {
+                       list_t * r_list = &this->replace;
+                       char * token;
+                       r_list->next = r_list;
+                       r_list->prev = r_list;
+                       insert(&this->list, sysfaci_start->prev);
+                       this->name = xstrdup(virt);
+                       while ((token = strsep(&real, delimeter))) {
+                           repl_t *restrict subst;
+                           string_t * r;
+                           if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+                               error("%s", strerror(errno));
+                           insert(&subst->r_list, r_list->prev);
+                           r = &subst->r[0];
+                           if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
+                               error("%s", strerror(errno));
+                           *r->ref = 1;
+                           r->name = ((char*)(r->ref))+alignof(typeof(r->ref));
+                           strcpy(r->name, token);
+                       }
+                   }
+               }
+           }
+       }
+       if (regexecutor(&creg.isactive, buf, SUBCONFNUM, subloc, 0) == true) {
+           char * key = (char*)0, * servs = (char*)0;
+           val = &subloc[SUBCONF - 1];
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               key = pbuf+val->rm_so;
+           }
+           val = &subloc[SUBCONFNUM - 1];
+           if (val->rm_so < val->rm_eo) {
+               *(pbuf+val->rm_eo) = '\0';
+               servs = pbuf+val->rm_so;
+           }
+           if (key && *key == '<' && servs && *servs) {
+               if (!strncmp("<interactive>", key, strlen(key))) {
+                   char * token;
+                   while ((token = strsep(&servs, delimeter))) {
+                       service_t *service = addservice(token);
+                       service = getorig(service);
+                       service->attr.flags |= SERV_INTRACT;
+                   }
+               }
+           }
+       }
+    }
+
+    fclose(conf);
+    return;
+err:
+    warn("fopen(%s): %s\n", file, strerror(errno));
+}
+
+static int cfgfile_filter(const struct dirent *restrict d) attribute((nonnull(1)));
+static int cfgfile_filter(const struct dirent *restrict d)
+{
+    boolean ret = false;
+    const char * name = d->d_name;
+    const char * end;
+
+    if (*name == '.')
+       goto out;
+    if (!name || (*name == '\0'))
+       goto out;
+    if ((end = strrchr(name, '.'))) {
+       end++;
+       if (!strncmp(end, "rpm", 3)     || /* .rpmorig, .rpmnew, .rmpsave, ... */
+           !strncmp(end, "ba", 2)      || /* .bak, .backup, ... */
+#ifdef SUSE
+           !strcmp(end,  "local")      || /* .local are sourced by the basename */
+#endif /* not SUSE */
+           !strcmp(end,  "old")        ||
+           !strcmp(end,  "new")        ||
+           !strcmp(end,  "org")        ||
+           !strcmp(end,  "orig")       ||
+           !strncmp(end, "dpkg", 3)    || /* .dpkg-old, .dpkg-new ... */
+           !strcmp(end,  "save")       ||
+           !strcmp(end,  "swp")        || /* Used by vi like editors */
+           !strcmp(end,  "core"))         /* modern core dump */
+       {
+           goto out;
+       }
+    }
+    if ((end = strrchr(name, ','))) {
+       end++;
+       if (!strcmp(end,  "v"))           /* rcs-files */
+           goto out;
+    }
+    ret = true;
+out:
+    return (int)ret;
+}
+
+static void scan_conf(const char *restrict file) attribute((nonnull(1)));
+static void scan_conf(const char *restrict file)
+{
+    struct dirent** namelist = (struct dirent**)0;
+    char path[PATH_MAX+1];
+    int n;
+
+    regcompiler(&creg.isysfaci,  CONFLINE, REG_EXTENDED|REG_ICASE);
+    regcompiler(&creg.isactive, CONFLINE2, REG_EXTENDED|REG_ICASE);
+
+    n = snprintf(&path[0], sizeof(path), "%s%s",   (root && !set_insconf) ? root : "", file);
+    if (n >= (int)sizeof(path) || n < 0)
+       error("snprintf(): %s\n", strerror(errno));
+
+    scan_conf_file(path);
+
+    n = snprintf(&path[0], sizeof(path), "%s%s.d", (root && !set_insconf) ? root : "", file);
+    if (n >= (int)sizeof(path) || n < 0)
+       error("snprintf(): %s\n", strerror(errno));
+
+    n = scandir(path, &namelist, cfgfile_filter, alphasort);
+    if(n > 0) {
+       while(n--) {
+           struct stat st;
+           char buf[PATH_MAX+1];
+           int r;
+
+           r = snprintf(&buf[0], sizeof(buf), "%s/%s", path, namelist[n]->d_name);
+           if (r >= (int)sizeof(buf) || r < 0)
+               error("snprintf(): %s\n", strerror(errno));
+
+           if ((stat(buf, &st) < 0) || !S_ISREG(st.st_mode))
+               continue;
+
+           scan_conf_file(buf);
+
+           free(namelist[n]);
+       }
+    }
+
+    if (namelist)
+       free(namelist);
+
+    regfree(&creg.isysfaci);
+    regfree(&creg.isactive);
+}
+
+static void expand_faci(list_t *restrict rlist, list_t *restrict head,
+                       int *restrict deep) attribute((noinline,nonnull(1,2,3)));
+static void expand_faci(list_t *restrict rlist, list_t *restrict head, int *restrict deep)
+{
+       repl_t * rent = getrepl(rlist);
+       list_t * tmp, * safe, * ptr = (list_t*)0;
+
+       list_for_each(tmp, sysfaci_start) {
+           if (!strcmp(getfaci(tmp)->name, rent->r[0].name)) {
+               ptr = &getfaci(tmp)->replace;
+               break;
+           }
+       }
+
+       if (!ptr || list_empty(ptr)) {
+           delete(rlist);
+           if (--(*rent->r[0].ref) <= 0)
+               free(rent->r[0].ref);
+           free(rent);
+           goto out;
+       }
+
+       if ((*deep)++ > 10) {
+           warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
+           goto out;
+       }
+
+       list_for_each_safe(tmp, safe, ptr) {
+           repl_t * rnxt = getrepl(tmp);
+           if (*rnxt->r[0].name == '$') {
+               expand_faci(tmp, head, deep);
+           } else {
+               if (*deep == 1) {
+                   if (--(*rent->r[0].ref) <= 0)
+                       free(rent->r[0].ref);
+                   rent->r[0] = rnxt->r[0];
+                   ++(*rent->r[0].ref);
+               } else {
+                   repl_t *restrict subst;
+                   if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+                       error("%s", strerror(errno));
+                   insert(&subst->r_list, head);
+                   subst->r[0] = rnxt->r[0];
+                   ++(*subst->r[0].ref);
+               }
+           }
+       }
+out:
+       (*deep)--;
+       return;
+}
+
+static inline void expand_conf(void)
+{
+    list_t *ptr;
+    list_for_each(ptr, sysfaci_start) {
+       list_t * rlist, * safe, * head = &getfaci(ptr)->replace;
+       list_for_each_safe(rlist, safe, head) {
+           if (*getrepl(rlist)->r[0].name == '$') {
+               int deep = 0;
+               expand_faci(rlist, rlist, &deep);
+           }
+       }
+    }
+}
+
+/*
+ * Scan for a Start or Kill script within a runlevel directory.
+ * We start were we leave the directory, the upper level
+ * has to call rewinddir(3) if necessary.
+ */
+static inline char * scan_for(DIR *const restrict rcdir,
+                             const char *const restrict script,
+                             const char type) attribute((always_inline,nonnull(1,2)));
+static inline char * scan_for(DIR *const rcdir,
+                             const char *const script, const char type)
+{
+    struct dirent *d;
+    char * ret = (char*)0;
+
+    while ((d = readdir(rcdir)) != (struct dirent*)0) {
+       char * ptr = d->d_name;
+
+       if (*ptr != type)
+           continue;
+       ptr++;
+
+       if (strspn(ptr, "0123456789") < 2)
+           continue;
+       ptr += 2;
+
+       if (!strcmp(ptr, script)) {
+           ret = d->d_name;
+           break;
+       }
+    }
+    return ret;
+}
+
+#ifdef SUSE
+/*
+ * A simple command line checker of the parent process to determine if this is
+ * a sub process "/bin/sh" forked off for executing a temporary file for %preun,
+ * %postun, %pre, or %post scriptlet.
+ */
+static inline boolean underrpm(void)
+{
+    boolean ret = false;
+    const pid_t pp = getppid();
+    char buf[PATH_MAX], *argv[3], *ptr;
+# if defined(USE_RPMLIB) && (USE_RPMLIB > 0)
+    char *tmppath, *shell;
+# endif /* USE_RPMLIB */
+    int argc, fd;
+    ssize_t len;
+
+    snprintf(buf, sizeof(buf)-1, "/proc/%lu/cmdline", (unsigned long)pp);
+    if ((fd = open(buf, O_NOCTTY|O_RDONLY)) < 0)
+       goto out;
+
+    memset(buf, '\0', sizeof(buf));
+    if ((len = read(fd , buf, sizeof(buf)-1)) < 0)
+       goto out;
+
+    ptr = &buf[0];
+    argc = 0;
+    do {
+       argv[argc++] = ptr;
+       if (argc > 2)
+           break;
+       if ((len = len - (ssize_t)(ptr - &buf[0])) < 0)
+           break;
+    } while ((ptr = memchr(ptr, '\0', len)) && *(++ptr));
+
+    if (argc != 3)
+       goto out;
+
+# if defined(USE_RPMLIB) && (USE_RPMLIB > 0)
+    rpmReadConfigFiles(NULL, NULL);
+    rpmFreeRpmrc();
+
+    if ((shell = rpmExpand("%_buildshell", NULL)) == NULL)
+       shell = xstrdup("/bin/sh");
+
+    if (strncmp(argv[0], shell, strlen(shell)) != 0) {
+       free(shell);
+       goto out;
+    }
+    free(shell);
+
+    if ((tmppath = rpmExpand("%_tmppath", NULL)) == NULL)
+       tmppath = xstrdup("/var/tmp");
+
+    if (strncmp(argv[1], tmppath, strlen(tmppath)) != 0) {
+       free(tmppath);
+       goto out;
+    }
+
+    len = strlen(tmppath);
+    free(tmppath);
+
+    ptr = argv[1];
+    if (strncmp(ptr + len, "/rpm-tmp.", 9) != 0)
+       goto out;
+# else  /* not USE_RPMLIB */
+    if ((strcmp(argv[0], "/bin/sh") != 0) &&
+       (strcmp(argv[0], "/bin/bash") != 0))
+       goto out;
+
+    if ((strncmp(argv[1], "/var/tmp/rpm-tmp.", 17) != 0) &&
+       (strncmp(argv[1], "/usr/tmp/rpm-tmp.", 17) != 0) &&
+       (strncmp(argv[1], "/tmp/rpm-tmp.", 13) != 0))
+       goto out;
+# endif /* not USE_RPMLIB */
+    if ((argc = atoi(argv[2])) >= 0 && argc <= 2)
+       ret = true;
+out:
+    if (fd >= 0)
+       close(fd);
+
+    return ret;
+}
+#endif /* SUSE */
+
+static struct option long_options[] =
+{
+    {"verbose",        0, (int*)0, 'v'},
+    {"config", 1, (int*)0, 'c'},
+    {"dryrun", 0, (int*)0, 'n'},
+    {"default",        0, (int*)0, 'd'},
+    {"remove", 0, (int*)0, 'r'},
+    {"force",  0, (int*)0, 'f'},
+    {"path",   1, (int*)0, 'p'},
+    {"override",1, (int*)0, 'o'},
+    {"help",   0, (int*)0, 'h'},
+    { 0,       0, (int*)0,  0 },
+};
+
+static void help(const char *restrict const name) attribute((nonnull(1)));
+static void help(const char *restrict const  name)
+{
+    printf("Usage: %s [<options>] [init_script|init_directory]\n", name);
+    printf("Available options:\n");
+    printf("  -h, --help       This help.\n");
+    printf("  -r, --remove     Remove the listed scripts from all runlevels.\n");
+    printf("  -f, --force      Ignore if a required service is missed.\n");
+    printf("  -v, --verbose    Provide information on what is being done.\n");
+    printf("  -p <path>, --path <path>  Path to replace " INITDIR ".\n");
+    printf("  -o <path>, --override <path> Path to replace " OVERRIDEDIR ".\n");
+    printf("  -c <config>, --config <config>  Path to config file.\n");
+    printf("  -n, --dryrun     Do not change the system, only talk about it.\n");
+    printf("  -d, --default    Use default runlevels a defined in the scripts\n");
+}
+
+
+/*
+ * Do the job.
+ */
+int main (int argc, char *argv[])
+{
+    DIR * initdir;
+    struct dirent *d;
+    struct stat st_script;
+    extension char * argr[argc];
+    char * path = INITDIR;
+    char * override_path = OVERRIDEDIR;
+    char * insconf = INSCONF;
+    const char *const ipath = path;
+    int runlevel, c, dfd;
+    boolean del = false;
+    boolean defaults = false;
+    boolean ignore = false;
+
+    myname = basename(*argv);
+
+#ifdef SUSE
+    if (underrpm())
+       ignore = true;
+#endif /* SUSE */
+
+    if (getuid() == (uid_t)0)
+       o_flags |= O_NOATIME;
+
+    for (c = 0; c < argc; c++)
+       argr[c] = (char*)0;
+
+    while ((c = getopt_long(argc, argv, "c:dfrhvno:p:", long_options, (int *)0)) != -1) {
+       size_t l;
+       switch (c) {
+           case 'c':
+               if (optarg == (char*)0 || *optarg == '\0')
+                   goto err;
+               insconf = optarg;
+               set_insconf = true;
+               break;
+           case 'd':
+               defaults = true;
+               break;
+           case 'r':
+               del = true;
+               break;
+           case 'f':
+               ignore = true;
+               break;
+           case 'v':
+               verbose = true;
+               break;
+           case 'n':
+               verbose = true;
+               dryrun = true;
+               break;
+           case 'p':
+               if (optarg == (char*)0 || *optarg == '\0')
+                   goto err;
+               if (path != ipath) free(path);
+               l = strlen(optarg) - 1;
+               path = xstrdup(optarg);
+               if (*(path+l) == '/')
+                   *(path+l) = '\0';
+               break;
+           case 'o':
+               if (optarg == (char*)0 || *optarg == '\0')
+                   goto err;
+               override_path = optarg;
+               set_override = true;
+               break;
+           case '?':
+           err:
+               error("For help use: %s -h\n", myname);
+           case 'h':
+               help(myname);
+               exit(0);
+           default:
+               break;
+       }
+    }
+    argv += optind;
+    argc -= optind;
+
+    if (!argc && del)
+       error("usage: %s [[-r] init_script|init_directory]\n", myname);
+
+    if (*argv) {
+       char * token = strpbrk(*argv, delimeter);
+
+       /*
+        * Let us separate the script/service name from the additional arguments.
+        */
+       if (token && *token) {
+           *token = '\0';
+           *argr = ++token;
+       }
+
+       /* Catch `/path/script', `./script', and `path/script' */
+       if (strchr(*argv, '/')) {
+           if (stat(*argv, &st_script) < 0)
+               error("%s: %s\n", *argv, strerror(errno));
+       } else {
+           pushd(path);
+           if (stat(*argv, &st_script) < 0)
+               error("%s: %s\n", *argv, strerror(errno));
+           popd();
+       }
+
+       if (S_ISDIR(st_script.st_mode)) {
+           const size_t l = strlen(*argv) - 1;
+
+           if (path != ipath) free(path);
+           path = xstrdup(*argv);
+           if (*(path+l) == '/')
+               *(path+l) = '\0';
+
+           argv++;
+           argc--;
+           if (argc || del)
+               error("usage: %s [[-r] init_script|init_directory]\n", myname);
+
+       } else {
+           char * base, * ptr = xstrdup(*argv);
+
+           if ((base = strrchr(ptr, '/'))) {
+               if (path != ipath) free(path);
+               *base = '\0';
+               path  = ptr;
+           } else
+               free(ptr);
+       }
+    }
+
+    if (strcmp(path, INITDIR) != 0) {
+       char * tmp;
+       root = xstrdup(path);
+       if ((tmp = strstr(root, INITDIR))) {
+           *tmp = '\0';
+       } else {
+           free(root);
+           root = (char*)0;
+       }
+    }
+
+    c = argc;
+    while (c--) {
+       char * base;
+       char * token = strpbrk(argv[c], delimeter);
+
+       /*
+        * Let us separate the script/service name from the additional arguments.
+        */
+       if (token && *token) {
+           *token = '\0';
+           argr[c] = ++token;
+       }
+
+       if (stat(argv[c], &st_script) < 0) {
+           if (errno != ENOENT)
+               error("%s: %s\n", argv[c], strerror(errno));
+           pushd(path);
+           if (stat(argv[c], &st_script) < 0)
+               error("%s: %s\n", argv[c], strerror(errno));
+           popd();
+       }
+       if ((base = strrchr(argv[c], '/'))) {
+           base++;
+           argv[c] = base;
+       }
+    }
+
+#if defined(DEBUG) && (DEBUG > 0)
+    for (c = 0; c < argc; c++)
+       if (argr[c])
+           printf("Overwrite argument for %s is %s\n", argv[c], argr[c]);
+#endif /* DEBUG */
+
+    /*
+     * Scan and set our configuration for virtual services.
+     */
+    scan_conf(insconf);
+
+    /*
+     * Expand system facilities to real serivces
+     */
+    expand_conf();
+
+    /*
+     * Initialize the regular scanner for the scripts.
+     */
+    scan_script_regalloc();
+
+    /*
+     * Scan always for the runlevel links to see the current
+     * link scheme of the services.
+     */
+    scan_script_locations(path, override_path, ignore);
+
+    /*
+     * Clear out aliases found for scripts found up to this point.
+     */
+    clear_all();
+
+    /*
+     * Open the script directory
+     */
+    if ((initdir = opendir(path)) == (DIR*)0 || (dfd = dirfd(initdir)) < 0)
+       error("can not opendir(%s): %s\n", path, strerror(errno));
+
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+    (void)posix_fadvise(dfd, 0, 0, POSIX_FADV_WILLNEED);
+    (void)posix_fadvise(dfd, 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
+    /*
+     * Now scan for the service scripts and their LSB comments.
+     */
+    pushd(path);
+
+    /*
+     * Scan scripts found in the command line to be able to resolve
+     * all dependcies given within those scripts.
+     */
+    if (argc > 1) for (c = 0; c < argc; c++) {
+       const char *const name = argv[c];
+       service_t * first = (service_t*)0;
+       char * provides, * begin, * token;
+       const uchar lsb = scan_script_defaults(dfd, name, override_path, (char**)0, true, ignore);
+
+       if ((lsb & FOUND_LSB_HEADER) == 0) {
+           if ((lsb & (FOUND_LSB_DEFAULT|FOUND_LSB_OVERRIDE)) == 0)
+               warn("warning: script '%s' missing LSB tags and overrides\n", name);
+           else
+               warn("warning: script '%s' missing LSB tags\n", name);
+       }
+
+       if (!script_inf.provides || script_inf.provides == empty)
+           script_inf.provides = xstrdup(name);
+
+       provides = xstrdup(script_inf.provides);
+       begin = provides;
+       while ((token = strsep(&begin, delimeter)) && *token) {
+           service_t * service;
+
+           if (*token == '$') {
+               warn("script %s provides system facility %s, skipped!\n", name, token);
+               continue;
+           }
+           if (*token == '#') {
+               warn("script %s provides facility %s with comment sign, skipped!\n", name, token);
+               continue;
+           }
+
+           service = addservice(token);
+
+           if (first)
+               nickservice(first, service);
+           else
+               first = service;
+
+           service->attr.flags |= SERV_CMDLINE;
+       }
+       free(provides);
+    }
+
+    /*
+     * Scan now all scripts found in the init.d/ directory
+     */
+    while ((d = readdir(initdir)) != (struct dirent*)0) {
+       const boolean isarg = chkfor(d->d_name, argv, argc);
+       service_t * service = (service_t*)0;
+       char * token;
+       char * begin = (char*)0;        /* hold start pointer of strings handled by strsep() */
+       boolean hard = false;
+       uchar lsb = 0;
+#if defined(DEBUG) && (DEBUG > 0)
+       int nobug = 0;
+#endif
+
+       if (*d->d_name == '.')
+           continue;
+       errno = 0;
+
+       /* d_type seems not to work, therefore use (l)stat(2) */
+       if (xstat(dfd, d->d_name, &st_script) < 0) {
+           warn("can not stat(%s)\n", d->d_name);
+           continue;
+       }
+       if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode))
+       {
+           if (S_ISDIR(st_script.st_mode))
+               continue;
+           if (isarg)
+               warn("script %s is not an executable regular file, skipped!\n", d->d_name);
+           continue;
+       }
+
+       if (!strncmp(d->d_name, "README", strlen("README"))) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       if (!strncmp(d->d_name, "Makefile", strlen("Makefile"))) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       if (!strncmp(d->d_name, "core", strlen("core"))) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       /* Common scripts not used within runlevels */
+       if (!strcmp(d->d_name, "rx")       ||
+           !strncmp(d->d_name, "skeleton", 8) ||
+           !strncmp(d->d_name, "powerfail", 9))
+       {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+#ifdef SUSE
+       if (!strcmp(d->d_name, "boot") || !strcmp(d->d_name, "rc"))
+#else  /* not SUSE */
+       if (!strcmp(d->d_name, "rcS") || !strcmp(d->d_name, "rc"))
+#endif /* not SUSE */
+       {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       if (cfgfile_filter(d) == 0) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       /* left by emacs like editors */
+       if (d->d_name[strlen(d->d_name)-1] == '~') {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       if (strspn(d->d_name, "$.#%_+-\\*[]^:()~")) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
+           continue;
+       }
+
+       /* main scanner for LSB comment in current script */
+       lsb = scan_script_defaults(dfd, d->d_name, override_path, (char**)0, false, ignore);
+
+       if ((lsb & FOUND_LSB_HEADER) == 0) {
+           if ((lsb & (FOUND_LSB_DEFAULT|FOUND_LSB_OVERRIDE)) == 0)
+               warn("warning: script '%s' missing LSB tags and overrides\n", d->d_name);
+           else
+               warn("warning: script '%s' missing LSB tags\n", d->d_name);
+       }
+
+#ifdef SUSE
+       /* Common script ... */
+       if (!strcmp(d->d_name, "halt")) {
+           service_t *serv = addservice("halt");
+           serv = getorig(serv);
+           makeprov(serv,   d->d_name);
+           runlevels(serv, 'S', "0");
+           serv->attr.flags |= (SERV_ALL|SERV_NOSTOP|SERV_INTRACT);
+           continue;
+       }
+
+       /* ... and its link */
+       if (!strcmp(d->d_name, "reboot")) {
+           service_t *serv = addservice("reboot");
+           serv = getorig(serv);
+           makeprov(serv,   d->d_name);
+           runlevels(serv, 'S', "6");
+           serv->attr.flags |= (SERV_ALL|SERV_NOSTOP|SERV_INTRACT);
+           continue;
+       }
+
+       /* Common script for single mode */
+       if (!strcmp(d->d_name, "single")) {
+           service_t *serv = addservice("single");
+           serv = getorig(serv);
+           makeprov(serv,   d->d_name);
+           runlevels(serv, 'S', "1 S");
+           serv->attr.flags |= (SERV_ALL|SERV_NOSTOP|SERV_INTRACT);
+           rememberreq(serv, REQ_SHLD, "kbd");
+           continue;
+       }
+#endif /* SUSE */
+
+#ifndef SUSE
+       if (!lsb) {
+           script_inf.required_start = xstrdup(DEFAULT_DEPENDENCY);
+           script_inf.required_stop = xstrdup(DEFAULT_DEPENDENCY);
+           script_inf.default_start = xstrdup(DEFAULT_START_LVL);
+           script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
+       }
+#endif /* not SUSE */
+
+       /*
+        * Oops, no comment found, guess one
+        */
+       if (!script_inf.provides || script_inf.provides == empty) {
+           service_t * guess;
+           script_inf.provides = xstrdup(d->d_name);
+
+           /*
+            * Use guessed service to find it within the the runlevels
+            * (by using the list from the first scan for script locations).
+            */
+           if ((guess = findservice(script_inf.provides))) {
+               /*
+                * Try to guess required services out from current scheme.
+                * Note, this means that all services are required.
+                */
+               if (!script_inf.required_start || script_inf.required_start == empty) {
+                   list_t * ptr;
+                   list_for_each_prev(ptr, s_start) {
+                       service_t * tmp = getservice(ptr);
+                       tmp = getorig(tmp);
+                       if (!tmp->attr.sorder)
+                           continue;
+                       if (tmp->attr.sorder >= guess->attr.sorder)
+                           continue;
+                       if (tmp->start->lvl & guess->start->lvl) {
+                           script_inf.required_start = xstrdup(tmp->name);
+                           break;
+                       }
+                   }
+               }
+               if (!script_inf.required_stop || script_inf.required_stop == empty) {
+                   list_t * ptr;
+                   list_for_each_prev(ptr, s_start) {
+                       service_t * tmp = getservice(ptr);
+                       tmp = getorig(tmp);
+                       if (!tmp->attr.korder)
+                           continue;
+                       if (tmp->attr.korder <= guess->attr.korder)
+                           continue;
+                       if (tmp->stopp->lvl & guess->stopp->lvl) {
+                           script_inf.required_stop = xstrdup(tmp->name);
+                           break;
+                       }
+                   }
+               }
+               if (!script_inf.default_start || script_inf.default_start == empty) {
+                   if (guess->start->lvl)
+                       script_inf.default_start = lvl2str(guess->start->lvl);
+               }
+               if (!script_inf.default_stop || script_inf.default_stop == empty) {
+                   if (guess->stopp->lvl)
+                       script_inf.default_stop = lvl2str(guess->stopp->lvl);
+               }
+
+           } else {    /* !findservice(&guess, script_inf.provides) */
+
+               list_t * ptr;
+               /*
+                * Find out which levels this service may have out from current scheme.
+                * Note, this means that the first requiring service wins.
+                */
+               list_for_each(ptr, s_start) {
+                   service_t * cur;
+                   list_t * req;
+
+                   if (script_inf.default_start && script_inf.default_start != empty)
+                          break;
+                   cur = getservice(ptr);
+                   cur = getorig(cur);
+
+                   if (list_empty(&cur->sort.req) || !(cur->attr.flags & SERV_ENABLED))
+                       continue;
+
+                   np_list_for_each(req, &cur->sort.req) {
+                       if (!strcmp(getreq(req)->serv->name, script_inf.provides)) {
+                           script_inf.default_start = lvl2str(getservice(ptr)->start->lvl);
+                           break;
+                       }
+                   }
+               }
+               list_for_each(ptr, s_start) {
+                   service_t * cur;
+                   list_t * rev;
+
+                   if (script_inf.default_stop && script_inf.default_stop != empty)
+                          break;
+                   cur = getservice(ptr);
+                   cur = getorig(cur);
+
+                   if (list_empty(&cur->sort.rev) || !(cur->attr.flags & SERV_ENABLED))
+                       continue;
+
+                   np_list_for_each(rev, &cur->sort.rev) {
+                       if (!strcmp(getreq(rev)->serv->name, script_inf.provides)) {
+                           script_inf.default_stop = lvl2str(getservice(ptr)->stopp->lvl);
+                           break;
+                       }
+                   }
+               }
+           }           /* !findservice(&guess, script_inf.provides) */
+       }
+
+       /*
+        * Use guessed service to find it within the the runlevels
+        * (by using the list from the first scan for script locations).
+        */
+       if (!service) {
+           char * provides = xstrdup(script_inf.provides);
+           service_t * first = (service_t*)0;
+
+           begin = provides;
+           while ((token = strsep(&begin, delimeter)) && *token) {
+
+               if (*token == '$') {
+                   warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
+                   continue;
+               }
+               if (*token == '#') {
+                   warn("script %s provides facility %s with comment sign, skipped!\n", d->d_name, token);
+                   continue;
+               }
+
+               service = addservice(token);
+               if (first)
+                   nickservice(first, service);
+               else
+                   first = service;
+
+#if defined(DEBUG) && (DEBUG > 0)
+               nobug++;
+#endif
+               if (!makeprov(service, d->d_name)) {
+
+                   if (!del || (del && !isarg))
+                       warn("script %s: service %s already provided!\n", d->d_name, token);
+
+                   if (!del && !ignore && isarg)
+                       error("exiting now!\n");
+
+                   if (!del || (del && !ignore && !isarg))
+                       continue;
+
+                   /* Provide this service with an other name to be able to delete it */
+                   service = addservice(d->d_name);
+                   service = getorig(service);
+                   service->attr.flags |= SERV_ALREADY;
+                   (void)makeprov(service, d->d_name);
+
+                   continue;
+               }
+
+               if (service) {
+                   boolean known = (service->attr.flags & SERV_KNOWN);
+                   service->attr.flags |= SERV_KNOWN;
+
+                   if (!known) {
+                       if (script_inf.required_start && script_inf.required_start != empty) {
+                           rememberreq(service, REQ_MUST, script_inf.required_start);
+#ifdef USE_COMPAT_EMPTY
+                           if (!script_inf.required_stop || script_inf.required_stop == empty)
+                               script_inf.required_stop = xstrdup(script_inf.required_start);
+#endif /* USE_COMPAT_EMPTY */
+                       }
+                       if (script_inf.should_start && script_inf.should_start != empty) {
+                           rememberreq(service, REQ_SHLD, script_inf.should_start);
+#ifdef USE_COMPAT_EMPTY
+                           if (!script_inf.should_stop || script_inf.should_stop == empty)
+                               script_inf.should_stop = xstrdup(script_inf.should_start);
+#endif /* USE_COMPAT_EMPTY */
+                       }
+                       if (script_inf.required_stop && script_inf.required_stop != empty) {
+                           rememberreq(service, REQ_MUST|REQ_KILL, script_inf.required_stop);
+                       }
+                       if (script_inf.should_stop && script_inf.should_stop != empty) {
+                           rememberreq(service, REQ_SHLD|REQ_KILL, script_inf.should_stop);
+                       }
+                   }
+
+                   if (script_inf.start_before && script_inf.start_before != empty) {
+                       reversereq(service, REQ_SHLD, script_inf.start_before);
+#ifdef USE_COMPAT_EMPTY
+                       if (!script_inf.stop_after || script_inf.stop_after == empty)
+                           script_inf.stop_after = xstrdup(script_inf.start_before);
+#endif /* USE_COMPAT_EMPTY */
+                   }
+                   if (script_inf.stop_after && script_inf.stop_after != empty) {
+                       reversereq(service, REQ_SHLD|REQ_KILL, script_inf.stop_after);
+                   }
+                   /*
+                    * Use information from symbolic link structure to
+                    * check if all services are around for this script.
+                    */
+                   if (isarg && !ignore) {
+                       boolean ok = true;
+                       if (del)
+                           ok = chkdependencies(service);
+                       else
+                           ok = chkrequired(service);
+                       if (!ok && !ignore)
+                           error("exiting now!\n");
+                   }
+
+                   if (script_inf.default_start && script_inf.default_start != empty) {
+                       ushort deflvls = str2lvl(script_inf.default_start);
+
+                       if (service->attr.flags & SERV_ENABLED) {
+                           /*
+                            * Currently linked into service runlevel scheme, check
+                            * if the defaults are overwriten. Compare all bits,
+                            * which means `==' and not `&' and overwrite the defaults
+                            * of the current script.
+                            */
+                           if (!defaults && (deflvls != service->start->lvl)) {
+                               if (!del && isarg && !(argr[curr_argc]))
+                                   warn("warning: current start runlevel(s) (%s) of script `%s' overwrites defaults (%s).\n",
+                                        service->start->lvl ? lvl2str(service->start->lvl) : "empty", d->d_name, lvl2str(deflvls));
+                           }
+                       } else
+                           /*
+                            * Currently not linked into service runlevel scheme, info
+                            * needed for enabling interactive services at first time.
+                            */
+                           service->start->lvl = deflvls;
+
+                   } else if (script_inf.default_start == empty) {
+                       if (service->attr.flags & SERV_ENABLED) {
+                           /*
+                            * Currently linked into service runlevel scheme, check
+                            * if the defaults are overwriten. Compare all bits,
+                            * which means `==' and not `&' and overwrite the defaults
+                            * of the current script.
+                            */
+                           if (!defaults && service->start->lvl != 0) {
+                               warn("warning: current start runlevel(s) (%s) of script `%s' overwrites defaults (empty).\n",
+                                    lvl2str(service->start->lvl), d->d_name);
+                               script_inf.default_start = lvl2str(service->start->lvl);
+                           }
+                       }
+                   } else if (!script_inf.default_start && (service->attr.flags & SERV_NOTLSB)) {
+#ifdef SUSE
+                       /*
+                        * Could be a none LSB script, use info from current link scheme.
+                        * If not found use default.
+                        */
+                       if (service->attr.flags & SERV_ENABLED)
+                           script_inf.default_start = lvl2str(service->start->lvl);
+                       else
+                           script_inf.default_start = xstrdup(DEFAULT_START_LVL);
+#endif /* SUSE */
+                   }
+#ifdef SUSE
+                   /*
+                    * This because SuSE boot script concept uses a differential link scheme.
+                    * Therefore default_stop is ignored and overwriten by default_start.
+                    */
+                   xreset(script_inf.default_stop);
+                   if (script_inf.default_start && script_inf.default_start != empty)
+                       script_inf.default_stop = xstrdup(script_inf.default_start);
+                   else
+                       script_inf.default_stop = empty;
+                   oneway(script_inf.default_stop);
+#endif /* SUSE */
+                   if (script_inf.default_stop && script_inf.default_stop != empty) {
+                       ushort deflvlk = str2lvl(script_inf.default_stop);
+
+                       /*
+                        * Compare all bits, which means `==' and not `&' and overwrite
+                        * the defaults of the current script.
+                        */
+                       if (service->attr.flags & SERV_ENABLED) {
+                           /*
+                            * Currently linked into service runlevel scheme, check
+                            * if the defaults are overwriten.
+                            */
+                           if (!defaults && (deflvlk != service->stopp->lvl)) {
+                               if (!del && isarg && !(argr[curr_argc]))
+                                   warn("warning: current stop runlevel(s) (%s) of script `%s' overwrites defaults (%s).\n",
+                                        service->stopp->lvl ? lvl2str(service->stopp->lvl) : "empty", d->d_name, lvl2str(deflvlk));
+                           }
+                       } else
+                           /*
+                            * Currently not linked into service runlevel scheme, info
+                            * needed for enabling interactive services at first time.
+                            */
+                           service->stopp->lvl = deflvlk;
+
+                   } else if (script_inf.default_stop == empty) {
+                       if (service->attr.flags & SERV_ENABLED) {
+                           /*
+                            * Currently linked into service runlevel scheme, check
+                            * if the defaults are overwriten. Compare all bits,
+                            * which means `==' and not `&' and overwrite the defaults
+                            * of the current script.
+                            */
+                           if (!defaults && service->stopp->lvl != 0) {
+                               warn("warning: current stop runlevel(s) (%s) of script `%s' overwrites defaults (empty).\n",
+                                    lvl2str(service->stopp->lvl), d->d_name);
+                               script_inf.default_stop = lvl2str(service->stopp->lvl);
+                           }
+                       }
+                   } else if (!script_inf.default_stop && (service->attr.flags & SERV_NOTLSB)) {
+#ifdef SUSE
+                       /*
+                        * Could be a none LSB script, use info from current link scheme.
+                        * If not found use default.
+                        */
+                       if (service->attr.flags & SERV_ENABLED)
+                           script_inf.default_stop = lvl2str(service->stopp->lvl);
+                       else
+                           script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
+#endif /* SUSE */
+                   }
+               }
+           }
+           free(provides);
+       }
+
+#ifdef SUSE
+       /* Ahh ... set default multiuser with network */
+       if (!script_inf.default_start || script_inf.default_start == empty) {
+           if (!script_inf.default_start)
+               warn("Default-Start undefined, assuming default start runlevel(s) for script `%s'\n", d->d_name);
+           script_inf.default_start = xstrdup(DEFAULT_START_LVL);
+           xreset(script_inf.default_stop);
+           script_inf.default_stop = xstrdup(script_inf.default_start);
+           oneway(script_inf.default_stop);
+       }
+#else  /* not SUSE */
+       if (!script_inf.default_start) {
+           warn("Default-Start undefined, assuming empty start runlevel(s) for script `%s'\n", d->d_name);
+           script_inf.default_start = empty;
+       }
+#endif /* not SUSE */
+
+#ifdef SUSE
+       if (!script_inf.default_stop || script_inf.default_stop == empty) {
+           if (script_inf.default_start && script_inf.default_start != empty)
+               script_inf.default_stop = xstrdup(script_inf.default_start);
+           else
+               script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
+           oneway(script_inf.default_stop);
+       }
+#else  /* not SUSE */
+       if (!script_inf.default_stop) {
+           warn("Default-Stop  undefined, assuming empty stop  runlevel(s) for script `%s'\n", d->d_name);
+           script_inf.default_stop = empty;
+       }
+#endif /* not SUSE */
+
+       if (isarg && !defaults && !del) {
+           if (argr[curr_argc]) {
+               char * ptr = argr[curr_argc];
+               struct _mark {
+                   const char * wrd;
+                   char * order;
+                   char ** str;
+               } mark[] = {
+                   {"start=",    (char*)0, &script_inf.default_start},
+                   {"stop=",     (char*)0, &script_inf.default_stop },
+#if 0
+                   {"reqstart=", (char*)0, &script_inf.required_start},
+                   {"reqstop=",  (char*)0, &script_inf.required_stop },
+#endif
+                   {(char*)0,    (char*)0, (char**)0}
+               };
+
+               for (c = 0; mark[c].wrd; c++) {
+                   char * order = strstr(ptr, mark[c].wrd);
+                   if (order)
+                       mark[c].order = order;
+               }
+
+               for (c = 0; mark[c].wrd; c++)
+                   if (mark[c].order) {
+                       *(mark[c].order) = '\0';
+                       mark[c].order += strlen(mark[c].wrd);
+                   }
+
+               for (c = 0; mark[c].wrd; c++)
+                   if (mark[c].order) {
+                       size_t len = strlen(mark[c].order);
+                       if (len > 0) {
+                           char * ptr = mark[c].order + len - 1;
+                           if (*ptr == ',') *ptr = '\0';
+                       }
+                       xreset(*(mark[c].str));
+                       *(mark[c].str) = xstrdup(mark[c].order);
+                   }
+               hard = true;
+#ifdef SUSE
+               /*
+                * This because SuSE boot script concept uses a differential link scheme.
+                * Therefore default_stop is ignored and overwriten by default_start.
+                */
+               if (strcmp(script_inf.default_stop, script_inf.default_start) != 0) {
+                   xreset(script_inf.default_stop);
+                   script_inf.default_stop = xstrdup(script_inf.default_start);
+                   oneway(script_inf.default_stop);
+               }
+#endif /* SUSE */
+           }
+       }
+
+#if defined(DEBUG) && (DEBUG > 0)
+       if (!nobug) {
+           fprintf(stderr, "internal BUG at line %d with script %s\n", __LINE__, d->d_name);
+           exit(1);
+       }
+#endif
+
+       begin = script_inf.provides;
+       while ((token = strsep(&script_inf.provides, delimeter)) && *token) {
+           if (*token == '$')
+               continue;
+           if (*token == '#')
+               continue;
+           if (!service)
+               service = addservice(token);
+           service = getorig(service);
+
+           if ((service->attr.flags & SERV_ENABLED) && !hard) {
+               if (del)
+                   continue;
+               if (!defaults)
+                   continue;
+           }
+
+           if (script_inf.default_start && script_inf.default_start != empty)
+               runlevels(service, 'S', script_inf.default_start);
+           if (script_inf.default_stop && script_inf.default_stop != empty)
+               runlevels(service, 'K', script_inf.default_stop);
+       }
+       script_inf.provides = begin;
+
+       /* Remember if not LSB conform script */
+       if (!lsb && service) {
+           service = getorig(service);
+           service->attr.flags |= SERV_NOTLSB;
+       }
+    }
+    /* Reset remaining pointers */
+    scan_script_reset();
+
+    /*
+     * Free the regular scanner for the scripts.
+     */
+    scan_script_regfree();
+
+    /* back */
+    popd();
+    closedir(initdir);
+
+    /*
+     * Clear out aliases found for all scripts.
+     */
+    clear_all();
+
+    /*
+     * Set virtual dependencies for already enabled none LSB scripts.
+     */
+    nonlsb_script();
+
+    /*
+     * Now generate for all scripts the dependencies
+     */
+    follow_all();
+    if (is_loop_detected() && !ignore)
+       error("exiting without changing boot order!\n");
+
+    /*
+     * Be sure that interactive scripts are the only member of
+     * a start group (for parallel start only).
+     */
+    active_script();
+
+    /*
+     * Move the `$all' scripts to the end of all
+     */
+    all_script();
+
+    /*
+     * Sorry but we support only [KS][0-9][0-9]<name>
+     */
+    if (maxstart > MAX_DEEP || maxstop > MAX_DEEP)
+       error("Maximum of %u in ordering reached\n", MAX_DEEP);
+
+#if defined(DEBUG) && (DEBUG > 0)
+    printf("Maxorder %d/%d\n", maxstart, maxstop);
+    show_all();
+#else
+# ifdef SUSE   /* SuSE's SystemV link scheme */
+    pushd(path);
+    for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
+       const ushort lvl = map_runlevel_to_lvl(runlevel);
+       char nlink[PATH_MAX+1], olink[PATH_MAX+1];
+       const char * rcd = (char*)0;
+       const char * script;
+       service_t *serv;
+       DIR  * rcdir;
+
+       if ((rcd = map_runlevel_to_location(runlevel)) == (char*)0)
+           continue;
+
+       rcdir = openrcdir(rcd);         /* Creates runlevel directory if necessary */
+       if (rcdir == (DIR*)0)
+           break;
+       if ((dfd = dirfd(rcdir)) < 0) {
+           closedir(rcdir);
+           break;
+       }
+       pushd(rcd);
+
+       /*
+        * See if we found scripts which should not be
+        * included within this runlevel directory.
+        */
+       while ((d = readdir(rcdir)) != (struct dirent*)0) {
+           const char * ptr = d->d_name;
+           char type;
+
+           if (*ptr != 'S' && *ptr != 'K')
+               continue;
+           type = *ptr;
+           ptr++;
+
+           if (strspn(ptr, "0123456789") != 2)
+               continue;
+           ptr += 2;
+
+           if (xstat(dfd, d->d_name, &st_script) < 0)
+               xremove(dfd, d->d_name);        /* dangling sym link */
+
+           if (notincluded(ptr, type, runlevel)) {
+               serv = findservice(getprovides(ptr));
+               if (defaults) {
+                   xremove(dfd, d->d_name);
+                   if (serv && --serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+               } else if (lvl & LVL_ONEWAY) {
+                   xremove(dfd, d->d_name);
+                   if (serv && --serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+               } else if (del && ignore) {
+                   if (serv && (serv->attr.flags & SERV_ALREADY)) {
+                       xremove(dfd, d->d_name);
+                       if (--serv->attr.ref <= 0)
+                           serv->attr.flags &= ~SERV_ENABLED;
+                   }
+               }
+           }
+       }
+
+       /*
+        * Seek for scripts which are included, link or
+        * correct order number if necessary.
+        */
+
+       script = (char*)0;
+       while ((serv = listscripts(&script, 'X', lvl))) {
+           const boolean this = chkfor(script, argv, argc);
+           boolean found, slink;
+           char * clink;
+
+           if (*script == '$')         /* Do not link in virtual dependencies */
+               continue;
+
+           slink = false;
+           if ((serv->start->lvl & lvl) == 0)
+               goto stop;
+
+           sprintf(olink, "../%s",   script);
+           sprintf(nlink, "S%.2d%s", serv->attr.sorder, script);
+
+           found = false;
+           rewinddir(rcdir);
+           while ((clink = scan_for(rcdir, script, 'S'))) {
+               found = true;
+               if (strcmp(clink, nlink)) {
+                   xremove(dfd, clink);                /* Wrong order, remove link */
+                   if (--serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+                   if (!this) {
+                       xsymlink(dfd, olink, nlink);    /* Not ours, but correct order */
+                       if (++serv->attr.ref)
+                           serv->attr.flags |= SERV_ENABLED;
+                   }
+                   if (this && !del) {
+                       xsymlink(dfd, olink, nlink);    /* Restore, with correct order */
+                       if (++serv->attr.ref)
+                           serv->attr.flags |= SERV_ENABLED;
+                   }
+               } else {
+                   if (del && this) {
+                       xremove(dfd, clink);            /* Found it, remove link */
+                       if (--serv->attr.ref <= 0)
+                           serv->attr.flags &= ~SERV_ENABLED;
+                   }
+               }
+           }
+
+           if (this) {
+               /*
+                * If we haven't found it and we shouldn't delete it
+                * we try to add it.
+                */
+               if (!del && !found) {
+                   xsymlink(dfd, olink, nlink);
+                   if (++serv->attr.ref)
+                       serv->attr.flags |= SERV_ENABLED;
+                   found = true;
+               }
+           }
+
+           /* Start links done, now do Kill links */
+
+           slink = found;
+       stop:
+           if ((serv->stopp->lvl & lvl) == 0)
+               continue;
+
+           sprintf(olink, "../%s",   script);
+           sprintf(nlink, "K%.2d%s", serv->attr.korder, script);
+
+           found = false;
+           rewinddir(rcdir);
+           while ((clink = scan_for(rcdir, script, 'K'))) {
+               found = true;
+               if (strcmp(clink, nlink)) {
+                   xremove(dfd, clink);                /* Wrong order, remove link */
+                   if (--serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+                   if (!this) {
+                       xsymlink(dfd, olink, nlink);    /* Not ours, but correct order */
+                       if (++serv->attr.ref)
+                           serv->attr.flags |= SERV_ENABLED;
+                   }
+                   if (this && !del) {
+                       xsymlink(dfd, olink, nlink);    /* Restore, with correct order */
+                       if (++serv->attr.ref)
+                           serv->attr.flags |= SERV_ENABLED;
+                   }
+               } else {
+                   if (del && this) {
+                       xremove(dfd, clink);            /* Found it, remove link */
+                       if (--serv->attr.ref <= 0)
+                           serv->attr.flags &= ~SERV_ENABLED;
+                   }
+               }
+           }
+
+           if (this && slink) {
+               /*
+                * If we haven't found it and we shouldn't delete it
+                * we try to add it.
+                */
+               if (!del && !found) {
+                   xsymlink(dfd, olink, nlink);
+                   if (++serv->attr.ref)
+                       serv->attr.flags |= SERV_ENABLED;
+               }
+           }
+       }
+       popd();
+       closedir(rcdir);
+    }
+# else  /* not SUSE but Debian SystemV link scheme */
+   /*
+    * Remark: At SuSE we use boot scripts for system initialization which
+    * will be executed by /etc/init.d/boot (which is equal to rc.sysinit).
+    * At system reboot or system halt the stop links of those boot scripts
+    * will be executed by /etc/init.d/halt.  Don't know how todo this for
+    * a traditional standard SystemV link scheme.  Maybe for such an
+    * approach a new directory halt.d/ whould be an idea.
+    */
+    pushd(path);
+    for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
+       char nlink[PATH_MAX+1], olink[PATH_MAX+1];
+       const char * rcd = (char*)0;
+       const char * script;
+       service_t * serv;
+       ushort lvl, seek;
+       DIR  * rcdir;
+
+       if ((rcd = map_runlevel_to_location(runlevel)) == (char*)0)
+           continue;
+       lvl  = map_runlevel_to_lvl(runlevel);
+       seek = map_runlevel_to_seek(runlevel);
+
+       rcdir = openrcdir(rcd);         /* Creates runlevel directory if necessary */
+       if (rcdir == (DIR*)0)
+           break;
+       if ((dfd = dirfd(rcdir)) < 0) {
+           closedir(rcdir);
+           break;
+       }
+       pushd(rcd);
+
+       /*
+        * See if we found scripts which should not be
+        * included within this runlevel directory.
+        */
+       while ((d = readdir(rcdir)) != (struct dirent*)0) {
+           const char * ptr = d->d_name;
+           char type;
+
+           if (*ptr != 'S' && *ptr != 'K')
+               continue;
+           type = *ptr;
+           ptr++;
+
+           if (strspn(ptr, "0123456789") != 2)
+               continue;
+           ptr += 2;
+
+           if (xstat(dfd, d->d_name, &st_script) < 0)
+               xremove(dfd, d->d_name);        /* dangling sym link */
+
+           if (notincluded(ptr, type, runlevel)) {
+               serv = findservice(getprovides(ptr));
+               if (defaults) {
+                   xremove(dfd, d->d_name);
+                   if (serv && --serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+#  ifndef USE_KILL_IN_BOOT
+               } else if (lvl & LVL_BOOT) {
+                   xremove(dfd, d->d_name);
+                   if (serv && --serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+#  endif /* USE_KILL_IN_BOOT */
+               } else if (del && ignore) {
+                   if (serv && (serv->attr.flags & SERV_ALREADY))
+                       xremove(dfd, d->d_name);
+                       if (--serv->attr.ref <= 0)
+                           serv->attr.flags &= ~SERV_ENABLED;
+               }
+           }
+       }
+
+       script = (char*)0;
+       while ((serv = listscripts(&script, 'X', seek))) {
+           const boolean this = chkfor(script, argv, argc);
+           boolean found;
+           char * clink;
+           char mode;
+
+           if (*script == '$')         /* Do not link in virtual dependencies */
+               continue;
+
+           sprintf(olink, "../init.d/%s", script);
+           if (serv->stopp->lvl & lvl) {
+#  ifndef USE_KILL_IN_BOOT
+               if (lvl & LVL_BOOT)                     /* No kill links in rcS.d */
+                       continue;
+#  endif /* USE_KILL_IN_BOOT */
+               sprintf(nlink, "K%.2d%s", serv->attr.korder, script);
+               mode = 'K';
+           } else if (serv->start->lvl & lvl) {
+               sprintf(nlink, "S%.2d%s", serv->attr.sorder, script);
+               mode = 'S';
+           } else
+               continue;               /* We aren't suppose to be on this runlevel */
+
+           found = false;
+
+           rewinddir(rcdir);
+           while ((clink = scan_for(rcdir, script, mode))) {
+               found = true;
+               if (strcmp(clink, nlink)) {
+                   xremove(dfd, clink);                /* Wrong order, remove link */
+                   if (--serv->attr.ref <= 0)
+                       serv->attr.flags &= ~SERV_ENABLED;
+                   if (!this) {
+                       xsymlink(dfd, olink, nlink);    /* Not ours, but correct order */
+                       if (++serv->attr.ref)
+                           serv->attr.flags |= SERV_ENABLED;
+                   }
+                   if (this && !del) {
+                       xsymlink(dfd, olink, nlink);    /* Restore, with correct order */
+                       if (++serv->attr.ref)
+                           serv->attr.flags |= SERV_ENABLED;
+                   }
+               } else {
+                   if (del && this) {
+                       xremove(dfd, clink);            /* Found it, remove link */
+                       if (--serv->attr.ref <= 0)
+                           serv->attr.flags &= ~SERV_ENABLED;
+                   }
+               }
+           }
+
+           if (this) {
+               /*
+                * If we haven't found it and we shouldn't delete it
+                * we try to add it.
+                */
+               if (!del && !found) {
+                   xsymlink(dfd, olink, nlink);
+                   if (++serv->attr.ref)
+                       serv->attr.flags |= SERV_ENABLED;
+                   found = true;
+               }
+           }
+       }
+
+       popd();
+       closedir(rcdir);
+    }
+# endif /* !SUSE, standard SystemV link scheme */
+#endif  /* !DEBUG */
+
+    /*
+     * Do the makedep
+     */
+    makedep();
+
+    /*
+     * Back to the root(s)
+     */
+    popd();
+
+    /*
+     * Make valgrind happy
+     */
+    if (path != ipath) free(path);
+    if (root) free(root);
+
+    return 0;
+}
diff --git a/insserv.conf b/insserv.conf
new file mode 100644 (file)
index 0000000..2efcc60
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# All local filesystems are mounted (done during boot phase)
+#
+$local_fs      boot.localfs
+
+#
+# Low level networking (ethernet card)
+#
+$network       network +pcmcia +hotplug
+
+#
+# Named is operational
+#
+$named         +named +dnsmasq +lwresd $network
+
+#
+# All remote filesystems are mounted (note in some cases /usr may
+# be remote. Most applications that care will probably require
+# both $local_fs and $remote_fs)
+#
+$remote_fs     $local_fs +nfs
+
+#
+# System logger is operational
+#
+$syslog                syslog
+
+#
+# SunRPC portmapper available
+#
+$portmap       portmap
+
+#
+# The system time has been set correctly
+#
+$time          boot.clock +xntpd
+
+#
+# Services which need to be interactive
+#
+<interactive>   boot.crypto boot.localfs boot.rootfsck apache apache2 kdump
diff --git a/install_initd b/install_initd
new file mode 100755 (executable)
index 0000000..49703c0
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /sbin/insserv ${1+"$@"}
diff --git a/listing.c b/listing.c
new file mode 100644 (file)
index 0000000..6451e0e
--- /dev/null
+++ b/listing.c
@@ -0,0 +1,1163 @@
+/*
+ * listing.c
+ *
+ * Copyright 2000-2008 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
+ *                                 2003 SuSE Linux AG, Germany.
+ *                            2007-2008 SuSE Linux Products GmbH Nuernberg, Germany
+ *
+ * This source is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include "listing.h"
+
+int maxstart = 0;              /* Maximum start order of runlevels 0 upto 6 and S */
+int maxstop  = 0;              /* Maximum stop  order of runlevels 0 upto 6 and S */
+static int *maxorder;          /* Pointer to one of above */
+
+/* See listing.c for list_t and list_entry() macro */
+#define getdir(list)           list_entry((list), dir_t,   d_list)
+#define getlink(list)          list_entry((list), link_t,  l_list)
+#define getnextlink(list)      (list_empty(list) ? (dir_t*)0 : getlink((list)->next)->target)
+
+/*
+ * We handle services (aka scripts) as directories because
+ * dependencies can be handels as symbolic links therein.
+ * A provided service will be linked into a required service.
+ * For the general type of linked lists see listing.h.
+ */
+
+typedef struct dir_struct dir_t;
+
+typedef struct link_struct {
+    list_t               l_list;       /* The linked list of symbolic links */
+    dir_t      *restrict target;
+} __align link_t;                      /* This is a "symbolic link" */
+
+typedef struct handle_struct {
+    list_t                 link;       /* The linked list of symbolic start/stop links in the directory */
+    level_t                 run;
+    ushort                flags;
+    uchar               mindeep;       /* Default start/stop deep if any */
+    uchar                  deep;       /* Current start/stop deep */
+    char                 * name;
+} __align handle_t;
+
+struct dir_struct {
+    list_t               d_list;       /* The peg into linked list to other directories */
+    handle_t              start;
+    handle_t              stopp;
+    service_t    *restrict serv;
+    int                             ref;
+    char               * script;
+    char                 * name;
+} __align;                             /* This is a "directory" */
+
+#define attof(dir)     (&(dir)->serv->attr)
+
+/*
+ * The linked list off all directories, note that the s_list
+ * entry within the dir_struct is used as the peg pointer.
+ */
+static list_t dirs = { &dirs, &dirs };
+static list_t * d_start = &dirs;
+
+#define DIR_SCAN       0x0001
+#define DIR_LOOP       0x0002
+#define DIR_LOOPREPORT 0x0004
+#define DIR_MAXDEEP    0x0008
+
+/*
+ * The linked list off all services, note that the d_list
+ * entry within the service_struct is used as the peg pointer.
+ */
+static list_t servs = { &servs, &servs };
+list_t * s_start = &servs;
+
+/*
+ * Provide or find a service dir, set initial states and
+ * link it into the maintaining if a new one.
+ */
+
+static inline dir_t * providedir(const char *restrict const name) attribute((malloc,always_inline,nonnull(1)));
+static inline dir_t * providedir(const char *restrict const name)
+{
+    dir_t *restrict dir = (dir_t*)0;
+    service_t *restrict serv;
+    list_t * ptr;
+
+    list_for_each_prev(ptr, d_start) {
+       dir = getdir(ptr);
+       if (!strcmp(dir->name, name))
+           goto out;
+    }
+
+    if (posix_memalign((void*)&serv, sizeof(void*), alignof(service_t)+strsize(name)) != 0)
+       error("%s", strerror(errno));
+
+    memset(serv, 0, alignof(service_t)+strsize(name));
+    insert(&serv->s_list, s_start->prev);
+    serv->name = ((char*)serv)+alignof(service_t);
+
+    if (posix_memalign((void*)&dir, sizeof(void*), alignof(dir_t)) != 0)
+       error("%s", strerror(errno));
+
+    memset(dir, 0, alignof(dir_t));
+    insert(&dir->d_list, d_start->prev);
+    dir->ref = 1;
+
+    serv->dir = (void*)dir;
+    dir->serv = serv;
+
+    initial(&dir->start.link);
+    initial(&dir->stopp.link);
+
+    initial(&serv->sort.req);
+    initial(&serv->sort.rev);
+
+    strcpy(serv->name, name);
+    dir->name      = serv->name;
+    dir->start.name = serv->name;
+    dir->stopp.name = serv->name;
+
+    dir->start.mindeep = 1;
+    dir->stopp.mindeep = 1;
+
+    serv->start = &dir->start.run;
+    serv->stopp = &dir->stopp.run;
+out:
+    return dir;
+}
+
+/*
+ * Find or add and initialize a service
+ */
+service_t * addservice(const char *restrict const serv) attribute((malloc,nonnull(1)));
+service_t * addservice(const char *restrict const serv)
+{
+    service_t * this;
+    list_t * ptr;
+    dir_t * dir;
+
+    list_for_each_prev(ptr, s_start) {
+       this = getservice(ptr);
+       if (!strcmp(this->name, serv))
+           goto out;
+    }
+    dir = providedir(serv);
+    this = dir->serv;
+out:
+    return this;
+}
+
+/*
+ * Always return the address of the original service
+ */
+service_t * getorig(service_t *restrict const serv)
+{
+    dir_t *const dir = (dir_t *)serv->dir;
+    return dir->serv;
+}
+
+/*
+ * Find a service dir by its script name.
+ */
+static inline dir_t * findscript(const char *restrict const script) attribute((always_inline,nonnull(1)));
+static inline dir_t * findscript(const char *restrict const script)
+{
+    dir_t  * ret = (dir_t*)0;
+    list_t * ptr;
+
+    list_for_each_prev(ptr, d_start) {
+       dir_t * dir = getdir(ptr);
+
+       if (!dir->script)
+           continue;
+
+       if (!strcmp(dir->script, script)) {
+           ret = dir;
+           break;
+       }
+    }
+
+    return ret;
+}
+
+/*
+ * Link the current service into the required service.
+ * If the services do not exist, they will be created.
+ */
+static void ln_sf(dir_t *restrict cur, dir_t *restrict req, const char mode) attribute((nonnull(1,2)));
+static void ln_sf(dir_t *restrict cur, dir_t *restrict req, const char mode)
+{
+    list_t * dent, * l_list = (mode == 'K') ? &req->stopp.link : &req->start.link;
+    link_t *restrict this;
+
+    if (cur == req)
+       goto out;
+
+    list_for_each_prev(dent, l_list) {
+       dir_t * target = getlink(dent)->target;
+       if (!strcmp(target->name, cur->name))
+           goto out;
+    }
+
+    if (posix_memalign((void*)&this, sizeof(void*), alignof(link_t)) == 0) {
+       insert(&this->l_list, l_list->prev);
+       this->target = cur;
+       ++cur->ref;
+       goto out;
+    }
+    error("%s", strerror(errno));
+out:
+    return;
+}
+
+/*
+ * Remember loops to warn only once
+ */
+static inline boolean remembernode (handle_t *restrict const peg) attribute((always_inline,nonnull(1)));
+static inline boolean remembernode (handle_t *restrict const peg)
+{
+    register boolean ret = true;
+
+    if (peg->flags & DIR_LOOP)
+       goto out;
+
+    ret = false;
+    peg->flags |= DIR_LOOP;
+out:
+    return ret;
+}
+
+/*
+ * Recursively called function to follow all
+ * links within a service dir.
+ * Just like a `find * -follow' within a directory tree
+ * of depth one with cross linked dependencies.
+ *
+ * Be warned: the direction is naturally reversed.  That
+ * means that the most requested services have the lowest
+ * order.  In other word, an empty link list of a service
+ * indicates that this service has a higher order number.
+ */
+#if defined(DEBUG) && (DEBUG > 0)
+# define loop_warn_two(a,b,o)  \
+       warn("There is a loop between service %s and %s if %s (list:%d)\n", \
+       (a)->name, (b)->name, o, __LINE__)
+# define loop_warn_one(a,o)    \
+       warn("There is a loop at service %s if %s (list:%d)\n", \
+       (a)->name, o, __LINE__)
+#else
+# define loop_warn_two(a,b,o)  \
+       warn("There is a loop between service %s and %s if %s\n", (a)->name, (b)->name, o)
+# define loop_warn_one(a,o)    \
+       warn("There is a loop at service %s if %s\n", (a)->name, o)
+#endif
+#define loop_check(a)  \
+       ((a) && (a)->flags & DIR_LOOP)
+
+static void __follow (dir_t *restrict dir, dir_t *restrict skip, const int, const char, const char)
+#if  __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+       attribute((noinline,flatten,nonnull(1)));
+#else
+       attribute((noinline,nonnull(1)));
+#endif
+static void __follow (dir_t *restrict dir, dir_t *restrict skip, const int level, const char mode, const char reportloop)
+{
+    list_t * l_list;
+    dir_t * tmp;
+    register int deep = level; /* Link depth, maybe we're called recursively */
+    register int loop = 0;     /* Count number of links in symbolic list */
+    handle_t * peg, * pskp = (handle_t*)0;
+    const char * act;
+
+    if (mode == 'K') {
+       peg = &dir->stopp;
+       if (skip) pskp = &skip->stopp;
+       act  = "stopped";
+    } else {
+       peg = &dir->start;
+       if (skip) pskp = &skip->start;
+       act  = "started";
+    }
+    l_list = &peg->link;
+    prefetch(l_list->next);
+
+    if (peg->flags & DIR_SCAN) {
+       if (pskp) {
+           if (!remembernode(pskp) || !remembernode(peg))
+               loop_warn_two(peg, pskp, act);
+       } else {
+           /* Does this happen? */
+           if (!remembernode(pskp))
+               loop_warn_one(peg, act);
+       }
+       goto out;
+    }
+
+    if (deep < (peg->mindeep)) /* Default deep of this tree is higher */
+       deep = (peg->mindeep);
+
+    if (deep > MAX_DEEP) {
+       if ((peg->flags & DIR_MAXDEEP) == 0)
+           warn("Max recursions depth %d for %s reached\n",  MAX_DEEP, peg->name);
+       peg->flags |= DIR_MAXDEEP;
+       goto out;
+    }
+
+    for (tmp = dir; tmp; tmp = getnextlink(l_list)) {
+       register boolean recursion = true;
+       handle_t * ptmp = (mode == 'K') ? &tmp->stopp : &tmp->start;
+       uchar  * order = &ptmp->deep;
+       list_t * dent;
+
+       if (loop++ > MAX_DEEP) {
+           if (pskp) {
+               if (!remembernode(pskp) || !remembernode(ptmp))
+                   loop_warn_two(ptmp, pskp, act);
+           } else {
+               if (!remembernode(ptmp))
+                   loop_warn_one(ptmp, act);
+           }
+           break;                      /* Loop detected, stop recursion */
+       }
+       l_list = &ptmp->link;           /* List of symbolic links for getnextlink() */
+       prefetch(l_list->next);
+
+       if (!((peg->run.lvl) & (ptmp->run.lvl)))
+            continue;                  /* Not same boot level */
+
+       if (pskp && pskp == ptmp) {
+           if (!remembernode(pskp) || !remembernode(ptmp))
+               loop_warn_one(pskp, act);
+           break;                      /* Loop detected, stop recursion */
+       }
+
+       /*
+        * As higher the link depth, as higher the start order.
+        */
+       if (*order > deep)
+           deep = *order;
+       if (*order < deep)
+           *order = deep;
+
+       if ((ptmp->run.lvl) & LVL_ALL) {
+           if (maxorder && (*maxorder < *order))
+               *maxorder = *order;
+       }
+
+       if (list_empty(l_list))
+           break;                      /* No further service requires this one */
+
+       /*
+        * Do not count the dependcy deep of the system facilities
+        * but follow them to count the replacing provides.
+        */
+       if (*ptmp->name == '$')
+           warn("System facilities not fully expanded, see %s!\n", dir->name);
+       else if (++deep > MAX_DEEP) {
+           if ((ptmp->flags & DIR_MAXDEEP) == 0)
+               warn("Max recursions depth %d reached\n",  MAX_DEEP);
+           ptmp->flags |= DIR_MAXDEEP;
+           break;
+       }
+
+       ptmp->flags |= DIR_SCAN;        /* Mark this service for loop detection */
+
+       /*
+        * If there are links in the links included, follow them
+        */
+       np_list_for_each(dent, l_list) {
+           dir_t * target = getlink(dent)->target;
+           handle_t * ptrg = (mode == 'K') ? &target->stopp : &target->start;
+
+           if ((peg->run.lvl & ptrg->run.lvl) == 0)
+               continue;                       /* Not same boot level */
+
+           if (target == tmp)
+               break;                          /* Loop avoided */
+       
+           if (target == dir)
+               break;                          /* Loop avoided */
+       
+           if (skip && skip == target) {
+               if (!remembernode(pskp) || !remembernode(ptmp))
+                   loop_warn_two(pskp, ptmp, act);
+               recursion = false;
+               break;                          /* Loop detected, stop recursion */
+           }
+
+           if (ptrg->deep >= deep)             /* Nothing new */
+               continue;
+                                               /* The inner recursion */
+           __follow(target, tmp, deep, mode, reportloop);
+           prefetch(dent->next);
+
+           /* Just for the case an inner recursion was stopped */
+           if (loop_check(ptrg) || loop_check(ptmp) || loop_check(pskp)) {
+               recursion = false;
+               break;                          /* Loop detected, stop recursion */
+           }
+       }
+
+       ptmp->flags &= ~DIR_SCAN;       /* Remove loop detection mark */
+       prefetch(l_list->next);
+
+       if (!recursion) {
+           if (reportloop && !(ptmp->flags & DIR_LOOPREPORT)) {
+               warn(" loop involving service %s at depth %d\n", tmp->name, level);
+               ptmp->flags |= DIR_LOOPREPORT;
+           }
+           break;                      /* Loop detected, stop recursion */
+       }
+    }
+out:
+    return;                    /* Make compiler happy */
+}
+
+#undef loop_warn_two
+#undef loop_warn_one
+#undef loop_check
+
+/*
+ * Helper for follow_all: start with depth one.
+ */
+static inline void follow(dir_t *restrict dir, const char mode, const char reportloop) attribute((always_inline,nonnull(1)));
+static inline void follow(dir_t *restrict dir, const char mode, const char reportloop)
+{
+    const int deep = (mode == 'K') ? (dir->stopp.mindeep) : (dir->start.mindeep);
+    /* Link depth starts here with one */
+    __follow(dir, (dir_t*)0, deep, mode, reportloop);
+}
+
+/*
+ * Put not existing services into a guessed order.
+ * The maximal order of not existing services can be
+ * set if they are required by existing services.
+ */
+static void guess_order(dir_t *restrict dir, const char mode) attribute((nonnull(1)));
+static void guess_order(dir_t *restrict dir, const char mode)
+{
+    handle_t * peg  = (mode == 'K') ? &dir->stopp : &dir->start;
+    list_t * l_list = &peg->link;
+    register int min = 99;
+    register int deep = 0;
+    ushort lvl = 0;
+
+    if (dir->script)   /* Skip it because we have read it */
+       goto out;
+
+    if (*dir->name == '$') {   /* Don't touch our system facilities */
+       warn("System facilities not fully expanded, see %s!\n", dir->name);
+       goto out;
+    }
+
+    /* No full loop required because we seek for the lowest order */
+    if (!list_empty(l_list)) {
+       dir_t * target = getnextlink(l_list);
+       handle_t * ptrg = (mode == 'K') ? &target->stopp : &target->start;
+       uchar * order = &ptrg->deep;
+       list_t * dent;
+
+       if (min > *order)
+           min = *order;
+
+       lvl |= ptrg->run.lvl;
+
+       list_for_each_prev(dent, l_list) {
+           dir_t * tmp = getlink(dent)->target;
+           handle_t * ptmp = (mode == 'K') ? &tmp->stopp : &tmp->start;
+           uchar * order = &ptmp->deep;
+
+           if (++deep > MAX_DEEP)
+               break;
+
+           if (target == dir)
+               break;          /* Loop detected */
+
+           if (min > *order)
+               min = *order;
+
+           lvl |= ptmp->run.lvl;
+       }
+       if (min > 1) {          /* Set guessed order of this unknown script */
+           uchar * order = &peg->deep;
+           *order = min - 1;
+           peg->run.lvl |= lvl;        /* Set guessed runlevels of this unknown script */
+       } else {
+           peg->run.lvl  = LVL_BOOT;
+       }
+    }
+out:
+    return;
+}
+
+/*
+ * Sort linked list of provides into start or stop order
+ * during this set new start or stop order of the serives.
+ */
+#undef SORT_REQUESTS
+void lsort(const char type)
+{
+    list_t sort = { &sort, &sort };
+#ifdef SORT_REQUESTS
+    list_t * this;
+#endif /* SORT_REQUESTS */
+    int order;
+
+    switch (type) {
+    case 'K':
+       for (order = 0; order <= maxstop; order++) {
+           list_t * ptr, * safe;
+           list_for_each_safe(ptr, safe, d_start) {
+               dir_t * dir = getdir(ptr);
+               if (dir->stopp.deep == order)
+                   move_tail(ptr, &sort);
+           }
+       }
+       join(&sort, d_start);
+#ifdef SORT_REQUESTS
+       list_for_each(this, s_start) {
+           service_t * serv = getservice(this);
+           if (serv->attr.flags & SERV_DUPLET)
+               continue;
+           initial(&sort);
+           for (order = 0; order <= maxstop; order++) {
+               list_t * ptr, * safe;
+               list_for_each_safe(ptr, safe, &serv->sort.rev) {
+                   req_t * rev = getreq(ptr);
+                   dir_t * dir = (dir_t*)rev->serv->dir;
+                   if (dir->stopp.deep == order)
+                       move_tail(ptr, &sort);
+               }
+           }
+           join(&sort, &serv->sort.rev);
+       }
+#endif /* SORT_REQUESTS */
+       break;
+    default:
+       for (order = 0; order <= maxstart; order++) {
+           list_t * ptr, * safe;
+           list_for_each_safe(ptr, safe, d_start) {
+               dir_t * dir = getdir(ptr);
+               if (dir->start.deep == order)
+                   move_tail(ptr, &sort);
+           }
+       }
+       join(&sort, d_start);
+#ifdef SORT_REQUESTS
+       list_for_each(this, s_start) {
+           service_t * serv = getservice(this);
+           if (serv->attr.flags & SERV_DUPLET)
+               continue;
+           initial(&sort);
+           for (order = 0; order <= maxstart; order++) {
+               list_t * ptr, * safe;
+               list_for_each_safe(ptr, safe, &serv->sort.req) {
+                   req_t * req = getreq(ptr);
+                   dir_t * dir = (dir_t*)req->serv->dir;
+                   if (dir->start.deep == order)
+                       move_tail(ptr, &sort);
+               }
+           }
+           join(&sort, &serv->sort.req);
+       }
+#endif /* SORT_REQUESTS */
+       break;
+    }
+
+
+}
+
+/*
+ * Clear out aliases of existing services, that is that for *one* script there
+ * exist several provides which could have have been required different by
+ * other services.  This avoids doing the same work several times.
+ */ 
+void nickservice(service_t *restrict orig, service_t *restrict nick)
+{
+    dir_t * dir = (dir_t*)orig->dir;
+    dir_t * cmp = (dir_t*)nick->dir;
+    list_t * dent, * safe;
+
+    if (dir == cmp)
+       return;
+
+    if (cmp->script && cmp->script != dir->script)
+       return;
+
+    list_for_each_safe(dent, safe, &cmp->start.link) {
+       link_t * link  = getlink(dent);
+       dir_t * target = link->target;
+
+       if (target == cmp)
+           continue;
+
+       ln_sf(target, dir, 'S');
+
+       /* remove the link from local link list but never free the target */
+
+       delete(dent);
+       free(link);
+    }
+
+    list_for_each_safe(dent, safe, &cmp->stopp.link) {
+       link_t * link  = getlink(dent);
+       dir_t * target = link->target;
+
+       if (target == cmp)
+           continue;
+
+       ln_sf(target, dir, 'K');
+
+       /* remove the link from local link list but never free the target */
+
+       delete(dent);
+       free(link);
+    }
+
+    delete(&cmp->d_list);      /* remove alias entry from global service list */
+
+                               /* remember levels of old start handle */
+    dir->start.run.lvl |= cmp->start.run.lvl;
+    dir->start.flags   |= cmp->start.flags;
+
+                               /* remember levels of old stop handle */
+    dir->stopp.run.lvl |= cmp->stopp.run.lvl;
+    dir->stopp.flags   |= cmp->stopp.flags;
+
+                               /* remember global flags of old provide */
+    orig->attr.flags |= nick->attr.flags;
+    nick->attr.flags |= SERV_DUPLET;
+
+    if (cmp->script && cmp->script != dir->script) {
+       free(nick->attr.script);
+       nick->attr.script = orig->attr.script;
+    }
+
+    nick->dir   = (void*)dir;  /* remember main provide */
+    nick->start = &dir->start.run;
+    nick->stopp = &dir->stopp.run;
+
+    if (--cmp->ref <= 0) free(cmp);
+
+    list_for_each_safe(dent, safe, &nick->sort.req) {
+       req_t * this = getreq(dent);
+       boolean ok = true;
+       list_t * req;
+       list_for_each(req, &orig->sort.req) {
+           if (!strcmp(this->serv->name,getreq(req)->serv->name)) {
+               ok = false;
+               break;
+           }
+       }
+       if (!ok) {
+           delete(dent);
+           free(this);
+       } else
+           move_tail(dent, &orig->sort.req);
+    }
+
+    list_for_each_safe(dent, safe, &nick->sort.rev) {
+       req_t * this = getreq(dent);
+       boolean ok = true;
+       list_t * rev;
+       list_for_each(rev, &orig->sort.rev) {
+           if (!strcmp(this->serv->name,getreq(rev)->serv->name)) {
+               ok = false;
+               break;
+           }
+       }
+       if (!ok) {
+           delete(dent);
+           free(this);
+       } else
+           move_tail(dent, &orig->sort.rev);
+    }
+}
+
+void clear_all(void)
+{
+    list_t * this;
+
+    /*
+     * Find dangling links in global service list and remove them
+     * if we by detect the remove bit from set above in the flags.
+     */
+
+    list_for_each(this, d_start) {
+       dir_t *dir = getdir(this);
+       list_t *dent, *hold;
+
+       list_for_each_safe(dent, hold, &dir->start.link) {
+           link_t * link  = getlink(dent);
+           dir_t * target = link->target;
+
+           if (target == dir)
+               continue;
+
+           if ((attof(target)->flags & SERV_DUPLET) == 0)
+               continue;
+
+           /* remove the link from local link list */
+
+           delete(dent);
+           free(link);
+
+           /* 
+            * Do not free allocated strings and structure if in use
+            * never free cmp->attr.script as this remains always in use.
+            */
+
+           if (--target->ref <= 0) free(target);
+       }
+
+       list_for_each_safe(dent, hold, &dir->stopp.link) {
+           link_t * link  = getlink(dent);
+           dir_t * target = link->target;
+
+           if (target == dir)
+               continue;
+
+           if ((attof(target)->flags & SERV_DUPLET) == 0)
+               continue;
+
+           /* remove the link from local link list */
+
+           delete(dent);
+           free(link);
+
+           /* 
+            * Do not free allocated strings and structure if in use
+            * never free cmp->attr.script as this remains always in use.
+            */
+
+           if (--target->ref <= 0) free(target);
+       }
+    }
+#if defined(DEBUG) && (DEBUG > 0)
+    list_for_each(this, s_start) {
+       service_t * srv = getservice(this);
+       list_t * nxt, * hold;
+
+       if (srv->attr.flags & SERV_DUPLET)
+           continue;
+
+       list_for_each_safe(nxt, hold, s_start) {
+           list_t * dent, * safe;
+           service_t * orv;
+
+           orv = getservice(nxt);
+
+           if ((orv->attr.flags & SERV_DUPLET) == 0)
+               continue;
+
+           if (srv->dir != orv->dir)
+               continue;
+
+           srv->attr.flags |= orv->attr.flags;
+           srv->attr.flags &= ~SERV_DUPLET;
+
+           list_for_each_safe(dent, safe, &orv->sort.req) {
+               req_t * this = getreq(dent);
+               boolean ok = true;
+               list_t * req;
+               list_for_each(req, &srv->sort.req) {
+                   if (!strcmp(this->serv->name,getreq(req)->serv->name)) {
+                       ok = false;
+                       break;
+                   }
+               }
+               if (!ok) {
+                  fprintf(stderr, "BUG: removed %s from start list of %s, missed getorig()?\n",
+                          this->serv->name, orv->name);
+                  delete(dent);
+                  free(this);
+               } else {
+                  fprintf(stderr, "BUG: moved %s from start list of %s to %s, missed getorig()?\n",
+                          this->serv->name, orv->name, srv->name);
+                  move_tail(dent, &srv->sort.req);
+               }
+           }
+
+           list_for_each_safe(dent, safe, &orv->sort.rev) {
+               req_t * this = getreq(dent);
+               boolean ok = true;
+               list_t * rev;
+               list_for_each(rev, &srv->sort.rev) {
+                  if (!strcmp(this->serv->name,getreq(rev)->serv->name)) {
+                       ok = false;
+                       break;
+                  }
+               }
+               if (!ok) {
+                  fprintf(stderr, "BUG: removed %s from start list of %s, missed getorig()?\n",
+                          this->serv->name, orv->name);
+                  delete(dent);
+                  free(this);
+               } else {
+                  fprintf(stderr, "BUG: moved %s from start list of %s to %s, missed getorig()?\n",
+                          this->serv->name, orv->name, srv->name);
+                  move_tail(dent, &srv->sort.rev);
+               }
+           }
+       }
+    }
+#endif
+}
+
+/*
+ * Follow all services and their dependencies recursivly.
+ */
+void follow_all(void)
+{
+    list_t *tmp;
+
+    /*
+     * Follow all scripts and calculate the main ordering.
+     */
+    list_for_each(tmp, d_start) {
+       maxorder = &maxstart;
+       follow(getdir(tmp), 'S', 1);
+       maxorder = &maxstop;
+       follow(getdir(tmp), 'K', 1);
+    }
+
+    /*
+     * Guess order of not installed scripts in comparision
+     * to the well known scripts.
+     */
+    list_for_each(tmp, d_start) {
+       maxorder = &maxstart;
+       guess_order(getdir(tmp), 'S');
+       maxorder = &maxstart;
+       guess_order(getdir(tmp), 'K');
+    }
+}
+
+boolean is_loop_detected(void)
+{
+    list_t *tmp;
+    list_for_each(tmp, d_start) {
+       dir_t * dir = getdir(tmp);
+       if (dir->start.flags & DIR_LOOPREPORT)
+           return true;
+       if (dir->stopp.flags  & DIR_LOOPREPORT)
+           return true;
+    }
+    return false;
+}
+
+/*
+ * For debuging: show all services
+ */
+#if defined(DEBUG) && (DEBUG > 0)
+void show_all()
+{
+    list_t *tmp;
+    if (maxstop > 0) list_for_each(tmp, d_start) {
+       char * script, *name, *lvlstr;
+       dir_t * dir = getdir(tmp);
+       handle_t * peg;
+       uchar deep;
+       ushort lvl;
+       if (!dir)
+           continue;
+       name = dir->name;
+       peg  = &dir->stopp;
+       lvl  = peg->run.lvl;
+       deep = peg->deep;
+       if (attof(dir)->script)
+           script = attof(dir)->script;
+       else if (*name == '$')
+           script = "%system";
+       else
+           script = "%guessed";
+       lvlstr = lvl2str(lvl);
+       info("K%.2d %s 0x%.2x '%s' (%s)\n", deep, name, lvl, lvlstr, script);
+       xreset(lvlstr);
+    }
+    if (maxstart > 0) list_for_each(tmp, d_start) {
+       char * script, *name, *lvlstr;
+       dir_t * dir = getdir(tmp);
+       handle_t * peg;
+       uchar deep;
+       ushort lvl;
+       if (!dir)
+           continue;
+       name = dir->name;
+       peg  = &dir->start;
+       lvl  = peg->run.lvl;
+       deep = peg->deep;
+       if (attof(dir)->script)
+           script = attof(dir)->script;
+       else if (*name == '$')
+           script = "%system";
+       else
+           script = "%guessed";
+       lvlstr = lvl2str(lvl);
+       info("S%.2d %s 0x%.2x '%s' (%s)\n", deep, name, lvl, lvlstr, script);
+       xreset(lvlstr);
+    }
+}
+#endif
+
+/*
+ * Used within loops to get scripts not included in this runlevel
+ */
+boolean notincluded(const char *restrict const script, const char mode, const int runlevel)
+{
+    list_t *tmp;
+    boolean ret = false;
+    const ushort lvl = map_runlevel_to_lvl (runlevel);
+
+    list_for_each_prev(tmp, d_start) {
+       dir_t * dir = getdir(tmp);
+       level_t * run = (mode == 'K') ? &dir->stopp.run : &dir->start.run;
+
+       if (run->lvl & lvl)             /* Same runlevel */
+           continue;
+
+       if (dir->script == (char*)0)    /* No such file */
+           continue;
+
+       if (strcmp(script, dir->script))
+           continue;                   /* Not this file */
+
+       ret = true;                     /* Not included */
+       break;
+    }
+
+    return ret;
+}
+
+/*
+ * Used within loops to list services an for a given runlevel bit mask.
+ */
+service_t * listscripts(const char **restrict script, const char mode, const ushort lvl)
+{
+    static list_t * tmp;
+    service_t * serv;
+    ushort level;
+    dir_t * dir;
+
+    if (!*script)
+       tmp  = d_start->next;
+
+    do {
+       serv = (service_t*)0;
+       if (tmp == d_start)
+           break;
+       prefetch(tmp->next);
+       dir = getdir(tmp);
+
+        attof(dir)->korder = dir->stopp.deep;
+        attof(dir)->sorder = dir->start.deep;
+
+       serv = dir->serv;
+       *script = serv->attr.script;
+
+       switch (mode) {
+       case 'X':
+           level = (dir->stopp.run.lvl|dir->start.run.lvl);
+           break;
+       case 'K':
+           level = dir->stopp.run.lvl;
+           break;
+       default:
+           level = dir->start.run.lvl;
+           break;
+       }
+
+       tmp = tmp->next;
+
+    } while ((*script == (char*)0) || (level & lvl) == 0);
+
+    return serv;
+}
+
+/*
+ * THIS services DEPENDS on that service befor startup or shutdown.
+ */
+void requires(service_t *restrict this, service_t *restrict dep, const char mode)
+{
+    ln_sf((dir_t*)this->dir, (dir_t*)dep->dir, mode);
+}
+
+/*
+ * Set the runlevels of a service.
+ */
+void runlevels(service_t *restrict serv, const char mode, const char *restrict lvl)
+{
+    dir_t * dir   = (dir_t *)serv->dir;
+    handle_t * peg = (mode == 'K') ? &dir->stopp : &dir->start;
+    peg->run.lvl |= str2lvl(lvl);
+}
+
+/*
+ * Reorder all services starting with a service
+ * being in same runlevels.
+ */
+void setorder(const char *restrict script, const char mode, const int order, const boolean recursive)
+{
+    dir_t * dir = findscript(script);
+    handle_t * peg;
+    list_t * tmp;
+
+    if (!dir)
+       goto out;
+
+    if (mode == 'K') {
+       peg = &dir->stopp;
+       maxorder = &maxstop;
+    } else {
+       peg = &dir->start;
+       maxorder = &maxstart;
+    }
+
+    if (peg->mindeep < order)
+       peg->mindeep = order;           /* Remember lowest default order deep */
+
+    if (peg->deep >= peg->mindeep)     /* Nothing to do */
+       goto out;
+
+    if (!recursive) {
+       peg->deep = peg->mindeep;
+       goto out;
+    }
+
+    /*
+     * Follow the script and re-calculate the ordering.
+     */
+    __follow(dir, (dir_t*)0, peg->mindeep, mode, 0);
+
+    /*
+     * Guess order of not installed scripts in comparision
+     * to the well known scripts.
+     */
+    list_for_each(tmp, d_start)
+       guess_order(getdir(tmp), mode);
+out:
+    return;
+}
+
+/*
+ * Get the order of a script.
+ */
+int getorder(const char *restrict script, const char mode)
+{
+    dir_t * dir = findscript(script);
+    int order = 0;
+
+    if (dir) {
+       handle_t * peg = (mode == 'K') ? &dir->stopp : &dir->start;
+       order = peg->deep;
+    }
+
+    return order;
+}
+
+/*
+ * Provide a service if the corresponding script
+ * was read and the scripts name was remembered.
+ * A given script name marks a service as a readed one.
+ * One script and several provided facilities leads
+ * to the same order for those facilities.
+ */
+boolean makeprov(service_t *restrict serv, const char *restrict script)
+{
+    dir_t *restrict alias = findscript(script);
+    dir_t *restrict dir   = (dir_t *restrict)serv->dir;
+    boolean ret = true;
+
+    if (!dir->script) {
+       list_t * ptr;
+       if (!alias) {
+           serv->attr.script = xstrdup(script);
+           serv->attr.flags |= SERV_SCRIPT;
+           dir->script = serv->attr.script;
+       } else
+           dir->script = alias->script;
+
+       list_for_each(ptr, s_start) {
+           service_t * tmp = getservice(ptr);
+           if (tmp == serv)
+               continue;
+           if (tmp->dir != serv->dir)
+               continue;
+           if (tmp->attr.script)
+               continue;
+           tmp->attr.script = dir->script;
+           tmp->attr.flags |= SERV_SCRIPT;
+       }
+
+    } else if (strcmp(dir->script, script))
+       ret = false;
+
+    return ret;
+}
+
+/*
+ * Find the script name of a provided feature
+ */
+const char * getscript(const char *restrict prov)
+{
+    char * script = (char*)0;
+    list_t * ptr;
+
+    list_for_each(ptr, s_start) {
+       service_t * this = getservice(ptr);
+       if (!strcmp(this->name, prov)) {
+           if (this->attr.script)
+               script = this->attr.script;
+           break;
+       }
+    }
+    return script;
+}
+
+/*
+ * Return the provided service of a given script
+ */
+const char * getprovides(const char *restrict script)
+{
+    const dir_t * dir = findscript(script);
+    const char * prov = (const char*)0;
+
+    if (dir)
+       prov = dir->name;
+    return prov;
+}
+
+/*
+ * Find a specific service by its name
+ */
+service_t * findservice(const char *restrict const name)
+{
+    list_t * ptr;
+    service_t * ret = (service_t*)0;
+
+    if (name == (const char*)0)
+       goto out;
+
+    list_for_each(ptr, s_start) {
+       service_t * this = getservice(ptr);
+       if (!strcmp(this->name, name)) {
+           ret = this;
+           break;
+       }
+    }
+out:
+    return ret;
+}
diff --git a/listing.h b/listing.h
new file mode 100644 (file)
index 0000000..3cd10f5
--- /dev/null
+++ b/listing.h
@@ -0,0 +1,407 @@
+/*
+ * listing.h
+ *
+ * Copyright 2000,2008 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany.
+ *                                 2008 SuSE Linux Products GmbH Nuernberg, Germany
+ *
+ * This source is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stddef.h>
+#include <sys/types.h>
+#include "config.h"
+
+typedef enum _boolean {false, true} boolean;
+typedef unsigned char uchar;
+#ifndef __USE_MISC
+typedef unsigned short ushort;
+typedef unsigned int uint;
+#endif
+
+#ifndef __OPTIMIZE__
+# warning This will not compile without -O at least
+#endif
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
+# ifndef  inline
+#  define inline               __inline__
+# endif
+# ifndef  restrict
+#  define restrict             __restrict__
+# endif
+# ifndef  volatile
+#  define volatile             __volatile__
+# endif
+# ifndef  asm
+#  define asm                  __asm__
+# endif
+# ifndef  extension
+#  define extension            __extension__
+# endif
+#endif
+#ifndef  attribute
+# define attribute(attr)       __attribute__(attr)
+#endif
+
+/*
+ * This is lent from the kernel by e.g. using
+ *
+ *   echo '#include <asm-i386/processor.h>\nint main () { prefetch(); return 0; }' | \
+ *     gcc -I/usr/src/linux/include -D__KERNEL__ -x c -E -P - | \
+ *     sed -rn '/void[[:blank:]]+prefetch[[:blank:]]*\(/,/^}/p'
+ *
+ * on the appropiate architecture (here on i686 for i586).
+ */
+static inline void prefetch(const void *restrict x) attribute((used,always_inline));
+static inline void prefetch(const void *restrict x)
+{
+#if   defined(__x86_64__)
+    asm volatile ("prefetcht0 %0"  :: "m" (*(unsigned long *)x))
+#elif defined(__ia64__)
+    asm volatile ("lfetch [%0]"    :: "r" (x))
+#elif defined(__powerpc64__)
+    asm volatile ("dcbt 0,%0"      :: "r" (x))
+#elif 1 && defined(__i386__)
+    asm volatile ("661:\n\t"
+                 ".byte 0x8d,0x74,0x26,0x00\n"
+                 "\n662:\n"
+                 ".section .altinstructions,\"a\"\n"
+                 "  .align 4\n"
+                 "  .long 661b\n"
+                 "  .long 663f\n"
+                 "  .byte %c0\n"
+                 "  .byte 662b-661b\n"
+                 "  .byte 664f-663f\n"
+                 ".previous\n"
+                 ".section .altinstr_replacement,\"ax\"\n"
+                 "   663:\n\t"
+                 "   prefetchnta (%1)"
+                 "   \n664:\n"
+                 ".previous"
+                 :: "i" ((0*32+25)), "r" (x))
+#endif
+    ;
+}
+
+#if defined(DEBUG) && (DEBUG > 0)
+# define __align attribute((packed))
+#else
+# define __align attribute((aligned(sizeof(struct list_struct*))))
+#endif
+#define __packed attribute((packed))
+
+#define alignof(type)          (sizeof(type)+(sizeof(type)%sizeof(void*)))
+#define strsize(string)                ((strlen(string)+1)*sizeof(char))
+
+typedef struct list_struct {
+    struct list_struct * next, * prev;
+} __align list_t;
+
+/*
+ * Linked list handling
+ * ====================
+ * The structures which will be linked into such lists have to be of the
+ * same type.  The structures may have alway a list identifier of the type
+ * `list_t' as very first element.  With this the macro list_entry() can
+ * be used to cast the memory address of a list member to the corresponding
+ * allocated structure.
+ */
+
+/*
+ * Insert new entry as next member.
+ */
+static inline void insert(list_t *restrict new, list_t *restrict here) attribute((always_inline,nonnull(1,2)));
+static inline void insert(list_t *restrict new, list_t *restrict here)
+{
+    list_t * prev = here;
+    list_t * next = here->next;
+
+    next->prev = new;
+    new->next = next;
+    new->prev = prev;
+    prev->next = new;
+}
+
+/*
+ * Set head
+ */
+static inline void initial(list_t *restrict head) attribute((always_inline,nonnull(1)));
+static inline void initial(list_t *restrict head)
+{
+    head->prev = head->next = head;
+}
+
+/*
+ * Remove entries, note that the pointer its self remains.
+ */
+static inline void delete(list_t *restrict entry) attribute((always_inline,nonnull(1)));
+static inline void delete(list_t *restrict entry)
+{
+    list_t * prev = entry->prev;
+    list_t * next = entry->next;
+
+    next->prev = prev;
+    prev->next = next;
+
+    initial(entry);
+}
+
+static inline void join(list_t *restrict list, list_t *restrict head) attribute((always_inline,nonnull(1,2)));
+static inline void join(list_t *restrict list, list_t *restrict head)
+{
+    list_t * first = list->next;
+
+    if (first != list) {
+       list_t * last = list->prev;
+               list_t * at = head->next;
+
+               first->prev = head;
+               head->next = first;
+
+               last->next = at;
+               at->prev = last;
+    }
+}
+
+static inline boolean list_empty(list_t *restrict head) attribute((always_inline,nonnull(1)));
+static inline boolean list_empty(list_t *restrict head)
+{
+     return head->next == head;
+}
+
+static inline void move_tail(list_t *restrict entry, list_t *restrict head) attribute((always_inline,nonnull(1,2)));
+static inline void move_tail(list_t *restrict entry, list_t *restrict head)
+{
+    list_t * prev = entry->prev;
+    list_t * next = entry->next;
+
+    next->prev = prev;         /* remove enty from old list */
+    prev->next = next;
+
+    prev = head->prev;
+    next = head;
+
+    next->prev = entry;                /* and add it at tail of new list */
+    entry->next = next;
+    entry->prev = prev;
+    prev->next = entry;
+}
+
+
+#define list_entry(ptr, type, member)  (__extension__ ({       \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       ((type *)( (char *)(__mptr) - offsetof(type,member) )); }))
+#define list_for_each(pos, head)       \
+       for (pos = (head)->next; prefetch(pos->next), pos != (head); pos = pos->next)
+#define np_list_for_each(pos, head)    \
+       for (pos = (head)->next; pos != (head); pos = pos->next)
+#define list_for_each_safe(pos, safe, head)    \
+       for (pos = (head)->next, safe = pos->next; pos != (head); pos = safe, safe = pos->next)
+#define list_for_each_prev(pos, head)  \
+       for (pos = (head)->prev; prefetch(pos->prev), pos != (head); pos = pos->prev)
+#define np_list_for_each_prev(pos, head)       \
+       for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+/*
+ * The runlevel bits within own struct
+ */
+typedef struct level_struct {
+    ushort                 lvl;
+} __packed level_t;
+
+/*
+ * Common attributes
+ */
+typedef struct attr_struct {
+    ushort               flags;
+    short                  ref;
+    uchar               sorder;
+    uchar               korder;
+    char               *script;
+} __packed attr_t;
+
+/*
+ * Linked list of required services (start/stop)
+ */
+typedef struct sort_struct {
+    list_t            req, rev;
+} __align sort_t;
+
+/*
+ * Objects of linked list of required services
+ */
+typedef struct service_struct service_t;
+typedef struct req_serv {
+    list_t                list;
+    ushort               flags;
+    service_t   *restrict serv;
+} __align req_t;
+#define getreq(arg)    list_entry((arg), struct req_serv, list)
+
+/*
+ * Used by findservice()
+ */
+struct service_struct {
+    list_t              s_list;
+    sort_t                sort;
+    void       *restrict   dir;
+    level_t    *restrict start;
+    level_t    *restrict stopp;
+    attr_t                attr;
+    char                * name;
+} __align;
+#define getservice(list)       list_entry((list), service_t, s_list)
+
+extern list_t * s_start;
+extern int maxstart;
+extern int maxstop;
+
+extern void clear_all(void);
+extern void nickservice(service_t *restrict orig, service_t *restrict nick) attribute((nonnull(1,2)));
+extern void follow_all(void);
+extern void show_all(void);
+extern void requires(service_t *restrict this, service_t *restrict dep, const char mode) attribute((nonnull(1,2)));
+extern void runlevels(service_t *restrict serv, const char mode, const char *restrict lvl) attribute((nonnull(1,3)));
+extern boolean makeprov(service_t *restrict serv, const char *restrict script) attribute((nonnull(1,2)));
+extern void setorder(const char *restrict script, const char mode, const int order, const boolean recursive) attribute((nonnull(1)));
+extern int getorder(const char *restrict script, const char mode) attribute((nonnull(1)));
+extern boolean notincluded(const char *restrict const script, const char mode, const int runlevel) attribute((nonnull(1)));
+extern const char * getscript(const char *restrict prov) attribute((nonnull(1)));
+extern const char * getprovides(const char *restrict script) attribute((nonnull(1)));
+extern service_t * listscripts(const char **restrict script, const char mode, const ushort lvl);
+extern boolean is_loop_detected(void);
+extern service_t * addservice(const char *restrict const serv) attribute((malloc,nonnull(1)));
+extern service_t * findservice(const char *restrict const name);
+extern service_t * getorig(service_t *restrict serv) attribute((const,nonnull(1)));
+extern void lsort(const char type);
+
+/*
+ * Common short cuts
+ */
+extern const char *const delimeter;
+extern void error(const char *restrict fmt, ...) attribute((noreturn,format(printf,1,2)));
+extern void warn (const char *restrict fmt, ...) attribute((format(printf,1,2)));
+extern void info (const char *restrict fmt, ...) attribute((format(printf,1,2)));
+extern inline int map_has_runlevels(void) attribute((always_inline));
+extern inline char map_runlevel_to_key(const int runlevel);
+extern inline ushort map_key_to_lvl(const char key);
+extern inline const char *map_runlevel_to_location(const int runlevel);
+extern inline ushort map_runlevel_to_lvl(const int runlevel);
+extern inline ushort map_runlevel_to_seek(const int runlevel);
+extern ushort str2lvl(const char *restrict lvl) attribute((nonnull(1)));
+extern char * lvl2str(const ushort lvl);
+
+static inline char * xstrdup(const char *restrict s) attribute((always_inline,malloc));
+static inline char * xstrdup(const char *restrict s)
+{
+    char * r;
+    if (!s)
+       error("%s", strerror(EINVAL));
+    if (!(r = strdup(s)))
+       error("%s", strerror(errno));
+    return r;
+} 
+
+#define xreset(ptr)    \
+       {char *restrict tmp = (char *restrict)ptr; if (ptr && *tmp) free(ptr);} ptr = NULL
+
+#if defined(HAS_unlinkat) && defined(_ATFILE_SOURCE)
+# define xremove(d,x) (__extension__ ({ if ((dryrun ? 0 : \
+       (unlinkat(d,x,0) != 0 && (errno != EISDIR || unlinkat(d,x,AT_REMOVEDIR) != 0)))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+       else \
+       info("remove service %s/%s%s\n", path, rcd, x); }))
+#else
+# define xremove(d,x) (__extension__ ({ if ((dryrun ? 0 : (remove(x) != 0))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+       else \
+       info("remove service %s/%s%s\n", path, rcd, x); }))
+#endif
+#if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE)
+# define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlinkat(x, d, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+       info("enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+#else
+# define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlink(x, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+       info("enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+#endif
+#if defined(HAS_fstatat) && defined(_ATFILE_SOURCE)
+# define xstat(d,x,s)  (__extension__ ({ fstatat(d,x,s, 0); }))
+# define xlstat(d,x,s) (__extension__ ({ fstatat(d,x,s, AT_SYMLINK_NOFOLLOW); }))
+#else
+# define xstat(d,x,s)  (__extension__ ({ stat(x,s); }))
+# define xlstat(d,x,s) (__extension__ ({ lstat(x,s); }))
+#endif
+#if defined(HAS_readlinkat) && defined(_ATFILE_SOURCE)
+# define xreadlink(d,x,b,l)    (__extension__ ({ readlinkat(d,x,b,l); }))
+#else
+# define xreadlink(d,x,b,l)    (__extension__ ({ readlink(x,b,l); }))
+#endif
+#if defined(HAS_openat) && defined(_ATFILE_SOURCE)
+# define xopen(d,x,f)  (__extension__ ({ openat(d,x,f); }))
+#else
+# define xopen(d,x,f)  (__extension__ ({ open(x,f); }))
+#endif
+
+/*
+ * Bits of the requests
+ */
+#define REQ_MUST       0x0001
+#define REQ_SHLD       0x0002
+#define REQ_KILL       0x0004
+
+/*
+ * Bits of the services
+ */
+#define SERV_KNOWN     0x0001
+#define SERV_NOTLSB    0x0002
+#define SERV_ALREADY   0x0004
+#define SERV_INTRACT   0x0008 
+#define SERV_ENABLED   0x0010
+#define SERV_ALL       0x0020
+#define SERV_DUPLET    0x0040
+#define SERV_SCRIPT    0x0080
+#define SERV_NOSTOP    0x0100
+#define SERV_CMDLINE   0x0200
+
+/*
+ * Bits of the runlevels
+ */
+#define LVL_HALT       0x0001
+#define LVL_ONE                0x0002
+#define LVL_TWO                0x0004
+#define LVL_THREE      0x0008
+#define LVL_FOUR       0x0010
+#define LVL_FIVE       0x0020
+#define LVL_REBOOT     0x0040
+#ifdef SUSE
+# define LVL_SINGLE    0x0080
+# define LVL_BOOT      0x0100
+#else
+# define LVL_SINGLE    0x0000
+# define LVL_BOOT      0x0080
+#endif
+
+/*
+ * LVL_BOOT is already done if one of the LVL_ALL will be entered.
+ */
+#define LVL_ALL                (LVL_HALT|LVL_ONE|LVL_TWO|LVL_THREE|LVL_FOUR|LVL_FIVE|LVL_REBOOT|LVL_SINGLE)
+
+/*
+ * Normal runlevels which are _direct_ available by shutdown/reboot/halt
+ */
+#define LVL_NORM       (LVL_HALT|LVL_ONE|LVL_TWO|LVL_THREE|LVL_FOUR|LVL_FIVE|LVL_REBOOT)
+
+/*
+ * Oneway runlevels at shutdown/reboot/halt/single
+ */
+#define LVL_ONEWAY     (LVL_HALT|LVL_ONE|LVL_REBOOT|LVL_SINGLE)
+/*
+ * Maximum start/stop level
+ */
+#define MAX_DEEP 99
diff --git a/packaging/10_nosuse.patch b/packaging/10_nosuse.patch
new file mode 100644 (file)
index 0000000..faad0a8
--- /dev/null
@@ -0,0 +1,17 @@
+Purpose: Disable the SUSE flag.
+Fixes:   None, made as part of Debian porting.
+Status:  Debian specific, showed to upstream.
+---
+Index: insserv/Makefile
+===================================================================
+--- insserv.orig/Makefile      2009-09-26 22:35:26.000000000 +0200
++++ insserv/Makefile   2009-09-26 22:35:45.000000000 +0200
+@@ -9,7 +9,7 @@
+ #DESTDIR =    /tmp/root
+ #DEBUG         =      -DDEBUG=1 -Wpacked
+ DEBUG  =
+-ISSUSE         =      -DSUSE
++ISSUSE         =      -DNOTSUSE
+ DESTDIR        =
+ VERSION        =      1.12.0
+ DATE   =      $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
diff --git a/packaging/11_debian_conf.patch b/packaging/11_debian_conf.patch
new file mode 100644 (file)
index 0000000..5ca0d2a
--- /dev/null
@@ -0,0 +1,55 @@
+Purpose: Adjust the insserv configuration for Debian init.d script names.
+Fixes:   None, made as part of Debian porting.
+Status:  Debian specific, showed to upstream.
+---
+Index: insserv/insserv.conf
+===================================================================
+--- insserv.orig/insserv.conf  2009-09-26 22:35:26.000000000 +0200
++++ insserv/insserv.conf       2009-09-26 22:35:39.000000000 +0200
+@@ -1,29 +1,29 @@
+ #
+ # All local filesystems are mounted (done during boot phase)
+ #
+-$local_fs     boot.localfs
++$local_fs     +mountall +mountoverflowtmp +umountfs
+ #
+ # Low level networking (ethernet card)
+ #
+-$network      network +pcmcia +hotplug
++$network      +networking +ifupdown
+ #
+ # Named is operational
+ #
+-$named                +named +dnsmasq +lwresd $network
++$named                +named +dnsmasq +lwresd +bind9 $network
+ #
+ # All remote filesystems are mounted (note in some cases /usr may
+ # be remote. Most applications that care will probably require
+ # both $local_fs and $remote_fs)
+ #
+-$remote_fs    $local_fs +nfs
++$remote_fs    $local_fs +mountnfs +mountnfs-bootclean +umountnfs +sendsigs
+ #
+ # System logger is operational
+ #
+-$syslog               syslog
++$syslog               +rsyslog +sysklogd +syslog-ng +dsyslog +inetutils-syslogd 
+ #
+ # SunRPC portmapper available
+@@ -33,9 +33,9 @@
+ #
+ # The system time has been set correctly
+ #
+-$time         boot.clock +xntpd
++$time         +hwclock
+ #
+ # Services which need to be interactive
+ #
+-<interactive>   boot.crypto boot.localfs boot.rootfsck apache apache2 kdump
++<interactive>   glibc udev console-screen keymap keyboard-setup console-setup cryptdisks cryptdisks-early checkfs-loop
diff --git a/packaging/20_install_perms_fixup.patch b/packaging/20_install_perms_fixup.patch
new file mode 100644 (file)
index 0000000..c3ac3c8
--- /dev/null
@@ -0,0 +1,29 @@
+Purpose: Use correct permissions for installing /sbin/insserv and
+         /etc/insserv.conf
+Authour: Kel Modderman
+Fixes:   -
+Status:  Not yet submitted upstream.
+
+Index: insserv/Makefile
+===================================================================
+--- insserv.orig/Makefile      2009-09-26 22:35:39.000000000 +0200
++++ insserv/Makefile   2009-09-26 22:35:39.000000000 +0200
+@@ -41,14 +41,14 @@
+            RM = rm -f
+         MKDIR = mkdir -p
+         RMDIR = rm -rf
+-   INSTBINFLAGS = -m 0700
++   INSTBINFLAGS = -m 0755
+       INSTBIN = install $(INSTBINFLAGS)
+-   INSTSRPFLAGS = -m 0700
++   INSTSRPFLAGS = -m 0755
+       INSTSRP = install $(INSTSRPFLAGS)
+-   INSTDOCFLAGS = -c -m 0444
++   INSTDOCFLAGS = -c -m 0644
+       INSTDOC = install $(INSTDOCFLAGS)
+    INSTCONFLAGS = -c -m 0644
+-      INSTCON = install $(INSTDOCFLAGS)
++      INSTCON = install $(INSTCONFLAGS)
+          LINK = ln -sf
+ #
+       SDOCDIR = $(DESTDIR)/usr/share/man/man8
diff --git a/packaging/21_tests_suite_new_functions.patch b/packaging/21_tests_suite_new_functions.patch
new file mode 100644 (file)
index 0000000..14c0f23
--- /dev/null
@@ -0,0 +1,36 @@
+Purpose: Add some extra functions used by Debian test suite script
+Authour: Kel Modderman
+Fixes:   -
+Status:  Should be sent upstream
+
+Index: insserv/tests/suite
+===================================================================
+--- insserv.orig/tests/suite   2009-09-26 22:35:26.000000000 +0200
++++ insserv/tests/suite        2009-09-26 22:35:39.000000000 +0200
+@@ -94,6 +94,12 @@
+     $insserv $debug -c $insconf -p $initddir -o $overridedir -r $script
+ }
++initdir_purge ()
++{
++    rm -rf ${initddir}/../rc*.d ${initddir}
++    mkdir -p ${initddir}
++}
++
+ relpath ()
+ {
+     local OLDIFS IFS
+@@ -201,6 +207,13 @@
+     chmod u+w,a+rx $script
+ }
++remscript ()
++{
++    local scriptname=$1
++    local script=${initddir}/$scriptname
++    rm -f $script
++}
++
+ insertscript ()
+ {
+     local scriptname=$1
diff --git a/packaging/30_deterministic_order.patch b/packaging/30_deterministic_order.patch
new file mode 100644 (file)
index 0000000..5e52033
--- /dev/null
@@ -0,0 +1,77 @@
+Purpose: Defend against undeterministic directory stream sequence
+         returned by readdir(3). Make sure script which is being
+         registered is processed before all others.
+Fixes:   #494514
+Status:  Applied upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:25.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:44.000000000 +0200
+@@ -2238,6 +2238,7 @@
+     boolean del = false;
+     boolean defaults = false;
+     boolean ignore = false;
++    boolean loadarg = false;
+     myname = basename(*argv);
+@@ -2305,7 +2306,9 @@
+     argv += optind;
+     argc -= optind;
+-    if (!argc && del)
++    if (argc)
++      loadarg = true;
++    else if (del)
+       error("usage: %s [[-r] init_script|init_directory]\n", myname);
+     if (*argv) {
+@@ -2490,17 +2493,45 @@
+     /*
+      * Scan now all scripts found in the init.d/ directory
+      */
+-    while ((d = readdir(initdir)) != (struct dirent*)0) {
+-      const boolean isarg = chkfor(d->d_name, argv, argc);
++    for (;;) {
+       service_t * service = (service_t*)0;
+       char * token;
+       char * begin = (char*)0;        /* hold start pointer of strings handled by strsep() */
+       boolean hard = false;
++      boolean isarg = false;
+       uchar lsb = 0;
+ #if defined(DEBUG) && (DEBUG > 0)
+       int nobug = 0;
+ #endif
++      if ((d = readdir(initdir)) == (struct dirent*)0) {
++          /*
++           * If first script in argument list was loaded in advance, then
++           * rewind the init.d/ directory stream and attempt to load all
++           * other scripts.
++           */
++          if (loadarg) {
++              loadarg = false;
++              rewinddir(initdir);
++              continue;
++          }
++          break;
++      }
++
++      isarg = chkfor(d->d_name, argv, argc);
++
++      /*
++       * Load first script in argument list before all other scripts. This
++       * avoids problems with loading scripts in underterministic sequence
++       * returned by readdir(3).
++       */
++      if (loadarg && !isarg)
++          continue;
++      if (loadarg  && isarg && (curr_argc != 0))
++          continue;
++      if (!loadarg && isarg && (curr_argc == 0))
++          continue;
++
+       if (*d->d_name == '.')
+           continue;
+       errno = 0;
diff --git a/packaging/40_badboy_segfault.patch b/packaging/40_badboy_segfault.patch
new file mode 100644 (file)
index 0000000..cd36055
--- /dev/null
@@ -0,0 +1,21 @@
+Purpose: Defend against corrupt or invalid scripts living in
+         /etc/rc[S0-6].d/
+Fixes:   #493202
+Status:  Acked by upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:44.000000000 +0200
+@@ -1696,6 +1696,11 @@
+           }
+           lsb = scan_script_defaults(dfd, d->d_name, override_path, &name, true, ignore);
++          if (!name) {
++              warn("warning: script is corrupt or invalid: %s/%s%s\n", path, rcd, d->d_name);
++              continue;
++          }
++
+           if (!script_inf.provides || script_inf.provides == empty)
+               script_inf.provides = xstrdup(ptr);
diff --git a/packaging/50_symlink_in_initddir.patch b/packaging/50_symlink_in_initddir.patch
new file mode 100644 (file)
index 0000000..11ee33e
--- /dev/null
@@ -0,0 +1,67 @@
+Purpose: Defend against symlinks in init.d/ to other scripts in init.d/
+Fixes:   #485045
+Status:  Work in progress.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:44.000000000 +0200
+@@ -2542,11 +2542,12 @@
+       errno = 0;
+       /* d_type seems not to work, therefore use (l)stat(2) */
+-      if (xstat(dfd, d->d_name, &st_script) < 0) {
++      if (xlstat(dfd, d->d_name, &st_script) < 0) {
+           warn("can not stat(%s)\n", d->d_name);
+           continue;
+       }
+-      if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode))
++      if ((!S_ISLNK(st_script.st_mode) && !S_ISREG(st_script.st_mode)) ||
++          !(S_IXUSR & st_script.st_mode))
+       {
+           if (S_ISDIR(st_script.st_mode))
+               continue;
+@@ -2555,6 +2556,43 @@
+           continue;
+       }
++      /*
++       * Do extra sanity checking of symlinks in init.d/ dir, except if it
++       * is named reboot, as that is a special case on SUSE
++       */
++      if (S_ISLNK(st_script.st_mode) && ((strcmp(d->d_name, "reboot") != 0)))
++      {
++          char * base;
++          char linkbuf[PATH_MAX+1];
++          int  linklen;
++
++          linklen = xreadlink(dfd, d->d_name, linkbuf, sizeof(linkbuf)-1);
++          if (linklen < 0)
++              continue;
++          linkbuf[linklen] = '\0';
++
++          /* skip symbolic links to other scripts in this relative path */
++          if (!(base = strrchr(linkbuf, '/'))) {
++              if (isarg)
++                  warn("script %s is a symlink to another script, skipped!\n",
++                       d->d_name);
++              continue;
++          }
++
++          /* stat the symlink target and make sure it is a valid script */
++          if (xstat(dfd, d->d_name, &st_script) < 0)
++              continue;
++
++          if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode)) {
++              if (S_ISDIR(st_script.st_mode))
++                  continue;
++              if (isarg)
++                  warn("script %s is not an executable regular file, skipped!\n",
++                       d->d_name);
++              continue;
++          }
++      }
++
+       if (!strncmp(d->d_name, "README", strlen("README"))) {
+           if (isarg)
+               warn("script name %s is not valid, skipped!\n", d->d_name);
diff --git a/packaging/61_interactive_keyword.patch b/packaging/61_interactive_keyword.patch
new file mode 100644 (file)
index 0000000..3d85384
--- /dev/null
@@ -0,0 +1,132 @@
+Purpose: Add support for a X-Interactive keyword to avoid specifying it in insserv.conf
+Fixes:   #458224
+Status:  Work in progress.
+---
+
+Index: insserv/insserv.8.in
+===================================================================
+--- insserv.orig/insserv.8.in  2009-09-26 22:35:25.000000000 +0200
++++ insserv/insserv.8.in       2009-09-26 22:35:43.000000000 +0200
+@@ -76,6 +76,7 @@
+  # X-Stop-After:      boot_facility_1 [ boot_facility_2 ...]
+  # Default-Start:     run_level_1 [ run_level_2 ...]
+  # Default-Stop:      run_level_1 [ run_level_2 ...]
++ # X-Interactive:     true
+  # Short-Description: single_line_description
+  # Description:       multiline_description
+  ### END INIT INFO
+@@ -117,6 +118,11 @@
+ these tags is stopped.
+ @@END_SUSE@@
+ .PP
++The optional X\-Interactive keyword implies that the script using this
++keyword should be started alone in a concurrent boot configuration
++because it interact with the user at the console.  Only the value
++`true' is recogniced.  All other are ignored.
++.PP
+ The optional
+ .B X\-Start\-Before
+ keyword implies that the script using this keyword
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:43.000000000 +0200
+@@ -97,6 +97,7 @@
+ #define DEFAULT_START DEFAULT  START VALUE
+ #define DEFAULT_STOP  DEFAULT  STOP  VALUE
+ #define DESCRIPTION   COMM "description" VALUE
++#define INTERACTIVE   COMM "x-interactive" VALUE
+ /* System facility search within /etc/insserv.conf */
+ #define EQSIGN                "([[:blank:]]*[=:][[:blank:]]*|[[:blank:]]+)"
+@@ -133,6 +134,7 @@
+     char *default_start;
+     char *default_stop;
+     char *description;
++    char *interactive;
+ } attribute((aligned(sizeof(char*)))) lsb_t;
+ /* Search results points here */
+@@ -147,6 +149,7 @@
+     regex_t def_start;
+     regex_t def_stop;
+     regex_t desc;
++    regex_t interact;
+ } attribute((aligned(sizeof(regex_t)))) reg_t;
+ typedef struct creg_struct {
+@@ -1132,6 +1135,7 @@
+     regcompiler(&reg.def_start, DEFAULT_START,  REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+     regcompiler(&reg.def_stop,  DEFAULT_STOP,   REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+     regcompiler(&reg.desc,      DESCRIPTION,    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
++    regcompiler(&reg.interact,  INTERACTIVE,    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ }
+ static inline void scan_script_reset(void) attribute((always_inline));
+@@ -1147,6 +1151,7 @@
+     xreset(script_inf.default_start);
+     xreset(script_inf.default_stop);
+     xreset(script_inf.description);
++    xreset(script_inf.interactive);
+ }
+ #define FOUND_LSB_HEADER   0x01
+@@ -1177,6 +1182,7 @@
+ #define default_start script_inf.default_start
+ #define default_stop  script_inf.default_stop
+ #define description   script_inf.description
++#define interactive   script_inf.interactive
+     info("Loading %s\n", path);
+@@ -1273,6 +1279,14 @@
+               description = empty;
+       }
++      if (!interactive    && regexecutor(&reg.interact,      COMMON_ARGS) == true) {
++          if (val->rm_so < val->rm_eo) {
++              *(pbuf+val->rm_eo) = '\0';
++              interactive = xstrdup(pbuf+val->rm_so);
++          } else
++              interactive = empty;
++      }
++
+       /* Skip scanning below from LSB magic end */
+       if ((end = strstr(buf, "### END INIT INFO")))
+           break;
+@@ -1341,6 +1355,7 @@
+ #undef default_start
+ #undef default_stop
+ #undef description
++#undef interactive
+     return ret;
+ }
+@@ -1503,6 +1518,7 @@
+     regfree(&reg.def_start);
+     regfree(&reg.def_stop);
+     regfree(&reg.desc);
++    regfree(&reg.interact);
+ }
+ static struct {
+@@ -1781,6 +1797,9 @@
+               if (script_inf.stop_after && script_inf.stop_after != empty) {
+                   reversereq(service, REQ_SHLD|REQ_KILL, script_inf.stop_after);
+               }
++              if (script_inf.interactive && 0 == strcmp(script_inf.interactive, "true")) {
++                  service->attr.flags |= SERV_INTRACT;
++              }
+           }
+           if (name) 
+@@ -2881,6 +2900,9 @@
+                       if (script_inf.should_stop && script_inf.should_stop != empty) {
+                           rememberreq(service, REQ_SHLD|REQ_KILL, script_inf.should_stop);
+                       }
++                      if (script_inf.interactive && 0 == strcmp(script_inf.interactive, "true")) {
++                          service->attr.flags |= SERV_INTRACT;
++                      }
+                   }
+                   if (script_inf.start_before && script_inf.start_before != empty) {
diff --git a/packaging/62_upstart_job.patch b/packaging/62_upstart_job.patch
new file mode 100644 (file)
index 0000000..2c0570e
--- /dev/null
@@ -0,0 +1,170 @@
+Purpose: Add support for upstart jobs.
+Fixes:   #547235
+Status:  Work in progress, not submitted upstream yet.
+---
+
+Index: insserv/insserv.8.in
+===================================================================
+--- insserv.orig/insserv.8.in  2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.8.in       2009-09-26 22:35:42.000000000 +0200
+@@ -266,6 +266,10 @@
+ .BR \-f ,\  \-\-force
+ Ignore if a required service is missed.
+ .TP
++.BR \-u\ <path> ,\  \-\-upstart-job\ <path>
++Path to replace existing upstart job path.  (default path is
++.IR /lib/init/upstart-job ).
++.TP
+ .BR \-h ,\  \-\-help
+ Print out short usage message.
+ .PP
+@@ -339,6 +343,12 @@
+ name as the boot or init script in the directory
+ .IR /etc/insserv/overrides/ .
+ .\"
++.SH UPSTART JOB COMPATIBILITY
++To allow upstart jobs to work as init.d scripts, insserv will
++recognize a symlink from path/to/init.d/script to
++/lib/init/upstart-job as upstart jobs, and instead of reading the
++header from the file will run the script with the argument lsb-header
++to get the script header.
+ .SH EXIT CODES
+ The exit codes have the following conditions:
+ .RS 7
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:43.000000000 +0200
+@@ -70,6 +70,8 @@
+ # define INSCONF      "/etc/insserv.conf"
+ #endif
++const char *upstartjob_path = "/lib/init/upstart-job";
++
+ /*
+  * For a description of regular expressions see regex(7).
+  */
+@@ -1154,6 +1156,43 @@
+     xreset(script_inf.interactive);
+ }
++static char *is_upstart_job_recursive(const char *path,
++                                    const char *basenamestr)
++{
++    struct stat statbuf;
++    if (-1 == lstat(path, &statbuf)) {
++      return 0;
++    }
++    if (S_ISLNK(statbuf.st_mode)) {
++        char buf[2048];
++        int len = readlink(path, buf, sizeof(buf)-1);
++      if (0 < len) {
++          buf[len] = '\0';
++          if (0 == strcmp(buf, upstartjob_path)) {
++            /* upstart job, return base name of original symlink */
++            return strdup(basenamestr);
++          } else
++            return is_upstart_job_recursive(buf, basenamestr);
++      }
++    }
++    return 0;
++}
++
++/*
++ * return name of upstart job if the script is a symlink to
++ * /lib/init/upstart-job, or NULL if path do not point to an
++ * upstart job.
++ */
++static char* is_upstart_job(const char *path)
++{
++
++    char *basenamestr = basename(path); /* GNU basename */
++    char *retval = is_upstart_job_recursive(path, basenamestr);
++    if (retval)
++        info("script '%s' is upstart job\n", basenamestr);
++    return retval;
++}
++
+ #define FOUND_LSB_HEADER   0x01
+ #define FOUND_LSB_DEFAULT  0x02
+ #define FOUND_LSB_OVERRIDE 0x04
+@@ -1170,7 +1209,8 @@
+     char *pbuf = buf;
+     FILE *script;
+     uchar ret = 0;
+-    int fd;
++    int fd = -1;
++    char *upstart_job = NULL;
+ #define provides      script_inf.provides
+ #define required_start        script_inf.required_start
+@@ -1186,12 +1226,23 @@
+     info("Loading %s\n", path);
+-    if ((fd = xopen(dfd, path, o_flags)) < 0 || (script = fdopen(fd, "r")) == (FILE*)0)
+-      error("fopen(%s): %s\n", path, strerror(errno));
++    if (NULL != (upstart_job = is_upstart_job(path))) {
++        char cmd[2048];
++      int len;
++      len = snprintf(cmd, sizeof(cmd),
++                     "%s %s lsb-header", upstartjob_path, upstart_job);
++      if (len < 0 || sizeof(cmd) == len)
++          error("snprintf: insufficient buffer for %s\n", path);
++      if ((FILE*)0 == (script = popen(cmd, "r")))
++          error("popen(%s): %s\n", path, strerror(errno));
++    } else {
++        if ((fd = xopen(dfd, path, o_flags)) < 0 || (script = fdopen(fd, "r")) == (FILE*)0)
++          error("fopen(%s): %s\n", path, strerror(errno));
+ #if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
+-    (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
++      (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ #endif
++    }
+ #define COMMON_ARGS   buf, SUBNUM, subloc, 0
+ #define COMMON_SHD_ARGS       buf, SUBNUM_SHD, subloc, 0
+@@ -1303,7 +1354,12 @@
+       (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
+ #endif
+-    fclose(script);
++    if (upstart_job) {
++        pclose(script);
++        free(upstart_job);
++        upstart_job = 0;
++    } else
++        fclose(script);
+     if (begin && end)
+       ret |= FOUND_LSB_HEADER;
+@@ -2224,6 +2280,7 @@
+     {"force", 0, (int*)0, 'f'},
+     {"path",  1, (int*)0, 'p'},
+     {"override",1, (int*)0, 'o'},
++    {"upstart-job",1, (int*)0, 'u'},
+     {"help",  0, (int*)0, 'h'},
+     { 0,      0, (int*)0,  0 },
+ };
+@@ -2277,7 +2334,7 @@
+     for (c = 0; c < argc; c++)
+       argr[c] = (char*)0;
+-    while ((c = getopt_long(argc, argv, "c:dfrhvno:p:", long_options, (int *)0)) != -1) {
++    while ((c = getopt_long(argc, argv, "c:dfrhvno:p:u:", long_options, (int *)0)) != -1) {
+       size_t l;
+       switch (c) {
+           case 'c':
+@@ -2317,6 +2374,11 @@
+               override_path = optarg;
+               set_override = true;
+               break;
++          case 'u':
++              if (optarg == (char*)0 || *optarg == '\0')
++                  goto err;
++              upstartjob_path = optarg;
++              break;
+           case '?':
+           err:
+               error("For help use: %s -h\n", myname);
diff --git a/packaging/70_req_start_all_depends.patch b/packaging/70_req_start_all_depends.patch
new file mode 100644 (file)
index 0000000..2144003
--- /dev/null
@@ -0,0 +1,30 @@
+Purpose: Correct dependency information written to .depend.* files
+         for scripts which declare Required-Start: $all
+Fixes:   nil
+Status:  Applied upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:42.000000000 +0200
+@@ -776,9 +776,6 @@
+           continue;
+ #endif /* not MINIMAL_RULES */
+-      if (list_empty(&serv->sort.req))
+-          continue;
+-
+       if (serv->start->lvl & LVL_BOOT)
+           out = boot;
+       else
+@@ -820,6 +817,10 @@
+               fprintf(out, " %s", name);
+           }
+       } else {
++
++          if (list_empty(&serv->sort.req))
++              continue;
++
+           np_list_for_each(pos, &serv->sort.req) {
+               req_t * req = getreq(pos);
+               service_t * dep = req->serv;
diff --git a/packaging/71_complete_makefile.patch b/packaging/71_complete_makefile.patch
new file mode 100644 (file)
index 0000000..7b13a54
--- /dev/null
@@ -0,0 +1,56 @@
+Purpose: Make sure the .depend.* files have complete dependencies when
+         recursive virtual facilities are used.
+Fixes:   #534526
+Status:  From upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:42.000000000 +0200
+@@ -2109,33 +2109,26 @@
+           goto out;
+       }
+-      if ((*deep)++ > 10) {
+-          warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
+-          goto out;
+-      }
+-
+       list_for_each_safe(tmp, safe, ptr) {
+           repl_t * rnxt = getrepl(tmp);
+           if (*rnxt->r[0].name == '$') {
+-              expand_faci(tmp, head, deep);
+-          } else {
+-              if (*deep == 1) {
+-                  if (--(*rent->r[0].ref) <= 0)
+-                      free(rent->r[0].ref);
+-                  rent->r[0] = rnxt->r[0];
+-                  ++(*rent->r[0].ref);
+-              } else {
+-                  repl_t *restrict subst;
+-                  if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+-                      error("%s", strerror(errno));
+-                  insert(&subst->r_list, head);
+-                  subst->r[0] = rnxt->r[0];
+-                  ++(*subst->r[0].ref);
++              if (*deep > 10) {
++                  warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
++                  goto out;
+               }
++              (*deep)++;
++              expand_faci(tmp, head, deep);
++              (*deep)--;
++          } else if (*deep > 0) {
++              repl_t *restrict subst;
++              if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
++                  error("%s", strerror(errno));
++              insert(&subst->r_list, head->prev);
++              subst->r[0] = rnxt->r[0];
++              (*subst->r[0].ref) = 1;
+           }
+       }
+ out:
+-      (*deep)--;
+       return;
+ }
diff --git a/packaging/81_lessverbose.patch b/packaging/81_lessverbose.patch
new file mode 100644 (file)
index 0000000..e8ed476
--- /dev/null
@@ -0,0 +1,157 @@
+Purpose: Reduce verbosity level (drop Loading... messages)
+Fixes:   -
+Status:  Not yet submitted upstream.
+---
+
+Index: insserv/listing.h
+===================================================================
+--- insserv.orig/listing.h     2009-09-26 22:35:25.000000000 +0200
++++ insserv/listing.h  2009-09-26 22:35:39.000000000 +0200
+@@ -283,7 +283,7 @@
+ extern const char *const delimeter;
+ extern void error(const char *restrict fmt, ...) attribute((noreturn,format(printf,1,2)));
+ extern void warn (const char *restrict fmt, ...) attribute((format(printf,1,2)));
+-extern void info (const char *restrict fmt, ...) attribute((format(printf,1,2)));
++extern void info (int level, const char *restrict fmt, ...) attribute((format(printf,2,3)));
+ extern inline int map_has_runlevels(void) attribute((always_inline));
+ extern inline char map_runlevel_to_key(const int runlevel);
+ extern inline ushort map_key_to_lvl(const char key);
+@@ -312,23 +312,23 @@
+       (unlinkat(d,x,0) != 0 && (errno != EISDIR || unlinkat(d,x,AT_REMOVEDIR) != 0)))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+       else \
+-      info("remove service %s/%s%s\n", path, rcd, x); }))
++      info(1, "remove service %s/%s%s\n", path, rcd, x); }))
+ #else
+ # define xremove(d,x) (__extension__ ({ if ((dryrun ? 0 : (remove(x) != 0))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+       else \
+-      info("remove service %s/%s%s\n", path, rcd, x); }))
++      info(1, "remove service %s/%s%s\n", path, rcd, x); }))
+ #endif
+ #if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE)
+ # define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlinkat(x, d, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+-      info("enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
++      info(1, "enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+ #else
+ # define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlink(x, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+-      info("enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
++      info(1, "enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+ #endif
+ #if defined(HAS_fstatat) && defined(_ATFILE_SOURCE)
+ # define xstat(d,x,s) (__extension__ ({ fstatat(d,x,s, 0); }))
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:41.000000000 +0200
+@@ -114,8 +114,8 @@
+ /* The main line buffer if unique */
+ static char buf[LINE_MAX];
+-/* When to be verbose */
+-static boolean verbose = false;
++/* When to be verbose, and what level of verbosity */
++static int verbose = 0;
+ /* When to be verbose */
+ static boolean dryrun = false;
+@@ -690,9 +690,9 @@
+     if (dryrun) {
+ #ifdef USE_KILL_IN_BOOT
+-      info("dryrun, not creating .depend.boot, .depend.start, .depend.halt, and .depend.stop\n");
++      info(1, "dryrun, not creating .depend.boot, .depend.start, .depend.halt, and .depend.stop\n");
+ #else  /* not USE_KILL_IN_BOOT */
+-      info("dryrun, not creating .depend.boot, .depend.start, and .depend.stop\n");
++      info(1, "dryrun, not creating .depend.boot, .depend.start, and .depend.stop\n");
+ #endif /* not USE_KILL_IN_BOOT */
+       return;
+     }
+@@ -707,8 +707,8 @@
+       return;
+     }
+-    info("creating .depend.boot\n");
+-    info("creating .depend.start\n");
++    info(1, "creating .depend.boot\n");
++    info(1, "creating .depend.start\n");
+     lsort('S');                                       /* Sort into start order, set new sorder */
+@@ -874,9 +874,9 @@
+       return;
+     }
+-    info("creating .depend.halt\n");
++    info(1, "creating .depend.halt\n");
+ #endif /* USE_KILL_IN_BOOT */
+-    info("creating .depend.stop\n");
++    info(1, "creating .depend.stop\n");
+     lsort('K');                                       /* Sort into stop order, set new korder */
+@@ -1014,9 +1014,9 @@
+ /*
+  * Print message when verbose is enabled
+  */
+-void info(const char *fmt, ...) {
++void info(int level, const char *fmt, ...) {
+     va_list ap;
+-    if (!verbose)
++    if (level > verbose)
+       goto out;
+     va_start(ap, fmt);
+     _logger(fmt, ap);
+@@ -1062,7 +1062,7 @@
+     if (stat(rcpath, &st) < 0) {
+       if (errno == ENOENT) {
+-          info("creating directory '%s'\n", rcpath);
++          info(1, "creating directory '%s'\n", rcpath);
+           if (!dryrun)
+               mkdir(rcpath, (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH));
+       } else
+@@ -1190,7 +1190,7 @@
+     char *basenamestr = basename(path); /* GNU basename */
+     char *retval = is_upstart_job_recursive(path, basenamestr);
+     if (retval)
+-        info("script '%s' is upstart job\n", basenamestr);
++        info(2, "script '%s' is upstart job\n", basenamestr);
+     return retval;
+ }
+@@ -1225,7 +1225,7 @@
+ #define description   script_inf.description
+ #define interactive   script_inf.interactive
+-    info("Loading %s\n", path);
++    info(2, "Loading %s\n", path);
+     if (NULL != (upstart_job = is_upstart_job(path))) {
+         char cmd[2048];
+@@ -1882,7 +1882,7 @@
+     regmatch_t subloc[SUBCONFNUM], *val = (regmatch_t*)0;
+     FILE *conf;
+-    info("Loading %s\n", file);
++    info(2, "Loading %s\n", file);
+     do {
+       const char * fptr = file;
+@@ -2347,10 +2347,10 @@
+               ignore = true;
+               break;
+           case 'v':
+-              verbose = true;
++              verbose ++;
+               break;
+           case 'n':
+-              verbose = true;
++              verbose ++;
+               dryrun = true;
+               break;
+           case 'p':
diff --git a/packaging/82_loop_exit_msg.patch b/packaging/82_loop_exit_msg.patch
new file mode 100644 (file)
index 0000000..2c8dd66
--- /dev/null
@@ -0,0 +1,20 @@
+Purpose: Make message printed when loops are detected look more like
+         the messages printed when other errors are detected ("exiting
+         now!"), to make it easier for piuparts to discover these errors too.
+Fixes:   -
+Status:  Not yet submitted upstream.
+---
+
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:41.000000000 +0200
+@@ -3250,7 +3250,7 @@
+      */
+     follow_all();
+     if (is_loop_detected() && !ignore)
+-      error("exiting without changing boot order!\n");
++      error("exiting now without changing boot order!\n");
+     /*
+      * Be sure that interactive scripts are the only member of
diff --git a/packaging/91_kfreebsd_nofadvice.patch b/packaging/91_kfreebsd_nofadvice.patch
new file mode 100644 (file)
index 0000000..ec8a447
--- /dev/null
@@ -0,0 +1,22 @@
+Purpose: Get insserv building on kfreebsd, missing the argument values for posix_fadvise().
+Fixes:   #?
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:40.000000000 +0200
+@@ -40,6 +40,13 @@
+ #endif /* USE_RPMLIB */
+ #include "listing.h"
++#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
++/* kfreebsd fail to provide working posix_fadvise */
++#  ifndef POSIX_FADV_SEQUENTIAL
++#    define posix_fadvise(fd, off, len, adv)        (-1)
++#  endif
++#endif
++
+ #ifdef SUSE
+ # define DEFAULT_START_LVL    "3 5"
+ # define DEFAULT_STOP_LVL     "3 5"
diff --git a/packaging/92_m68k_alignment.patch b/packaging/92_m68k_alignment.patch
new file mode 100644 (file)
index 0000000..ef4fe3c
--- /dev/null
@@ -0,0 +1,20 @@
+Purpose: Get insserv building on m68k, dropping some problematic
+         alignments (error: requested alignment is not a power of 2)
+Fixes:   #493637
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:40.000000000 +0200
+@@ -131,6 +131,10 @@
+ static boolean set_override = false;
+ static boolean set_insconf = false;
++#ifdef __m68k__ /* Fix #493637 */
++#  define aligned(a)
++#endif
++
+ /* Search results points here */
+ typedef struct lsb_struct {
+     char *provides;
diff --git a/packaging/93_hurd_no_path_max.patch b/packaging/93_hurd_no_path_max.patch
new file mode 100644 (file)
index 0000000..bad0d1a
--- /dev/null
@@ -0,0 +1,19 @@
+Purpose: Try to get insserv building on hurd, by faking a PATH_MAX value.
+Status:  Not yet submitted upstream.
+---
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:40.000000000 +0200
+@@ -1427,6 +1427,11 @@
+     return ret;
+ }
++#ifndef PATH_MAX
++/* for example hurd.  Should really dynamically aligh the buffer. */
++# define PATH_MAX 1024
++#endif
++
+ /*
+  * Follow symlinks, return the basename of the file pointed to by
+  * symlinks or the basename of the current path if no symlink.
diff --git a/packaging/94_v1_12_2.patch b/packaging/94_v1_12_2.patch
new file mode 100644 (file)
index 0000000..7b6c970
--- /dev/null
@@ -0,0 +1,82 @@
+Patch from upstream to detect and reject loops in virtual
+facilities (#541613) and warn about indirect dependencies to $all.
+
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:39.000000000 +0200
+@@ -233,6 +233,7 @@
+ typedef struct repl {
+     list_t     r_list;
+     string_t   r[1];
++    ushort    flags;
+ } __align repl_t;
+ #define getrepl(arg)  list_entry((arg), struct repl, r_list)
+@@ -1946,6 +1947,7 @@
+                               if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+                                   error("%s", strerror(errno));
+                               insert(&subst->r_list, r_list->prev);
++                              subst->flags = 0;
+                               r = &subst->r[0];
+                               if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
+                                   error("%s", strerror(errno));
+@@ -1975,6 +1977,7 @@
+                               error("%s", strerror(errno));
+                           insert(&subst->r_list, r_list->prev);
+                           r = &subst->r[0];
++                          subst->flags = 0;
+                           if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
+                               error("%s", strerror(errno));
+                           *r->ref = 1;
+@@ -2127,13 +2130,19 @@
+       list_for_each_safe(tmp, safe, ptr) {
+           repl_t * rnxt = getrepl(tmp);
++          if (rnxt->flags & 0x0001) {
++              error("Loop detected during expanding system facilities in the insserv.conf file(s): %s\n",
++                    rnxt->r[0].name);
++          }
+           if (*rnxt->r[0].name == '$') {
+               if (*deep > 10) {
+                   warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
+                   goto out;
+               }
+               (*deep)++;
++              rnxt->flags |= 0x0001;
+               expand_faci(tmp, head, deep);
++              rnxt->flags &= ~0x0001;
+               (*deep)--;
+           } else if (*deep > 0) {
+               repl_t *restrict subst;
+@@ -2154,9 +2163,12 @@
+     list_for_each(ptr, sysfaci_start) {
+       list_t * rlist, * safe, * head = &getfaci(ptr)->replace;
+       list_for_each_safe(rlist, safe, head) {
+-          if (*getrepl(rlist)->r[0].name == '$') {
++          repl_t * tmp = getrepl(rlist);
++          if (*tmp->r[0].name == '$') {
+               int deep = 0;
++              tmp->flags |= 0x0001;
+               expand_faci(rlist, rlist, &deep);
++              tmp->flags &= ~0x0001;
+           }
+       }
+     }
+Index: insserv/listing.c
+===================================================================
+--- insserv.orig/listing.c     2009-09-26 22:35:24.000000000 +0200
++++ insserv/listing.c  2009-09-26 22:35:39.000000000 +0200
+@@ -398,6 +398,12 @@
+               break;                          /* Loop detected, stop recursion */
+           }
++          if ((mode == 'S') && (attof(tmp)->flags & SERV_ALL)) {
++              warn("%s depends on %s and therefore on system facility `$all' which can not be true!\n",
++                   target->script ? target->script : target->name, tmp->script ? tmp->script : tmp->name);
++              continue;
++          }
++
+           if (ptrg->deep >= deep)             /* Nothing new */
+               continue;
+                                               /* The inner recursion */
diff --git a/packaging/95_stop_all.patch b/packaging/95_stop_all.patch
new file mode 100644 (file)
index 0000000..d78eb41
--- /dev/null
@@ -0,0 +1,159 @@
+Patch from upstream making $all work for stop sequences, placing
+scripts first in the stop sequence.  This patch invalidates
+60_all_keyword_start_only.patch
+
+Fixes #542043
+
+Index: insserv/insserv.c
+===================================================================
+--- insserv.orig/insserv.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/insserv.c  2009-09-26 22:35:39.000000000 +0200
+@@ -308,7 +308,10 @@
+           break;
+       case '$':
+           if (strcasecmp(token, "$all") == 0) {
+-              serv->attr.flags |= SERV_ALL;
++              if (bit & REQ_KILL)
++                  serv->attr.flags |= SERV_FIRST;
++              else
++                  serv->attr.flags |= SERV_ALL;
+               break;
+           }
+           /* Expand the `$' token recursively down */
+@@ -630,8 +633,7 @@
+ }
+ /*
+- * Last but not least the `$all' scripts will be set to the
+- * end of the current start order.
++ * The `$all' scripts will be set to the end of the current start order.
+  */
+ static inline void all_script(void) attribute((always_inline));
+ static inline void all_script(void)
+@@ -688,6 +690,50 @@
+ }
+ /*
++ * Last but not least the `$all' scripts will be set to the
++ * beginning of the current stop order.
++ */
++static inline void first_script(void) attribute((always_inline));
++static inline void first_script(void)
++{
++    list_t * pos;
++
++    list_for_each(pos, s_start) {
++      service_t * serv = getservice(pos);
++      list_t * tmp;
++
++      if (serv->attr.flags & SERV_DUPLET)
++          continue;                   /* Duplet */
++
++      if (!(serv->attr.flags & SERV_FIRST))
++          continue;
++
++      if (serv->attr.script == (char*)0)
++          continue;
++
++      list_for_each(tmp, s_start) {
++          service_t * cur = getservice(tmp);
++
++          if (cur->attr.flags & SERV_DUPLET)
++              continue;               /* Duplet */
++
++          if ((serv->start->lvl & cur->start->lvl) == 0)
++              continue;
++
++          if (cur == serv)
++              continue;
++
++          if (cur->attr.flags & SERV_FIRST)
++              continue;
++
++          rememberreq(serv, REQ_SHLD|REQ_KILL, cur->name);
++      }
++
++      setorder(serv->attr.script, 'K', 1, false);
++    }
++}
++
++/*
+  * Make the dependency files
+  */
+ static inline void makedep(void) attribute((always_inline));
+@@ -3274,6 +3320,11 @@
+     nonlsb_script();
+     /*
++     * Move the `$all' stop scripts to the very beginning
++     */
++    first_script();
++
++    /*
+      * Now generate for all scripts the dependencies
+      */
+     follow_all();
+Index: insserv/listing.c
+===================================================================
+--- insserv.orig/listing.c     2009-09-26 22:35:39.000000000 +0200
++++ insserv/listing.c  2009-09-26 22:35:39.000000000 +0200
+@@ -317,6 +317,7 @@
+     }
+     for (tmp = dir; tmp; tmp = getnextlink(l_list)) {
++      const typeof(attof(tmp)->flags) sflags = attof(tmp)->flags;
+       register boolean recursion = true;
+       handle_t * ptmp = (mode == 'K') ? &tmp->stopp : &tmp->start;
+       uchar  * order = &ptmp->deep;
+@@ -381,6 +382,7 @@
+       np_list_for_each(dent, l_list) {
+           dir_t * target = getlink(dent)->target;
+           handle_t * ptrg = (mode == 'K') ? &target->stopp : &target->start;
++          const typeof(attof(target)->flags) kflags = attof(target)->flags;
+           if ((peg->run.lvl & ptrg->run.lvl) == 0)
+               continue;                       /* Not same boot level */
+@@ -398,10 +400,18 @@
+               break;                          /* Loop detected, stop recursion */
+           }
+-          if ((mode == 'S') && (attof(tmp)->flags & SERV_ALL)) {
+-              warn("%s depends on %s and therefore on system facility `$all' which can not be true!\n",
+-                   target->script ? target->script : target->name, tmp->script ? tmp->script : tmp->name);
+-              continue;
++          if (mode == 'K') {
++              if (kflags & SERV_FIRST) {
++                  warn("Stopping %s depends on %s and therefore on system facility `$all' which can not be true!\n",
++                       tmp->script ? tmp->script : tmp->name, target->script ? target->script : target->name);
++                  continue;
++              }
++          } else {
++              if (sflags & SERV_ALL) {
++                  warn("Starting %s depends on %s and therefore on system facility `$all' which can not be true!\n",
++                       target->script ? target->script : target->name, tmp->script ? tmp->script : tmp->name);
++                  continue;
++              }
+           }
+           if (ptrg->deep >= deep)             /* Nothing new */
+@@ -847,7 +857,7 @@
+     list_for_each(tmp, d_start) {
+       maxorder = &maxstart;
+       guess_order(getdir(tmp), 'S');
+-      maxorder = &maxstart;
++      maxorder = &maxstop;
+       guess_order(getdir(tmp), 'K');
+     }
+ }
+Index: insserv/listing.h
+===================================================================
+--- insserv.orig/listing.h     2009-09-26 22:35:39.000000000 +0200
++++ insserv/listing.h  2009-09-26 22:35:39.000000000 +0200
+@@ -368,6 +368,7 @@
+ #define SERV_SCRIPT   0x0080
+ #define SERV_NOSTOP   0x0100
+ #define SERV_CMDLINE  0x0200
++#define SERV_FIRST    0x0400
+ /*
+  * Bits of the runlevels
diff --git a/packaging/96_hurd_no_at_funcs.patch b/packaging/96_hurd_no_at_funcs.patch
new file mode 100644 (file)
index 0000000..bcf2e75
--- /dev/null
@@ -0,0 +1,50 @@
+Purpose: Try to get insserv building on hurd, by avoiding the dummy *at
+         functions which exist in libc but always return an error.
+Status:  Not yet submitted upstream.
+
+---
+Index: insserv/listing.h
+===================================================================
+--- insserv.orig/listing.h     2009-09-27 15:45:38.000000000 +0200
++++ insserv/listing.h  2009-09-27 15:45:38.000000000 +0200
+@@ -307,7 +307,7 @@
+ #define xreset(ptr)   \
+       {char *restrict tmp = (char *restrict)ptr; if (ptr && *tmp) free(ptr);} ptr = NULL
+-#if defined(HAS_unlinkat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_unlinkat) && defined(_ATFILE_SOURCE) && !defined(__stub_unlinkat)
+ # define xremove(d,x) (__extension__ ({ if ((dryrun ? 0 : \
+       (unlinkat(d,x,0) != 0 && (errno != EISDIR || unlinkat(d,x,AT_REMOVEDIR) != 0)))) \
+       warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
+@@ -319,7 +319,7 @@
+       else \
+       info(1, "remove service %s/%s%s\n", path, rcd, x); }))
+ #endif
+-#if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_symlinkat) && defined(_ATFILE_SOURCE) && !defined(__stub_symlinkat)
+ # define xsymlink(d,x,y) (__extension__ ({ if ((dryrun ? 0 : (symlinkat(x, d, y) != 0))) \
+       warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
+       else \
+@@ -330,19 +330,19 @@
+       else \
+       info(1, "enable service %s -> %s/%s%s\n", x, path, rcd, y); }))
+ #endif
+-#if defined(HAS_fstatat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_fstatat) && defined(_ATFILE_SOURCE) && !defined(__stub_fstatat)
+ # define xstat(d,x,s) (__extension__ ({ fstatat(d,x,s, 0); }))
+ # define xlstat(d,x,s)        (__extension__ ({ fstatat(d,x,s, AT_SYMLINK_NOFOLLOW); }))
+ #else
+ # define xstat(d,x,s) (__extension__ ({ stat(x,s); }))
+ # define xlstat(d,x,s)        (__extension__ ({ lstat(x,s); }))
+ #endif
+-#if defined(HAS_readlinkat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_readlinkat) && defined(_ATFILE_SOURCE) && !defined(__stub_readlinkat)
+ # define xreadlink(d,x,b,l)   (__extension__ ({ readlinkat(d,x,b,l); }))
+ #else
+ # define xreadlink(d,x,b,l)   (__extension__ ({ readlink(x,b,l); }))
+ #endif
+-#if defined(HAS_openat) && defined(_ATFILE_SOURCE)
++#if defined(HAS_openat) && defined(_ATFILE_SOURCE) && !defined(__stub_openat)
+ # define xopen(d,x,f) (__extension__ ({ openat(d,x,f); }))
+ #else
+ # define xopen(d,x,f) (__extension__ ({ open(x,f); }))
diff --git a/packaging/bash-completion b/packaging/bash-completion
new file mode 100644 (file)
index 0000000..68c0ef3
--- /dev/null
@@ -0,0 +1,36 @@
+# insserv(8) completion
+#
+# Copyright (c) 2009 Kel Modderman <kel@otaku42.de>
+#
+
+have insserv &&
+_insserv()
+{
+    local cur prev sysvdir services options
+
+    cur=`_get_cword`
+    prev=${COMP_WORDS[COMP_CWORD-1]}
+
+    [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d \
+       || sysvdir=/etc/init.d
+
+    services=( $(echo $sysvdir/!(README*|*.dpkg*|*.rpm@(orig|new|save))) )
+    services=( ${services[@]#$sysvdir/} )
+    options=( -c --config -d -f -n -o --override -p --path -r -v )
+
+    case "$prev" in
+       -c|--config)
+           _filedir
+           ;;
+       -o|--override|-p|--path)
+           _filedir -d
+           ;;
+       *)
+           COMPREPLY=( $( compgen -W '${options[@]} ${services[@]}' -- \
+               $cur ) )
+           ;;
+    esac
+
+    return 0
+} &&
+complete -F _insserv insserv
diff --git a/packaging/check-archive-initd-scripts b/packaging/check-archive-initd-scripts
new file mode 100644 (file)
index 0000000..343a718
--- /dev/null
@@ -0,0 +1,247 @@
+#!/usr/bin/perl
+#
+# Check the consistency of all init.d scripts in the archive.  Run
+# this on bellini.debian.org.
+
+use warnings;
+use strict;
+use File::Basename;
+
+my $warn = 1;
+
+my $basedir = "/org/lintian.debian.org/laboratory/binary";
+
+my @scripts = @ARGV;
+@scripts = <$basedir/*/init.d/*> unless (@scripts);
+
+my %scriptinfo;
+my %provides;
+
+my @virts = qw($local_fs $remote_fs $syslog $time $named
+               $portmap $network $all
+               $mail-transport-agent $x-font-server
+               );
+my @harddepheaders = qw(required-start required-stop);
+my @softdepheaders = qw(should-start
+                    should-stop x-start-before x-stop-after);
+my $lsbheaders = "Provides|Required-Start|Required-Stop|Default-Start|Default-Stop";
+my $optheaders = "x-start-before|x-stop-after|should-start|should-stop";
+
+for my $virt (@virts) {
+    $provides{$virt} = ['insserv/etc/insserv.conf'];
+}
+
+# Ignore obsolete scripts, as these are unlikely to cause problems.
+for my $old (qw(glibc evms raid2 ldm sdm)) {
+    $provides{$old} = ['obsolete'];
+}
+
+# First pass to load the database
+for my $initdscript (@scripts) {
+    next if $initdscript =~ m%/rc|/rcS|/README%;
+    my %lsbinfo = parse_lsb_header($initdscript);
+    $scriptinfo{$initdscript} = \%lsbinfo;
+    next unless ($lsbinfo{'found'});
+
+    my %checked;
+    for my $provide (split(/[ ,\t]+/, $lsbinfo{provides})) {
+        if (exists $provides{$provide}) {
+            push(@{$provides{$provide}}, $initdscript)
+        } else {
+            $provides{$provide} = [$initdscript];
+        }
+        $checked{$provide} = 1;
+    }
+}
+
+for my $provide (sort keys %provides) {
+    if (1 < scalar @{$provides{$provide}}) {
+        my %script;
+        map { $script{basename($_)} = 1; } @{$provides{$provide}};
+        if (1 < scalar keys %script) {
+            error(sprintf("scripts %s provide duplicate '%s'",
+                          join(",", short_name(@{$provides{$provide}})),
+                          $provide));
+        }
+    }
+}
+
+# Second pass, to see which dependencies are missing
+for my $initdscript (@scripts) {
+    next unless ($scriptinfo{$initdscript}->{'found'});
+    my $short = short_name($initdscript);
+    my %checked;
+    my @hardmissing = ();
+    for my $header (@harddepheaders) {
+        my $list = $scriptinfo{$initdscript}->{$header};
+        next unless defined $list;
+        for my $facility (split(/[ ,\t]+/, $list)) {
+            next if exists $checked{$facility};
+            $checked{$facility} = 1;
+            push(@hardmissing, $facility)
+                unless exists $provides{$facility};
+        }
+    }
+    error("script $short depend on non-existing provides: "
+          . join(" ", @hardmissing)) if (@hardmissing);
+    my @softmissing = ();
+    for my $header (@softdepheaders) {
+        my $list = $scriptinfo{$initdscript}->{$header};
+        next unless defined $list;
+        for my $facility (split(/[ ,\t]+/, $list)) {
+            next if exists $checked{$facility};
+            $checked{$facility} = 1;
+            push(@softmissing, $facility)
+                unless exists $provides{$facility};
+        }
+    }
+    warning("script $short relate to non-existing provides: "
+            . join(" ", @softmissing)) if (@softmissing);
+
+    if (exists $checked{'$syslog'}
+        && $scriptinfo{$initdscript}->{'default-start'} =~ m/s/i) {
+        error("script $short depend on \$syslog and start from rcS.d/");
+    }
+    if (!exists $checked{'$remote_fs'}
+        && !exists $checked{'$syslog'}
+        && $scriptinfo{$initdscript}->{'need_remove_fs'}
+        && $scriptinfo{$initdscript}->{'default-start'} =~ m/s/i) {
+        warning("script $short possibly missing dependency on \$remote_fs");
+    } elsif (!exists $checked{'$local_fs'}
+             && !exists $checked{'$remote_fs'}
+             && !exists $checked{'$syslog'}
+             && $scriptinfo{$initdscript}->{'need_local_fs'}
+             && $scriptinfo{$initdscript}->{'default-start'} =~ m/s/i) {
+        warning("script $short possibly missing dependency on \$local_fs");
+    }
+
+    my %provided;
+    for my $provide (split(/[ ,\t]+/,
+                           $scriptinfo{$initdscript}->{provides})) {
+        $provided{$provide} = 1;
+        if ($provide =~ m/\$/) {
+            error("script $short provide virtual facility $provide");
+        }
+    }
+
+    my $basename = basename($initdscript, ".sh");
+    warning("script $short does not provide its own name")
+        unless exists $provided{$basename};
+
+    # Detect common problems with runlevel settings.
+    my @startrl = sort split(/\s+/, lc($scriptinfo{$initdscript}->{'default-start'}));
+    my @stoprl = sort split(/\s+/, lc($scriptinfo{$initdscript}->{'default-stop'}));
+
+    # Scripts starting in rcS.d/ normally do not stop or only stop
+    # during hald and shutdown.
+    if ((array_equal(['s'], \@startrl) && array_equal([], \@stoprl))
+        || ( array_equal(['s'], \@startrl)
+             && array_equal(['0','6'], \@stoprl))) {
+        # OK
+    } else {
+        # Most scripts either start in rcS.d, or in runlevels 2-5
+        if (!array_equal(['2', '3', '4', '5'], \@startrl) &&
+            !array_equal(['s'], \@startrl) &&
+            (!array_equal([], \@startrl) && @stoprl)) {
+            warning("script $short does not start in the usual runlevels: ",
+                    join(" ", @startrl));
+        }
+
+        # And most scripts stop in runlevel (1) runlevels (0, 1, 6),
+        # only starts or only stops in (0) or (6).
+        if (!array_equal(['0', '1', '6'], \@stoprl) &&
+            !array_equal(['1'], \@stoprl) &&
+            !array_equal(['0', '6'], \@stoprl) &&
+            !(array_equal(['0'], \@stoprl) && !@startrl) &&
+            !(array_equal(['6'], \@stoprl) && !@startrl) &&
+            !(array_equal([], \@stoprl) && @startrl)) {
+            warning("script $short does not stop in the usual runlevels: ",
+                    join(" ", @stoprl));
+        }
+    }
+}
+
+exit 0;
+
+sub parse_lsb_header {
+    my $initdscript = shift;
+    my $short = short_name($initdscript);
+    my %lsbinfo;
+    unless (open(INIT, "<", $initdscript)) {
+        error("script $short is unreadable");
+        return ();
+    }
+    my $inheader = 0;
+    while (<INIT>) {
+#        print;
+        chomp;
+        if (m/^\#\#\# BEGIN INIT INFO\s*$/) {
+            $lsbinfo{'found'} = 1;
+            $inheader = 1;
+        }
+        $inheader = 0 if (m/\#\#\# END INIT INFO$/);
+        if ($inheader
+            && m/^\# ($lsbheaders|$optheaders):\s*(\S?.*)$/i) {
+#            print "$1\n";
+            $lsbinfo{lc($1)} = $2;
+        }
+        s/\#.*$//; # Remove comments
+        $lsbinfo{'need_remove_fs'} = 1 if m%/usr/s?bin/%;
+        $lsbinfo{'need_local_fs'} = 1 if m%/var/%;
+
+        # Detect the use of tools resting in /usr/
+        $lsbinfo{'need_remove_fs'} = 1 if m%awk%;
+        $lsbinfo{'need_remove_fs'} = 1 if m%which%;
+    }
+    close(INIT);
+
+    # Check that all the required headers are present
+    if (!$lsbinfo{'found'}) {
+        error("script $short is missing LSB header");
+    } else {
+        for my $key (split(/\|/, lc($lsbheaders))) {
+            if (!exists $lsbinfo{$key}) {
+                error("script $short missing LSB keyword '$key'");
+            }
+        }
+    }
+    return %lsbinfo
+}
+
+sub short_name {
+    my @scripts;
+    for my $script ( @_ ) {
+        my $copy = $script;
+        $copy =~ s%$basedir/%%g;
+        push @scripts, $copy;
+    }
+    if (wantarray) {
+        return @scripts;
+    } else {
+        return $scripts[0];
+    }
+}
+
+sub array_equal {
+    my ($a1, $a2) = @_;
+    return 0 if (scalar @{$a1} != scalar @{$a2});
+
+    my $i = 0;
+    while ($i < scalar @{$a1}) {
+        return 0 if $a1->[$i] ne $a2->[$i];
+        $i++;
+    }
+    return 1;
+}
+
+sub info {
+    print "info: @_\n";
+}
+
+sub warning {
+    print "warning: @_\n" if $warn;
+}
+
+sub error {
+    print "error: @_\n";
+}
diff --git a/packaging/check-initd-order b/packaging/check-initd-order
new file mode 100644 (file)
index 0000000..e7d0ef6
--- /dev/null
@@ -0,0 +1,425 @@
+#!/usr/bin/perl
+#
+# Author: Petter Reinholdtsen
+# Date:   2005-08-21
+#
+# Read LSM init.d headers in SysV init.d scripts, and verify correct
+# start order for all runlevels.  It can also provide a graph.
+#
+# To generate a graph, run it like this
+#
+#   check-initd-order -g > initorder.dotty && dotty initorder.dotty
+
+use strict;
+use warnings;
+
+my $rcbase = "/etc";
+
+my $overridepath = "/usr/share/insserv/overrides";
+my $hostoverridepath =  "/etc/insserv/overrides";
+
+my $debug = 0;
+my $errors = 0;
+
+my %rcmap =
+    (
+     'B' => 'rc.boot',
+     'S' => 'rcS.d',
+     '1' => 'rc1.d',
+     '2' => 'rc2.d',
+     '3' => 'rc3.d',
+     '4' => 'rc4.d',
+     '5' => 'rc5.d',
+     '6' => 'rc6.d',
+     );
+
+my %sysmap;
+
+my %provideslist;
+my %scriptorder;
+my %opts;
+
+# Used to draw graphs
+my %gotrevdeps;
+my %allprovides;
+
+while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
+        shift @ARGV;
+        if (/^-([cdgko])$/) { $opts{$1}++; next }
+        if (/^-b$/) { $rcbase = shift; next }
+        if (/^-h|--help$/) { &usage; }
+        &usage("unknown option");
+}
+
+load_sysmap("$rcbase/insserv.conf");
+
+$debug = $opts{'d'};
+my $useoverrides = $opts{'o'} ? 0 : 1;
+
+if ($opts{'g'}) {
+    graph_generate();
+    exit 0;
+}
+
+check_bootorder();
+exit $errors > 0 ? 1 : 0;
+
+sub usage {
+    print STDERR "check-initd-order: error: @_\n" if ($#_ >= 0);
+    print STDERR <<EOF;
+usage: check-initd-order [-cdgko] [-b basedir]
+  -b basedir (default /etc)
+  -d enable debug output
+  -o do not load override files
+  -k use shutdown (reboot) sequence instead of boot sequence
+  -g generate graph
+  -c use combined boot and shutdown sequence (only for graphs)
+EOF
+    exit 1;
+}
+
+# Simple basename implementatin to avoid dependin on File::Basename
+# from perl-modules
+sub basename {
+    my $path = shift;
+    $path =~ s%^.*/([^/]+)$%$1%;
+    return $path;
+}
+
+sub error {
+    print STDERR "error: ", @_;
+    $errors++;
+}
+
+# Map packages to system metapackages.  These dependencies should
+# probably be more complex
+sub load_sysmap {
+    my $filename = shift;
+    unless (open(CONF, "<", "$filename")) {
+        print STDERR "error: unable to load $filename";
+        return;
+    }
+    while (<CONF>) {
+        chomp;
+        s/\#.*$//;
+        next if m/^\s*$/;
+        if (m/^(\$\S+)\s+(\S.*\S*)\S*$/) {
+            my $virt = $1;
+            for my $dep (split(/\s+/, $2)) {
+                $dep =~ s/^\+//g;
+                $sysmap{$dep} = $virt;
+            }
+        }
+    }
+    close(CONF);
+}
+
+sub graph_addnode {
+    my ($isstopseq, $lsbinforef) = @_;
+    my %lsbinfo = %{$lsbinforef};
+
+    unless ($lsbinfo{'provides'}) {
+        error "File ". $lsbinfo{'file'} . " is missing the provides header\n";
+        $lsbinfo{'provides'} = $lsbinfo{'file'};
+        $lsbinfo{'provides'} =~ s/^[SK]\d{2}//;
+    }
+
+    my $key = $opts{'k'} ? 'stop' : 'start';
+    my $revkey = $opts{'k'} ? 'stop-after' : 'start-before';
+    my @provides = split(/\s+/, $lsbinfo{'provides'});
+    for my $name (@provides) {
+        if (exists $sysmap{$name}) {
+            graph_addnode($isstopseq,
+                          {'provides'      => $sysmap{$name},
+                          "required-$key" => $name});
+        }
+    }
+
+    if (1 < @provides) {
+        my @providescopy = @provides;
+        my $lastprovide = shift @providescopy;
+        for my $provide (@providescopy) {
+            graph_addnode($isstopseq,
+                          {'provides'      => $lastprovide,
+                           "required-$key" => $provide});
+            graph_addnode($isstopseq,
+                          {'provides'      => $provide,
+                           "required-$key" => $lastprovide});
+        }
+    }
+
+    for my $provide (@provides) {
+        my $provideesc = $provide; $provideesc =~ s/"/\\"/g;
+        my %deps =
+            (
+             "required-$key" => 'blue',
+             "should-$key" => 'springgreen',
+             "$revkey" => 'yellow'
+             );
+
+        for $key (keys %deps) {
+            if (exists $lsbinfo{$key} && $lsbinfo{$key}) {
+                my @depends = split(/\s+/, $lsbinfo{$key});
+
+                my $dependonall = 0;
+                for my $pkg (@depends) {
+                    $dependonall = 1 if ($pkg eq '$all');
+                }
+
+                for my $pkg (@depends) {
+                    my $pkgesc = $pkg; $pkgesc =~ s/"/\\"/g;
+                    my $color = $deps{$key};
+                    if ($revkey eq $key) {
+                        print "\"$provideesc\" -> \"$pkgesc\"[color=$color] ;\n";
+                        $gotrevdeps{$pkg} = 1 unless $dependonall;
+                    } else {
+                        print "\"$pkgesc\" -> \"$provideesc\"[color=$color] ;\n";
+                        $gotrevdeps{$provide} = 1 unless $dependonall;
+                    }
+                }
+            }
+        }
+
+        print "\"$provideesc\" [shape=box];\n" unless $allprovides{$provide};
+        $allprovides{$provide} = 1;
+    }
+}
+
+sub graph_generate_mode {
+    my ($isstopseq) = @_;
+    my @dirs = $isstopseq ? $rcmap{6} : ($rcmap{S}, $rcmap{2});
+    for my $rcdir (@dirs) {
+        chdir "$rcbase/$rcdir/.";
+        my @scripts = $isstopseq ? <K*> : <S*>;
+        for my $script (@scripts) {
+            my $lsbinforef = load_lsb_tags("$rcbase/$rcdir/$script",
+                                           $useoverrides);
+
+            unless (defined $lsbinforef) {
+                error "LSB header missing in $rcbase/$rcdir/$script\n";
+                $script =~ s/^[SK]\d{2}//;
+                $lsbinforef = {'provides'       => $script,
+                               'required-start' => '$remote_fs $syslog',
+                               'required-stop'  => '$remote_fs $syslog'};
+            }
+            graph_addnode($isstopseq, $lsbinforef);
+        }
+    }
+    # Mark all packages without any reverse dependencies as depending
+    # on $all
+    for my $provide (keys %allprovides) {
+        next unless (exists $gotrevdeps{$provide});
+        my $lsbinforef = {'provides'       => '$all',
+                          'required-start' => "$provide",
+                          'required-stop'  => "$provide"};
+        graph_addnode($isstopseq, $lsbinforef);
+    }
+}
+
+sub graph_generate {
+    print "# Generating graph\n";
+    print <<EOF;
+digraph packages {
+rankdir=LR;
+concentrate=true;
+EOF
+    if ($opts{'c'}) {
+        graph_generate_mode();
+        graph_generate_mode(1);
+    } else {
+        graph_generate_mode($opts{'k'});
+    }
+    print <<EOF;
+}
+EOF
+}
+
+sub check_deps {
+    my ($lsbinforef, $tag, $order, $bootorder, $headername, $required) = @_;
+    my %lsbinfo = %{$lsbinforef};
+    my $name = $lsbinfo{'file'};
+    if ($lsbinfo{$headername}) {
+        my @depends = split(/\s+/, $lsbinfo{$headername});
+        for my $dep (@depends) {
+            if (! $required && exists $provideslist{$dep}) {
+                unless (exists $scriptorder{$tag}{$dep}
+                        and ("S" eq $tag
+                             ? $scriptorder{$tag}{$dep} < $bootorder
+                             : $scriptorder{$tag}{$dep} > $bootorder)) {
+                    my $deporder;
+                    if (exists $scriptorder{$tag}{$dep}) {
+                        $deporder = $scriptorder{$tag}{$dep}
+                    } else {
+                        $deporder = exists $provideslist{$dep} ? $provideslist{$dep} : "?";
+                    }
+                    error(sprintf("Incorrect order %s@%s %s %s%s\n",
+                           $dep, $deporder, 'S' eq $tag ? '>' : '<',
+                           $name, $order));
+                }
+            }
+        }
+    }
+}
+
+sub check_bootorder {
+    my $bootorder = 0;
+    my @dirs = $opts{'k'} ? $rcmap{6} : ($rcmap{S}, $rcmap{2});
+    my @scripts;
+    for my $rcdir (@dirs) {
+        push(@scripts, $opts{'k'} ? <$rcbase/$rcdir/K*> : <$rcbase/$rcdir/S*>);
+    }
+
+    if ($opts{'k'}) {
+        $scriptorder{'K'}{'$all'} = 1;
+    } else {
+        # Calculate script order for the script before the scripts
+        # with the last boot sequence number.
+        my $tmpbootorder = 0;
+        my $allorder = 0;
+        my $maxorder = 0;
+        my $maxbootorder = 0;
+        for my $scriptpath (@scripts) {
+            my $script = $scriptpath;
+            $script =~ s%^.*/([^/]+)$%$1%;
+            $tmpbootorder++;
+            my ($tag, $order, $name) = $script =~ m/^(.)(\d{2})(.+)$/;
+            if ($order > $maxorder) {
+                $allorder = $maxbootorder;
+                $maxbootorder = $tmpbootorder;
+                $maxorder = $order;
+            }
+
+            my $lsbinforef = load_lsb_tags($scriptpath,
+                                           $useoverrides);
+
+            if (exists $lsbinforef->{'provides'}
+                && $lsbinforef->{'provides'}) {
+                for my $provide (split(/\s+/, $lsbinforef->{'provides'})) {
+                    $provideslist{$provide} = $order;
+                }
+            } else {
+                $provideslist{$script} = $order;
+            }
+        }
+        $scriptorder{'S'}{'$all'} = $allorder;
+    }
+    for my $scriptpath (@scripts) {
+        my $script = $scriptpath;
+        $script =~ s%^.*/([^/]+)$%$1%;
+        $bootorder++;
+        my ($tag, $order, $name) = $script =~ m/^(.)(\d{2})(.+)$/;
+
+        $scriptorder{$tag}{$name} = $bootorder;
+        $scriptorder{$tag}{$sysmap{$name}} = $bootorder
+            if (exists $sysmap{$name});
+
+#           print "$script\n";
+#           print "T: $tag O: $order N: $name\n";
+        my $lsbinforef = load_lsb_tags($scriptpath,
+                                       $useoverrides);
+
+        unless (defined $lsbinforef) {
+            error "LSB header missing in $scriptpath\n";
+            next;
+        }
+        my %lsbinfo = %{$lsbinforef};
+
+        if (exists $lsbinfo{'provides'} && $lsbinfo{'provides'}) {
+            for my $provide (split(/\s+/, $lsbinfo{'provides'})) {
+                $scriptorder{$tag}{$provide} = $bootorder;
+                $scriptorder{$tag}{$sysmap{$provide}} = $bootorder
+                    if (exists $sysmap{$provide});
+            }
+        } else {
+            error "no LSB header provides value in script $scriptpath\n";
+        }
+
+        if ('S' eq $tag) {
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'required-start', 1);
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'should-start', 0);
+#            check_deps($lsbinforef, 'K', $order, $bootorder, 'start-before', 0);
+        }
+        if ('K' eq $tag) {
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'required-stop', 1);
+            check_deps($lsbinforef, $tag, $order, $bootorder, 'should-stop', 0);
+#            check_deps($lsbinforef, 'S', $order, $bootorder, 'stop-after', 0);
+        }
+    }
+}
+
+sub load_lsb_tags {
+    my ($initfile, $useoverrides) = @_;
+    my $lsbinforef = load_lsb_tags_from_file($initfile);
+
+    if ($useoverrides) {
+        # Try override file
+        $initfile = readlink($initfile) if (-l $initfile);
+        my $basename = basename($initfile);
+
+        # Only read shipped override file when initscript does not
+        # contain LSB tags.
+        if (! defined($lsbinforef) && -f "$overridepath/$basename") {
+            print STDERR "Override $overridepath/$basename\n" if $debug;
+            $lsbinforef = load_lsb_tags_from_file("$overridepath/$basename");
+        }
+
+        # Always read the host override in $hostoverridepath.
+        if (-f "$hostoverridepath/$basename") {
+            print STDERR "Override $hostoverridepath/$basename\n" if $debug;
+            $lsbinforef = load_lsb_tags_from_file("$hostoverridepath/$basename");
+        }
+
+    }
+    return $lsbinforef;
+}
+
+sub load_lsb_tags_from_file {
+    my ($file) = @_;
+    print STDERR "Loading $file\n" if $debug;
+    ### BEGIN INIT INFO
+    # Provides:          xdebconfigurator
+    # Required-Start:    $syslog
+    # Required-Stop:     $syslog
+    # Default-Start:     2 3 4 5
+    # Default-Stop:      1 6
+    # Short-Description: Genererate xfree86 configuration at boot time
+    # Description:       Preseed X configuration and use dexconf to
+    #                    genereate a new configuration file.
+    ### END INIT INFO
+    unless (open(FILE, "<$file")) {
+        warn "error: Unable to read $file";
+        return;
+    }
+    my $found = 0;
+    my ($provides, $requiredstart, $requiredstop, $shouldstart, $shouldstop);
+    my ($startbefore, $stopafter);
+    while (<FILE>) {
+        chomp;
+        $found = 1 if (m/\#\#\# BEGIN INIT INFO/);
+        next unless $found;
+        last if (m/\#\#\# END INIT INFO/);
+
+        $provides = $1      if (m/^\# provides:\s+(\S*.*\S+)\s*$/i);
+        $requiredstart = $1 if (m/^\# required-start:\s+(\S*.*\S+)\s*$/i);
+        $requiredstop = $1  if (m/^\# required-stop:\s+(\S*.*\S+)\s*$/i);
+        $shouldstart = $1   if (m/^\# should-start:\s+(\S*.*\S+)\s*$/i);
+        $shouldstop = $1    if (m/^\# should-stop:\s+(\S*.*\S+)\s*$/i);
+        $startbefore = $1   if (m/^\# X-Start-Before:\s+(\S*.*\S+)\s*$/i);
+        $stopafter = $1     if (m/^\# X-Stop-After:\s+(\S*.*\S+)\s*$/i);
+    }
+    close(FILE);
+
+    return undef unless ($found);
+
+#    print "Provides: $provides\n" if $provides;
+    return {
+            'provides'       => $provides,
+            'required-start' => $requiredstart,
+            'required-stop'  => $requiredstop,
+            'should-start'   => $shouldstart,
+            'should-stop'    => $shouldstop,
+            'start-before'   => $startbefore,
+            'stop-after'     => $stopafter,
+            'file'           => $file,
+            };
+}
diff --git a/packaging/devfsd b/packaging/devfsd
new file mode 100644 (file)
index 0000000..ed36858
--- /dev/null
@@ -0,0 +1,8 @@
+### BEGIN INIT INFO
+# Provides:          devfsd
+# Required-Start:    mountdevsubfs 
+# Required-Stop:     reboot
+# Default-Start:     S 1 2 3 4 5
+# Default-Stop:      0 6
+### END INIT INFO
+# Reported to BTS as bug #324671
diff --git a/packaging/hotplug b/packaging/hotplug
new file mode 100644 (file)
index 0000000..9e7b8d1
--- /dev/null
@@ -0,0 +1,7 @@
+### BEGIN INIT INFO
+# Provides:          hotplug
+# Required-Start:    mountdevsubfs checkroot $local_fs
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
diff --git a/packaging/hotplug-net b/packaging/hotplug-net
new file mode 100644 (file)
index 0000000..6f612d3
--- /dev/null
@@ -0,0 +1,7 @@
+### BEGIN INIT INFO
+# Provides:          hotplug-net
+# Required-Start:    $local_fs ifupdown
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:      0 6
+### END INIT INFO
diff --git a/packaging/initrd-tools.sh b/packaging/initrd-tools.sh
new file mode 100644 (file)
index 0000000..2f4a800
--- /dev/null
@@ -0,0 +1,7 @@
+### BEGIN INIT INFO
+# Provides:          initrd-tools
+# Required-Start:    mountdevsubfs
+# Required-Stop: 
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
diff --git a/packaging/insserv.spec b/packaging/insserv.spec
new file mode 100644 (file)
index 0000000..951c1a4
--- /dev/null
@@ -0,0 +1,109 @@
+Name: insserv
+License: GPL v2 or later
+Group: System/Base
+Provides: /sbin/insserv
+Version: 1.12.0
+Release: 1
+Summary: A Program to Arrange Initialization Scripts
+
+Source0: insserv-%{version}.tar.gz
+Source1: devfsd
+Source2: hotplug
+Source3: hotplug-net
+Source4: initrd-tools.sh
+Source5: modutils
+Source6: check-initd-order
+Source7: check-archive-initd-scripts
+Source8: seq-changes
+Source9: make-testsuite
+Source10: update-bootsystem-insserv
+Source11: update-rc.d-insserv
+Source12: bash-completion
+
+Patch0: 10_nosuse.patch
+Patch1: 11_debian_conf.patch
+Patch2: 20_install_perms_fixup.patch
+Patch3: 21_tests_suite_new_functions.patch
+Patch4: 30_deterministic_order.patch
+Patch5: 40_badboy_segfault.patch
+Patch6: 50_symlink_in_initddir.patch
+Patch7: 61_interactive_keyword.patch
+Patch8: 62_upstart_job.patch
+Patch9: 70_req_start_all_depends.patch 
+Patch10: 71_complete_makefile.patch
+Patch11: 81_lessverbose.patch
+Patch12: 82_loop_exit_msg.patch
+Patch13: 91_kfreebsd_nofadvice.patch
+Patch14: 92_m68k_alignment.patch
+Patch15: 93_hurd_no_path_max.patch
+Patch16: 94_v1_12_2.patch
+Patch17: 95_stop_all.patch
+Patch18: 96_hurd_no_at_funcs.patch
+
+%description
+Insserv enables an installed system init script (boot script) by
+reading the comment header of the script and calculating the
+dependencies between all scripts.
+
+
+%prep
+%setup
+
+%patch0 -p1 -b .10_nosuse
+%patch1 -p1 -b .11_debian_conf.patch
+%patch2 -p1 -b .20_install_perms_fixup.patch
+%patch3 -p1 -b .21_tests_suite_new_functions.patch
+%patch4 -p1 -b .30_deterministic_order.patch
+%patch5 -p1 -b .40_badboy_segfault.patch
+%patch6 -p1 -b .50_symlink_in_initddir.patch
+%patch7 -p1 -b .61_interactive_keyword.patch
+%patch8 -p1 -b .62_upstart_job.patch
+%patch9 -p1 -b .70_req_start_all_depends.patch
+%patch10 -p1 -b .71_complete_makefile.patch
+%patch11 -p1 -b .81_lessverbose.patch
+%patch12 -p1 -b .82_loop_exit_msg.patch
+%patch13 -p1 -b .91_kfreebsd_nofadvice.patch
+%patch14 -p1 -b .92_m68k_alignment.patch
+%patch15 -p1 -b .93_hurd_no_path_max.patch
+%patch16 -p1 -b .94_v1_12_2.patch
+%patch17 -p1 -b .95_stop_all.patch
+%patch18 -p1 -b .96_hurd_no_at_funcs.patch
+
+
+%build
+make INITDIR=%{_sysconfdir}/init.d INSCONF=%{_sysconfdir}/insserv.conf
+
+%install
+make install DESTDIR=%{buildroot}
+
+# Install overrides
+install -d %{buildroot}/%{_datadir}/%{name}/overrides/
+for src in %SOURCE1 %SOURCE2 %SOURCE3 %SOURCE4 %SOURCE5; do
+       install -m 644 $src %{buildroot}/%{_datadir}/%{name}/overrides/
+done
+
+# install
+for src in %SOURCE6 %SOURCE7 %SOURCE8 %SOURCE9; do
+       install $src %{buildroot}/%{_datadir}/%{name}/
+done
+
+install -d %{buildroot}/%{_sbindir}
+install %SOURCE10 %{buildroot}/%{_sbindir}/
+install %SOURCE11 %{buildroot}/%{_sbindir}/
+
+# Install bash(1) completion
+install -d %{buildroot}/%{_sysconfdir}/bash_completion.d
+install -m 644 %SOURCE12 %{buildroot}/%{_sysconfdir}/bash_completion.d/insserv
+
+install -d %{buildroot}/var/lib/update-rc.d %{buildroot}/%{_sysconfdir}/insserv.conf.d
+
+%files
+%defattr(-,root,root)
+%config %{_sysconfdir}/%{name}.conf
+/sbin/insserv
+%{_sbindir}/*
+%{_datadir}/%{name}/*
+%{_mandir}/man8/insserv.8.gz
+%dir /var/lib/update-rc.d
+%dir %{_sysconfdir}/insserv.conf.d
+%{_sysconfdir}/bash_completion.d/insserv
diff --git a/packaging/make-testsuite b/packaging/make-testsuite
new file mode 100644 (file)
index 0000000..c4aec47
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Extract key information from the current to try to generate a test
+# suite script to demonstrate detected bugs.
+
+echo "cat <<'EOF' > \$tmpdir\$insconf"
+grep -v '#' /etc/insserv.conf |grep -v '^$'
+echo "EOF"
+
+for f in /etc/init.d/*; do
+       name=$(basename $f)
+       case $name in
+           README|rc|rcS|skeleton)
+               ;;
+           *)
+               echo "addscript $name <<EOF"
+               sed -n -r '/^### BEGIN INIT INFO/, /END INIT INFO/p' < $f
+               echo "EOF"
+               echo
+               ;;
+       esac
+done
+
+cd /etc
+for f in rc?.d/*; do
+       case $f in
+           */README)
+               ;;
+           *)
+               echo ln -s $(readlink $f) $f
+               ;;
+       esac
+done
diff --git a/packaging/modutils b/packaging/modutils
new file mode 100644 (file)
index 0000000..dacdc4f
--- /dev/null
@@ -0,0 +1,8 @@
+### BEGIN INIT INFO
+# Provides:          modutils
+# Required-Start:    checkroot
+# Required-Stop:
+# Default-Start:     S
+# Default-Stop:
+### END INIT INFO
+# Reported to BTS as #335311
diff --git a/packaging/seq-changes b/packaging/seq-changes
new file mode 100644 (file)
index 0000000..4610bec
--- /dev/null
@@ -0,0 +1,54 @@
+#! /bin/bash
+# Script from Frans Pop
+
+set -e
+
+if [ -z "$1" ]; then
+       echo "Usage: insserv-seq-changes /var/lib/insserv/<old bootscripts tarball>"
+       exit 1
+fi
+
+oldtar="$(tar tzf $1)"
+for i in S $(seq 0 6); do
+       echo "Runlevel $i"
+       new="$(cd /etc/rc$i.d; ls -1 [KS]* | sort | nl)"
+       old="$(echo "$oldtar" | grep "^rc$i.d/[KS]" | cut -d/ -f2 | sort | nl)"
+       case $i in
+           S|0|6)
+               old="$(echo "$old" | sed -r "s/[KS][0-9]+//")"
+               new="$(echo "$new" | sed -r "s/[KS][0-9]+//")"
+               ;;
+           *)
+               old="$(echo "$old" | sed -r "s/([KS])[0-9]+/\1_/")"
+               new="$(echo "$new" | sed -r "s/([KS])[0-9]+/\1_/")"
+               ;;
+       esac
+       echo "$new" | while read num cmd; do
+               oldnum=$(echo "$old" | grep "[[:space:]]$cmd$" | awk '{print $1}')
+               if [ "$oldnum" ]; then
+                       diff=$(($num - $oldnum))
+               else
+                       oldnum="---"
+                       diff=""
+               fi
+               if [ ${#cmd} -ge 16 ]; then
+                       echo -e "$cmd\t$num\t$oldnum\t$diff"
+               elif [ ${#cmd} -ge 8 ]; then
+                       echo -e "$cmd\t\t$num\t$oldnum\t$diff"
+               else
+                       echo -e "$cmd\t\t\t$num\t$oldnum\t$diff"
+               fi
+       done
+       echo "$old"  | while read num cmd; do
+               if ! echo "$new" | grep -q "[[:space:]]$cmd$"; then
+                       if [ ${#cmd} -ge 16 ]; then
+                               echo -e "$cmd\t---\t$oldnum"
+                       elif [ ${#cmd} -ge 8 ]; then
+                               echo -e "$cmd\t\t---\t$oldnum"
+                       else
+                               echo -e "$cmd\t\t\t---\t$oldnum"
+                       fi
+               fi
+       done
+       echo
+done
diff --git a/packaging/update-bootsystem-insserv b/packaging/update-bootsystem-insserv
new file mode 100644 (file)
index 0000000..5b20a17
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Author: Petter Reinholdtsen
+# Date: 2009-08-04
+#
+# Transition script only to be used by sysv-rc version 2.87dsf-2 if
+# insserv is upgraded without sysv-rc being upgraded too.
+
+set -e
+
+case "$1" in
+    enable|'')
+       exit 0
+       ;;
+    check)
+       exit 1
+       ;;
+    *)
+       echo "error: Unknown argument '$1'"
+       exit 1
+       ;;
+esac
+
+exit 0
diff --git a/packaging/update-rc.d-insserv b/packaging/update-rc.d-insserv
new file mode 100644 (file)
index 0000000..1853251
--- /dev/null
@@ -0,0 +1,593 @@
+#! /usr/bin/perl
+#
+# update-rc.d  Update the links in /etc/rc[0-9S].d/
+#
+
+use strict;
+use warnings;
+
+my $initd = "/etc/init.d";
+my $etcd  = "/etc/rc";
+my $notreally = 0;
+
+# Save last action to this directory
+my $archive = "/var/lib/update-rc.d";
+
+# Print usage message and die.
+
+sub usage {
+       print STDERR "update-rc.d: error: @_\n" if ($#_ >= 0);
+       print STDERR <<EOF;
+usage: update-rc.d [-n] [-f] <basename> remove
+       update-rc.d [-n] <basename> defaults [NN | SS KK]
+       update-rc.d [-n] <basename> start|stop NN runlvl [runlvl] [...] .
+       update-rc.d [-n] <basename> disable|enable [S|2|3|4|5]
+               -n: not really
+               -f: force
+
+The disable|enable API is not stable and might change in the future.
+EOF
+       exit (1);
+}
+
+# Dependency based boot sequencing is the default, but upgraded
+# systems might keep the legacy ordering until the sysadm choose to
+# migrate to the new ordering method.  sysv-rc version 2.87dsf-2 will
+# remove /var/lib/insserv/using-insserv and this divert, thus transfering
+# the responsibility for dependency based update-rc.d to sysv-rc.
+if ( -f "/var/lib/insserv/using-insserv" && ! -f "/etc/init.d/.legacy-bootordering" ) {
+    info("using dependency based boot sequencing");
+    exit insserv_updatercd(@ARGV);
+}
+
+# Check out options.
+my $force;
+
+my @orig_argv = @ARGV;
+
+while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
+       shift @ARGV;
+       if (/^-n$/) { $notreally++; next }
+       if (/^-f$/) { $force++; next }
+       if (/^-h|--help$/) { &usage; }
+       &usage("unknown option");
+}
+
+sub save_last_action {
+    my ($script, @arguments) = @_;
+
+    return if $notreally;
+
+    open(FILE, ">", "$archive/${script}.new") || die "unable to write to $archive/${script}.new";
+    print FILE join(" ","update-rc.d",@arguments), "\n";
+    close(FILE);
+    rename "$archive/${script}.new", "$archive/${script}";
+}
+
+sub remove_last_action {
+    my ($script) = @_;
+    unlink "$archive/$script";
+}
+
+# Action.
+
+&usage() if ($#ARGV < 1);
+my $bn = shift @ARGV;
+
+unless ($bn =~ m/[a-zA-Z0-9+.-]+/) {
+    print STDERR "update-rc.d: illegal character in name '$bn'\n";
+    exit (1);
+}
+
+if ($ARGV[0] ne 'remove') {
+    if (! -f "$initd/$bn") {
+       print STDERR "update-rc.d: $initd/$bn: file does not exist\n";
+       exit (1);
+    }
+    &parse_lsb_header("$initd/$bn");
+    &cmp_args_with_defaults($bn, $ARGV[0], @ARGV);
+} elsif (-f "$initd/$bn") {
+    if (!$force) {
+       printf STDERR "update-rc.d: $initd/$bn exists during rc.d purge (use -f to force)\n";
+       exit (1);
+    }
+}
+
+my @startlinks;
+my @stoplinks;
+
+$_ = $ARGV[0];
+if    (/^remove$/)       { &checklinks ("remove"); remove_last_action($bn); }
+elsif (/^defaults$/)     { &defaults (@ARGV); &makelinks; save_last_action($bn, @orig_argv); }
+elsif (/^(start|stop)$/) { &startstop (@ARGV); &makelinks; save_last_action($bn, @orig_argv); }
+elsif (/^(dis|en)able$/) { &toggle (@ARGV); &makelinks; save_last_action($bn, @orig_argv); }
+else                     { &usage; }
+
+exit (0);
+
+sub info {
+    print STDOUT "update-rc.d: @_\n";
+}
+
+sub warning {
+    print STDERR "update-rc.d: warning: @_\n";
+}
+
+sub error {
+    print STDERR "update-rc.d: error: @_\n";
+    exit (1);
+}
+
+sub error_code {
+    my $rc = shift;
+    print STDERR "update-rc.d: error: @_\n";
+    exit ($rc);
+}
+
+# Check if there are links in /etc/rc[0-9S].d/ 
+# Remove if the first argument is "remove" and the links 
+# point to $bn.
+
+sub is_link () {
+    my ($op, $fn, $bn) = @_;
+    if (! -l $fn) {
+       warning "$fn is not a symbolic link\n";
+       return 0;
+    } else {
+       my $linkdst = readlink ($fn);
+       if (! defined $linkdst) {
+           die ("update-rc.d: error reading symbolic link: $!\n");
+       }
+       if (($linkdst ne "../init.d/$bn") && ($linkdst ne "$initd/$bn")) {
+           warning "$fn is not a link to ../init.d/$bn or $initd/$bn\n";
+           return 0;
+       }
+    }
+    return 1;
+}
+
+sub checklinks {
+    my ($i, $found, $fn, $islnk);
+
+    print " Removing any system startup links for $initd/$bn ...\n"
+       if (defined $_[0] && $_[0] eq 'remove');
+
+    $found = 0;
+
+    foreach $i (0..9, 'S') {
+       unless (chdir ("$etcd$i.d")) {
+           next if ($i =~ m/^[789S]$/);
+           die("update-rc.d: chdir $etcd$i.d: $!\n");
+       }
+       opendir(DIR, ".");
+       my $saveBN=$bn;
+       $saveBN =~ s/\+/\\+/g;
+       foreach $_ (readdir(DIR)) {
+           next unless (/^[SK]\d\d$saveBN$/);
+           $fn = "$etcd$i.d/$_";
+           $found = 1;
+           $islnk = &is_link ($_[0], $fn, $bn);
+           next unless (defined $_[0] and $_[0] eq 'remove');
+           if (! $islnk) {
+               print "   $fn is not a link to ../init.d/$bn; not removing\n"; 
+               next;
+           }
+           print "   $etcd$i.d/$_\n";
+           next if ($notreally);
+           unlink ("$etcd$i.d/$_") ||
+               die("update-rc.d: unlink: $!\n");
+       }
+       closedir(DIR);
+    }
+    $found;
+}
+
+sub parse_lsb_header {
+    my $initdscript = shift;
+    my %lsbinfo;
+    my $lsbheaders = "Provides|Required-Start|Required-Stop|Default-Start|Default-Stop";
+    open(INIT, "<$initdscript") || die "error: unable to read $initdscript";
+    while (<INIT>) {
+        chomp;
+        $lsbinfo{'found'} = 1 if (m/^\#\#\# BEGIN INIT INFO\s*$/);
+        last if (m/\#\#\# END INIT INFO\s*$/);
+        if (m/^\# ($lsbheaders):\s*(\S?.*)$/i) {
+       $lsbinfo{lc($1)} = $2;
+        }
+    }
+    close(INIT);
+
+    # Check that all the required headers are present
+    if (!$lsbinfo{found}) {
+       printf STDERR "update-rc.d: warning: $initdscript missing LSB information\n";
+       printf STDERR "update-rc.d: see <http://wiki.debian.org/LSBInitScripts>\n";
+    } else {
+        for my $key (split(/\|/, lc($lsbheaders))) {
+            if (!exists $lsbinfo{$key}) {
+                warning "$initdscript missing LSB keyword '$key'\n";
+            }
+        }
+    }
+}
+
+
+# Process the arguments after the "enable" or "disable" keyword.
+
+sub toggle {
+    my @argv = @_;
+    my ($action, %lvls, @start, @stop, @xstartlinks);
+
+    if (!&checklinks) {
+       print " System start/stop links for $initd/$bn do not exist.\n";
+       exit (0);
+    }
+
+    $action = $argv[0];
+    if ($#argv > 1) {
+       while ($#argv > 0 && shift @argv) {
+           if ($argv[0] =~ /^[S2-5]$/) {
+               $lvls{$argv[0]}++;
+           } else {
+               &usage ("expected 'S' '2' '3' '4' or '5'");
+           }
+       }
+    } else {
+       $lvls{$_}++ for ('S', '2', '3', '4', '5');
+    }
+
+    push(@start, glob($etcd . '[2-5S].d/[KS][0-9][0-9]' . $bn));
+
+    foreach (@start) {
+       my $islink = &is_link (undef, $_, $bn);
+       next if !$islink;
+
+       next unless my ($lvl, $sk, $seq) = m/^$etcd([2-5S])\.d\/([SK])([0-9]{2})$bn$/;
+       $startlinks[$lvl] = $sk . $seq;
+
+       if ($action eq 'disable' and $sk eq 'S' and $lvls{$lvl}) {
+           $xstartlinks[$lvl] = 'K' . sprintf "%02d", (100 - $seq);
+       } elsif ($action eq 'enable' and $sk eq 'K' and $lvls{$lvl}) {
+           $xstartlinks[$lvl] = 'S' . sprintf "%02d", -($seq - 100);
+       } else {
+           $xstartlinks[$lvl] = $sk . $seq;
+       }
+    }
+
+    push(@stop, glob($etcd . '[016].d/[KS][0-9][0-9]' . $bn));
+
+    foreach (@stop) {
+       my $islink = &is_link (undef, $_, $bn);
+       next if !$islink;
+
+       next unless my ($lvl, $sk, $seq) = m/^$etcd([016])\.d\/([SK])([0-9]{2})$bn$/;
+       $stoplinks[$lvl] = $sk . $seq;
+    }
+
+    if ($action eq 'disable') {
+       print " Disabling system startup links for $initd/$bn ...\n";
+    } elsif ($action eq 'enable') {
+       print " Enabling system startup links for $initd/$bn ...\n";
+    }
+
+    &checklinks ("remove");
+    @startlinks = @xstartlinks;
+
+    1;
+}
+
+# Process the arguments after the "defaults" keyword.
+
+sub defaults {
+    my @argv = @_;
+    my ($start, $stop) = (20, 20);
+
+    &usage ("defaults takes only one or two codenumbers") if ($#argv > 2);
+    $start = $stop = $argv[1] if ($#argv >= 1);
+    $stop  =         $argv[2] if ($#argv >= 2);
+    &usage ("codenumber must be a number between 0 and 99")
+       if ($start !~ /^\d\d?$/ || $stop  !~ /^\d\d?$/);
+
+    $start = sprintf("%02d", $start);
+    $stop  = sprintf("%02d", $stop);
+
+    $stoplinks[$_]  = "K$stop"  for (0, 1, 6);
+    $startlinks[$_] = "S$start" for (2, 3, 4, 5);
+
+    1;
+}
+
+# Process the arguments after the start or stop keyword.
+
+sub startstop {
+    my @argv = @_;
+    my($letter, $NN, $level);
+
+    while ($#argv >= 0) {
+       if    ($argv[0] eq 'start') { $letter = 'S'; }
+       elsif ($argv[0] eq 'stop')  { $letter = 'K'; }
+       else {
+           &usage("expected start|stop");
+       }
+
+       if ($argv[1] !~ /^\d\d?$/) {
+           &usage("expected NN after $argv[0]");
+       }
+       $NN = sprintf("%02d", $argv[1]);
+
+       if ($argv[-1] ne '.') {
+           &usage("start|stop arguments not terminated by \".\"");
+       }
+
+       shift @argv; shift @argv;
+       $level = shift @argv;
+       do {
+           if ($level !~ m/^[0-9S]$/) {
+               &usage(
+                      "expected runlevel [0-9S] (did you forget \".\" ?)");
+           }
+           if (! -d "$etcd$level.d") {
+               print STDERR
+                   "update-rc.d: $etcd$level.d: no such directory\n";
+               exit(1);
+           }
+           $level = 99 if ($level eq 'S');
+           $startlinks[$level] = "$letter$NN" if ($letter eq 'S');
+           $stoplinks[$level]  = "$letter$NN" if ($letter eq 'K');
+       } while (($level = shift @argv) ne '.');
+    }
+    1;
+}
+
+# Create the links.
+
+sub makelinks {
+    my($t, $i);
+    my @links;
+
+    if (&checklinks) {
+       print " System start/stop links for $initd/$bn already exist.\n";
+       return 0;
+    }
+    print " Adding system startup for $initd/$bn ...\n";
+
+    # nice unreadable perl mess :)
+
+    for($t = 0; $t < 2; $t++) {
+       @links = $t ? @startlinks : @stoplinks;
+       for($i = 0; $i <= $#links; $i++) {
+           my $lvl = $i;
+           $lvl = 'S' if ($i == 99);
+           next if (!defined $links[$i] or $links[$i] eq '');
+           print "   $etcd$lvl.d/$links[$i]$bn -> ../init.d/$bn\n";
+           next if ($notreally);
+           symlink("../init.d/$bn", "$etcd$lvl.d/$links[$i]$bn")
+               || die("update-rc.d: symlink: $!\n");
+       }
+    }
+
+    1;
+}
+
+## Dependency based
+sub insserv_updatercd {
+    my @args = @_;
+    my @opts;
+    my $scriptname;
+    my $action;
+    my $notreally = 0;
+
+    my @orig_argv = @args;
+
+    while($#args >= 0 && ($_ = $args[0]) =~ /^-/) {
+        shift @args;
+        if (/^-n$/) { push(@opts, $_); $notreally++; next }
+        if (/^-f$/) { push(@opts, $_); next }
+        if (/^-h|--help$/) { &usage; }
+        usage("unknown option");
+    }
+
+    usage("not enough arguments") if ($#args < 1);
+
+    $scriptname = shift @args;
+    $action = shift @args;
+    if ("remove" eq $action) {
+        if ( -f "/etc/init.d/$scriptname" ) {
+            my $rc = system("insserv", @opts, "-r", $scriptname) >> 8;
+            if (0 == $rc && !$notreally) {
+                remove_last_action($scriptname);
+            }
+            error_code($rc, "insserv rejected the script header") if $rc;
+            exit $rc;
+        } else {
+            # insserv removes all dangling symlinks, no need to tell it
+            # what to look for.
+            my $rc = system("insserv", @opts) >> 8;
+            if (0 == $rc && !$notreally) {
+                remove_last_action($scriptname);
+            }
+            error_code($rc, "insserv rejected the script header") if $rc;
+            exit $rc;
+        }
+    } elsif ("defaults" eq $action || "start" eq $action ||
+             "stop" eq $action) {
+        # All start/stop/defaults arguments are discarded so emit a
+        # message if arguments have been given and are in conflict
+        # with Default-Start/Default-Stop values of LSB comment.
+        cmp_args_with_defaults($scriptname, $action, @args);
+
+        if ( -f "/etc/init.d/$scriptname" ) {
+            my $rc = system("insserv", @opts, $scriptname) >> 8;
+            if (0 == $rc && !$notreally) {
+                save_last_action($scriptname, @orig_argv);
+            }
+            error_code($rc, "insserv rejected the script header") if $rc;
+            exit $rc;
+        } else {
+            error("initscript does not exist: /etc/init.d/$scriptname");
+        }
+    } elsif ("disable" eq $action || "enable" eq $action) {
+        insserv_toggle($notreally, $action, $scriptname, @args);
+        # Call insserv to resequence modified links
+        my $rc = system("insserv", @opts, $scriptname) >> 8;
+        if (0 == $rc && !$notreally) {
+            save_last_action($scriptname, @orig_argv);
+        }
+        error_code($rc, "insserv rejected the script header") if $rc;
+        exit $rc;
+    } else {
+        usage();
+    }
+}
+
+sub parse_def_start_stop {
+    my $script = shift;
+    my (%lsb, @def_start_lvls, @def_stop_lvls);
+
+    open my $fh, '<', $script or error("unable to read $script");
+    while (<$fh>) {
+        chomp;
+        if (m/^### BEGIN INIT INFO$/) {
+            $lsb{'begin'}++;
+        }
+        elsif (m/^### END INIT INFO$/) {
+            $lsb{'end'}++;
+            last;
+        }
+        elsif ($lsb{'begin'} and not $lsb{'end'}) {
+            if (m/^# Default-Start:\s*(\S?.*)$/) {
+                @def_start_lvls = split(' ', $1);
+            }
+            if (m/^# Default-Stop:\s*(\S?.*)$/) {
+                @def_stop_lvls = split(' ', $1);
+            }
+        }
+    }
+    close($fh);
+
+    return (\@def_start_lvls, \@def_stop_lvls);
+}
+
+sub lsb_header_for_script {
+    my $name = shift;
+
+    foreach my $file ("/etc/insserv/overrides/$name", "/etc/init.d/$name",
+                      "/usr/share/insserv/overrides/$name") {
+        return $file if -s $file;
+    }
+
+    error("cannot find a LSB script for $name");
+}
+
+sub cmp_args_with_defaults {
+    my ($name, $act) = (shift, shift);
+    my ($lsb_start_ref, $lsb_stop_ref, $arg_str, $lsb_str);
+    my (@arg_start_lvls, @arg_stop_lvls, @lsb_start_lvls, @lsb_stop_lvls);
+
+    ($lsb_start_ref, $lsb_stop_ref) = parse_def_start_stop("/etc/init.d/$name");
+    @lsb_start_lvls = @$lsb_start_ref;
+    @lsb_stop_lvls  = @$lsb_stop_ref;
+    return if (!@lsb_start_lvls and !@lsb_stop_lvls);
+
+    if ($act eq 'defaults') {
+        @arg_start_lvls = (2, 3, 4, 5);
+        @arg_stop_lvls  = (0, 1, 6);
+    } elsif ($act eq 'start' or $act eq 'stop') {
+        my $start = $act eq 'start' ? 1 : 0;
+        my $stop = $act eq 'stop' ? 1 : 0;
+
+        # The legacy part of this program passes arguments starting with
+        # "start|stop NN x y z ." but the insserv part gives argument list
+        # starting with sequence number (ie. strips off leading "start|stop")
+        # Start processing arguments immediately after the first seq number.
+        my $argi = $_[0] eq $act ? 2 : 1;
+
+        while (defined $_[$argi]) {
+            my $arg = $_[$argi];
+
+            # Runlevels 0 and 6 are always stop runlevels
+            if ($arg eq 0 or $arg eq 6) {
+               $start = 0; $stop = 1; 
+            } elsif ($arg eq 'start') {
+                $start = 1; $stop = 0; $argi++; next;
+            } elsif ($arg eq 'stop') {
+                $start = 0; $stop = 1; $argi++; next;
+            } elsif ($arg eq '.') {
+                next;
+            }
+            push(@arg_start_lvls, $arg) if $start;
+            push(@arg_stop_lvls, $arg) if $stop;
+        } continue {
+            $argi++;
+        }
+    }
+
+    if ($#arg_start_lvls != $#lsb_start_lvls or
+        join("\0", sort @arg_start_lvls) ne join("\0", sort @lsb_start_lvls)) {
+        $arg_str = @arg_start_lvls ? "@arg_start_lvls" : "none";
+        $lsb_str = @lsb_start_lvls ? "@lsb_start_lvls" : "none";
+        warning "$name start runlevel arguments ($arg_str) do not match",
+                "LSB Default-Start values ($lsb_str)";
+    }
+    if ($#arg_stop_lvls != $#lsb_stop_lvls or
+        join("\0", sort @arg_stop_lvls) ne join("\0", sort @lsb_stop_lvls)) {
+        $arg_str = @arg_stop_lvls ? "@arg_stop_lvls" : "none";
+        $lsb_str = @lsb_stop_lvls ? "@lsb_stop_lvls" : "none";
+        warning "$name stop runlevel arguments ($arg_str) do not match",
+                "LSB Default-Stop values ($lsb_str)";
+    }
+}
+
+sub insserv_toggle {
+    my ($dryrun, $act, $name) = (shift, shift, shift);
+    my (@toggle_lvls, $start_lvls, $stop_lvls, @symlinks);
+    my $lsb_header = lsb_header_for_script($name);
+
+    # Extra arguments to disable|enable action are runlevels. If none
+    # given parse LSB info for Default-Start value.
+    if ($#_ >= 0) {
+        @toggle_lvls = @_;
+    } else {
+        ($start_lvls, $stop_lvls) = parse_def_start_stop($lsb_header);
+        @toggle_lvls = @$start_lvls;
+        if ($#toggle_lvls < 0) {
+            error("$name Default-Start contains no runlevels, aborting.");
+        }
+    }
+
+    # Find symlinks in rc.d directories. Refuse to modify links in runlevels
+    # not used for normal system start sequence.
+    for my $lvl (@toggle_lvls) {
+        if ($lvl !~ /^[S2345]$/) {
+            warning("$act action will have no effect on runlevel $lvl");
+            next;
+        }
+        push(@symlinks, $_) for glob("/etc/rc$lvl.d/[SK][0-9][0-9]$name");
+    }
+
+    if (!@symlinks) {
+        error("no runlevel symlinks to modify, aborting!");
+    }
+
+    # Toggle S/K bit of script symlink.
+    for my $cur_lnk (@symlinks) {
+        my $sk;
+        my @new_lnk = split(//, $cur_lnk);
+
+        if ("disable" eq $act) {
+            $sk = rindex($cur_lnk, '/S') + 1;
+            next if $sk < 1;
+            $new_lnk[$sk] = 'K';
+        } else {
+            $sk = rindex($cur_lnk, '/K') + 1;
+            next if $sk < 1;
+            $new_lnk[$sk] = 'S';
+        }
+
+        if ($dryrun) {
+            printf("rename(%s, %s)\n", $cur_lnk, join('', @new_lnk));
+            next;
+        }
+
+        rename($cur_lnk, join('', @new_lnk)) or error($!);
+    }
+}
diff --git a/remove_initd b/remove_initd
new file mode 100755 (executable)
index 0000000..ef869cf
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /sbin/insserv -r ${1+"$@"}
diff --git a/tests/suite b/tests/suite
new file mode 100644 (file)
index 0000000..5a27309
--- /dev/null
@@ -0,0 +1,306 @@
+#
+# Common test suite definitions, declarations, and functions
+#
+set -eC
+set +o posix
+unset ${!LC@}
+export LANG=POSIX
+
+: ${insserv:=${PWD}/insserv}
+: ${tmpdir:=${PWD}/root}
+: ${initddir:=${tmpdir}/etc/init.d}
+: ${insconf:=${tmpdir}/etc/insserv.conf}
+: ${overridedir:=${tmpdir}/etc/insserv/override}
+: ${issuse=""}
+: ${debug:=""}
+
+declare -i retval=0
+declare -i checkfailed=0
+declare -i testcount=0
+declare -i testfailed=0
+finish_test ()
+{
+    if test 0 -ne $retval ; then
+        echo "error: $testcount test executed, $checkfailed fatal tests failed, $testfailed nonfatal test failed."
+    else
+        echo "success: $testcount test executed, $testfailed nonfatal tests failed."
+    fi
+    rm -rf ${tmpdir}
+    return $retval
+}
+trap 'finish_test' EXIT
+
+mkdir -p $initddir
+
+if test -n "${issuse}" ; then
+    runlevel_path ()
+    {
+       local -a level=($@)
+       level=(${level[@]/%s/S})
+       level=(${level[@]/#/rc})
+       level=(${level[@]/rc[bB]*/boot})
+       printf "${initddir}/%s.d\n" ${level[@]}
+    }
+    list_rclinks()
+    {
+       pushd $initddir/ &> /dev/null
+       echo ${initddir##*/}:
+       ls ${1+"$@"} *
+       popd &> /dev/null
+    }
+    cat <<-'EOF' > $insconf
+       $local_fs       boot.localfs +boot.crypto
+       $network        network
+       $named          +named +dnsmasq +lwresd $network
+       $remote_fs      $local_fs +nfs +smbfs
+       $syslog         syslog
+       $portmap        portmap
+       $time           boot.clock +ntp
+       <interactive>   boot.crypto boot.clock boot.localfs boot.rootfsck apache apache2 kdump ntp
+       EOF
+else
+    runlevel_path ()
+    {
+       printf "${initddir}/../rc%s.d\n" ${1+"$@"}
+    }
+    list_rclinks()
+    {
+       pushd $initddir/../ &> /dev/null
+       ls ${1+"$@"} *
+       popd &> /dev/null
+    }
+    cat <<-'EOF' > $insconf
+       $local_fs       +mountall +umountfs
+       $network        +networking +ifupdown
+       $named          +named +dnsmasq +lwresd +bind9 $network
+       $remote_fs      $local_fs +mountnfs +mountnfs-bootclean +umountnfs +sendsigs
+       $syslog         +syslog +sysklogd
+       $portmap        portmap
+       $time           hwclock
+       <interactive>   udev mountdevsubfs checkroot checkfs console-screen
+       EOF
+fi
+chmod u+w,a+r $insconf
+
+insserv_reg ()
+{
+    script=$(printf "${initddir}/%s\n" ${1+"$@"})
+    $insserv $debug -c $insconf -p $initddir -o $overridedir $script
+}
+
+insserv_del ()
+{
+    script=$(printf "${initddir}/%s\n" ${1+"$@"})
+    $insserv $debug -c $insconf -p $initddir -o $overridedir -r $script
+}
+
+relpath ()
+{
+    local OLDIFS IFS
+    local -a orgwords
+    local -a locwords
+    local -i relp=0
+    local -i deep=0
+    local p l
+    local path=""
+
+    OLDIFS="$IFS"; IFS=/
+    eval orgwords=(${1// /\\\\ }) ; shift
+    eval locwords=(${1// /\\\\ }) ; shift
+    IFS="$OLDIFS"
+    unset OLDIFS
+
+    deep=0
+    relp=0
+    for l in "${locwords[@]}" ; do
+        if test "$l" = ".." ; then
+           ((deep++))
+           continue
+       elif test $deep -gt 0 ; then
+           while ((deep-- > 0)) ; do
+               unset locwords[$((relp+deep))]
+               (((relp-1)-deep < 0)) || unset locwords[$(((relp-1)-deep))]
+           done
+           continue
+        fi
+       ((relp++))
+    done
+    locwords=(${locwords[@]})
+
+    deep=0
+    relp=0
+    for p in "${orgwords[@]}" ; do
+       if test "$p" = ".." ; then
+           ((deep++))
+           continue
+       elif test $deep -gt 0 ; then
+           while ((deep-- > 0)) ; do
+               unset orgwords[$((relp+deep))]
+               (((relp-1)-deep < 0)) || unset orgwords[$(((relp-1)-deep))]
+           done
+           continue
+       fi
+       ((relp++))
+    done
+    orgwords=(${orgwords[@]})
+
+    deep=0
+    relp=0
+    for p in "${orgwords[@]}" ; do
+       eval l="\${locwords[$((deep++))]}"
+       if test "$l" != "$p" -o $relp -ne 0 ; then
+           ((relp++))
+           path="${path}/$p"
+           test -n "$l" || continue
+               if test $relp -eq 1 ; then
+                   path="..${path}"
+               else
+                   path="../${path}"
+               fi
+        fi
+    done
+    unset orgwords p l
+
+    if test $deep -lt ${#locwords[@]} ; then
+       relp=0
+       while test $relp -lt $deep; do
+           unset locwords[$((relp++))]
+       done
+       while test ${#locwords[@]} -gt 0  ; do
+           path="../${path}"
+           unset locwords[$((relp++))]
+       done
+    fi
+
+    echo "$path"
+}
+
+counttest ()
+{
+    testcount=$(expr $testcount + 1)
+}
+
+error ()
+{
+    echo error: $@
+    checkfailed=$(expr $checkfailed + 1)
+    retval=1
+}
+
+warning ()
+{
+    echo warning: $@
+    testfailed=$(expr $testfailed + 1)
+}
+
+addscript ()
+{
+    local scriptname=$1
+    local script=${initddir}/$scriptname
+    cat > $script
+    chmod u+w,a+rx $script
+}
+
+insertscript ()
+{
+    local scriptname=$1
+    addscript   $scriptname
+    insserv_reg $scriptname
+}
+
+present_ok ()
+{
+    local rcdpath=$(runlevel_path $1); shift
+    local script=$1;   shift
+    local ret=0
+    test -L ${rcdpath}/[KS][0-9][0-9]$script || ret=1
+    counttest
+    return $ret
+}
+
+check_script_present ()
+{
+    local runlevel=$1; shift
+    local script=$1;   shift
+    present_ok $runlevel $script && return 0
+    error "script $script not present in runlevel $runlevel"
+}
+
+test_script_present ()
+{
+    local runlevel=$1; shift
+    local script=$1;   shift
+    present_ok $runlevel $script && return 0
+    warning "script $script not present in runlevel $runlevel"
+}
+
+check_script_not_present ()
+{
+    local runlevel=$1; shift
+    local script=$1;   shift
+    if present_ok $runlevel $script ; then
+       error "script $script present in runlevel $runlevel"
+    fi
+    return 0
+}
+
+test_script_not_present ()
+{
+    local runlevel=$1; shift
+    local script=$1;   shift
+    if present_ok $runlevel $script ; then
+       warning "script $script present in runlevel $runlevel"
+    fi
+    return 0
+}
+
+order_ok ()
+{
+    local rcdpath=$(runlevel_path $1); shift
+    local script1=$1;  shift
+    local script2=$1;  shift
+    local ret=0 scr order=""
+    pushd $rcdpath &> /dev/null
+    if test -n "${issuse}" ; then
+       for scr in S[0-9][0-9]* ; do
+           test -e "${scr}" || continue
+           test -L "${scr}" || continue
+           case "${scr#S[0-9][0-9]}" in
+           ${script1}) order="${order:+$order }${script1}" ;;
+           ${script2}) order="${order:+$order }${script2}" ;;
+           esac
+       done
+    else
+       for scr in [SK][0-9][0-9]* ; do
+           test -e "${scr}" || continue
+           test -L "${scr}" || continue
+           case "${scr#[SK][0-9][0-9]}" in
+           ${script1}) order="${order:+$order }${script1}" ;;
+           ${script2}) order="${order:+$order }${script2}" ;;
+           esac
+       done
+    fi
+    popd &> /dev/null
+    test "$order" = "$script1 $script2" || ret=1
+    counttest
+    return $ret
+}
+
+# Fatal check
+check_order ()
+{
+    local runlevel=$1
+    local script1=$2
+    local script2=$3
+    order_ok ${1+"$@"} || error   "incorrect $runlevel sequence $script1 not before $script2" || true
+}
+
+# Non-fatal check
+test_order ()
+{
+    local runlevel=$1
+    local script1=$2
+    local script2=$3
+    order_ok ${1+"$@"} || warning "incorrect $runlevel sequence $script1 not before $script2" || true
+}
+