--- /dev/null
+-------------------------------------------------------------------
+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
+
+
--- /dev/null
+ 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.
--- /dev/null
+#
+# 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
--- /dev/null
+ 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
+
--- /dev/null
+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>.
--- /dev/null
+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.
--- /dev/null
+# 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
--- /dev/null
+#!/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
--- /dev/null
+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
--- /dev/null
+#!/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";
+}
--- /dev/null
+#!/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,
+ };
+}
--- /dev/null
+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.
--- /dev/null
+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.
--- /dev/null
+etc/bash_completion.d
+etc/insserv.conf.d
+etc/insserv/overrides
+usr/sbin
+usr/share/insserv/overrides
+var/lib/update-rc.d
--- /dev/null
+insserv: binary-without-manpage usr/sbin/update-bootsystem-insserv
--- /dev/null
+#!/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
--- /dev/null
+debian/update-rc.d-insserv.8
--- /dev/null
+### 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
--- /dev/null
+### 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
--- /dev/null
+### 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
--- /dev/null
+### BEGIN INIT INFO
+# Provides: initrd-tools
+# Required-Start: mountdevsubfs
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+### END INIT INFO
--- /dev/null
+### BEGIN INIT INFO
+# Provides: modutils
+# Required-Start: checkroot
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+### END INIT INFO
+# Reported to BTS as #335311
--- /dev/null
+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:]')
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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;
--- /dev/null
+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);
+
--- /dev/null
+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);
--- /dev/null
+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) {
--- /dev/null
+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(®.def_start, DEFAULT_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.def_stop, DEFAULT_STOP, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.desc, DESCRIPTION, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
++ regcompiler(®.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(®.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(®.def_start);
+ regfree(®.def_stop);
+ regfree(®.desc);
++ regfree(®.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) {
--- /dev/null
+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);
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+
--- /dev/null
+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
--- /dev/null
+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':
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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"
--- /dev/null
+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;
--- /dev/null
+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.
--- /dev/null
+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 */
--- /dev/null
+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
--- /dev/null
+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); }))
--- /dev/null
+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
--- /dev/null
+[type: gettext/rfc822deb] insserv.templates
--- /dev/null
+# 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."
--- /dev/null
+# 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."
+
--- /dev/null
+# 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."
--- /dev/null
+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."
--- /dev/null
+# 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."
--- /dev/null
+# 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."
--- /dev/null
+# 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."
--- /dev/null
+# 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 ""
+"この機能は実験的なものであることに注意ください。依存関係ベースでの起動シーケンス"
+"から元に戻すのは、安全が確保されていない上にシステムの再インストールが必要になる"
+"かもしれません。"
+
--- /dev/null
+# 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."
--- /dev/null
+# 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."
--- /dev/null
+# 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 ""
+"Обратите внимание, что это пока эксперимент. Возвращение назад с порядка "
+"загрузки, основанного на зависимостях не гарантируется и может потребоваться "
+"переустановка системы."
--- /dev/null
+# 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."
--- /dev/null
+# 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 ""
--- /dev/null
+# 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."
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#! /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
--- /dev/null
+#!/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
--- /dev/null
+#! /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($!);
+ }
+}
--- /dev/null
+.\" 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>
--- /dev/null
+# 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
--- /dev/null
+#
+# 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}"
+}
+
--- /dev/null
+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
--- /dev/null
+.\"
+.\" 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>
--- /dev/null
+/*
+ * 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(®.prov, PROVIDES, REG_EXTENDED|REG_ICASE);
+ regcompiler(®.req_start, REQUIRED_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.req_stop, REQUIRED_STOP, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.shl_start, SHOULD_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.shl_stop, SHOULD_STOP, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.start_bf, START_BEFORE, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.stop_af, STOP_AFTER, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.def_start, DEFAULT_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.def_stop, DEFAULT_STOP, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.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(®.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(®.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(®.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(®.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(®.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(®.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(®.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(®.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(®.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(®.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(®.prov);
+ regfree(®.req_start);
+ regfree(®.req_stop);
+ regfree(®.shl_start);
+ regfree(®.shl_stop);
+ regfree(®.start_bf);
+ regfree(®.stop_af);
+ regfree(®.def_start);
+ regfree(®.def_stop);
+ regfree(®.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;
+}
--- /dev/null
+#
+# 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
--- /dev/null
+#!/bin/sh
+exec /sbin/insserv ${1+"$@"}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+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:]')
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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;
--- /dev/null
+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);
+
--- /dev/null
+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);
--- /dev/null
+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(®.def_start, DEFAULT_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.def_stop, DEFAULT_STOP, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
+ regcompiler(®.desc, DESCRIPTION, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
++ regcompiler(®.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(®.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(®.def_start);
+ regfree(®.def_stop);
+ regfree(®.desc);
++ regfree(®.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) {
--- /dev/null
+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);
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+
--- /dev/null
+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':
--- /dev/null
+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
--- /dev/null
+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"
--- /dev/null
+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;
--- /dev/null
+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.
--- /dev/null
+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 */
--- /dev/null
+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
--- /dev/null
+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); }))
--- /dev/null
+# 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
--- /dev/null
+#!/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";
+}
--- /dev/null
+#!/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,
+ };
+}
--- /dev/null
+### 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
--- /dev/null
+### 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
--- /dev/null
+### 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
--- /dev/null
+### BEGIN INIT INFO
+# Provides: initrd-tools
+# Required-Start: mountdevsubfs
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+### END INIT INFO
--- /dev/null
+#sbs-git:slp/pkgs/i/insserv insserv 1.12.0 4a5235dc3ec71a9c5267734a3559387b181a17ed
+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
+
+# license
+mkdir -p %{buildroot}/usr/share/license
+cp COPYING %{buildroot}/usr/share/license/%{name}
+
+%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
+/usr/share/license/%{name}
--- /dev/null
+#!/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
--- /dev/null
+### BEGIN INIT INFO
+# Provides: modutils
+# Required-Start: checkroot
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+### END INIT INFO
+# Reported to BTS as #335311
--- /dev/null
+#! /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
--- /dev/null
+#!/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
--- /dev/null
+#! /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($!);
+ }
+}
--- /dev/null
+#!/bin/sh
+exec /sbin/insserv -r ${1+"$@"}
--- /dev/null
+#
+# 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
+}
+