The following commit has been merged in the master branch:
commit 3dc58767f21fec9df9f0f40cf1ea66175483e257
Author: Russ Allbery <r...@debian.org>
Date:   Mon Dec 29 16:25:38 2008 -0800

    Check for scripts in /etc calling init scripts directly
    
    * checks/scripts{,.desc}:
      + [RA] Check for scripts in /etc that call init scripts directly
        without using invoke-rc.d.  Based on a patch by Raphael Geissert.
        (Closes: #381485)

diff --git a/checks/scripts b/checks/scripts
index 2085b06..919f92d 100644
--- a/checks/scripts
+++ b/checks/scripts
@@ -185,6 +185,11 @@ our @depends_needed = (
        [ 'xml-core'    => '\bupdate-xmlcatalog\s' ],
 );
 
+# When detecting commands inside shell scripts, use this regex to match the
+# beginning of the command rather than checking whether the command is at the
+# beginning of a line.
+our $LEADIN = qr'(?:(?:^|[`&;(|{])\s*|(?:if|then|do|while)\s+)';
+
 sub run {
 
 my %executable = ();
@@ -327,6 +332,41 @@ for my $filename (sort keys %{$info->scripts}) {
        tag("unusual-interpreter", $filename, "#!$interpreter");
     }
 
+    # Do some additional checks on shell scripts in /etc.  This should
+    # probably be extended eventually to any script in a public directory.
+    # This also needs smarter processing of multiline quoted strings,
+    # heredocs, and so forth.  Hopefully it will do for right now.
+    if ($filename =~ m,^./etc/, and $base =~ /^$known_shells_regex$/) {
+       my ($saw_init, $saw_invoke);
+       local $.;
+       open(FH, '<', 'unpacked/' . $filename);
+       while (<FH>) {
+           next if m,^\s*$,;  # skip empty lines
+           next if m,^\s*\#,; # skip comment lines
+           s/\#.*$//;         # eat comments
+           chomp;
+
+           # Check for running init scripts directly instead of via
+           # invoke-rc.d.  Scripts are allowed to reinvoke themselves with a
+           # different argument; some init scripts implement actions that
+           # way.  Scripts are also allowed to do this for actions other than
+           # those defined for invoke-rc.d.
+           if (m,$LEADIN/etc/init.d/(\S+)\s+[\"\']?(\S+)[\"\']?,) {
+               my ($script, $action) = ($1, $2);
+               next if "./etc/init.d/$script" eq $filename;
+               next unless $action =~ 
/^(force-)?(start|stop|restart|reload|status)$/;
+               $saw_init = $.;
+           }
+           if (m%^\s*invoke-rc\.d\s+%) {
+               $saw_invoke = 1;
+           }
+       }
+       close(FH);
+       if ($saw_init and not $saw_invoke) {
+           tag 'script-calls-init-script-directly', "$filename:$saw_init";
+       }
+    }
+
     # If we found the interpreter and the script is executable, check
     # dependencies.  This should be the last thing we do in the loop so that
     # we can use next for an early exit and reduce the nesting.
@@ -491,7 +531,6 @@ while (<SCRIPTS>) {
     my %warned;
     my ($saw_init, $saw_invoke, $saw_debconf, $saw_sete, $has_code);
     my $cat_string = "";
-    my $LEADIN = qr'(?:(?:^|[`&;(|{])\s*|(?:if|then|do|while)\s+)';
 
     my $previous_line = "";
     while (<C>) {
@@ -547,7 +586,7 @@ while (<SCRIPTS>) {
        }
 
        # Collect information about init script invocations to catch running
-       # init scripts directory rather than through invoke-rc.d.  Since the
+       # init scripts directly rather than through invoke-rc.d.  Since the
        # script is allowed to run the init script directly if invoke-rc.d
        # doesn't exist, only tag direct invocations where invoke-rc.d is
        # never used in the same script.  Lots of false negatives, but
diff --git a/checks/scripts.desc b/checks/scripts.desc
index 5889046..c215f5d 100644
--- a/checks/scripts.desc
+++ b/checks/scripts.desc
@@ -425,6 +425,15 @@ Info: This script apparently runs an init script directly 
rather than
  available.
 Ref: policy 9.3.3.2
 
+Tag: script-calls-init-script-directly
+Severity: normal
+Certainty: possible
+Info: This script apparently runs an init script directly rather than
+ using <tt>invoke-rc.d</tt>.  While use of <tt>invoke-rc.d</tt> is only
+ required for maintainer scripts, supporting the policy layer that it
+ implements is a good idea in any script.
+Ref: policy 9.3.3.2
+
 Tag: gconftool-used-in-maintainer-script
 Severity: normal
 Certainty: possible
diff --git a/debian/changelog b/debian/changelog
index d485642..2a11e8a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -8,6 +8,7 @@ lintian (2.1.4) UNRELEASED; urgency=low
       - desktop-mimetype-without-update-call
       - forbidden-postrm-interpreter
       - preinst-interpreter-without-predepends
+      - script-calls-init-script-directly
       - unknown-control-interpreter (split from unusual-interpreter)
     + Removed
       - desktop-file-but-no-dh_desktop-call
@@ -31,6 +32,9 @@ lintian (2.1.4) UNRELEASED; urgency=low
         interpreter-in-usr-local since the severity is higher.
       - unusual-control-interpreter is certain, not possible.
       - Suppress some cases of multiple tags about the same basic problem.
+    + [RA] Check for scripts in /etc that call init scripts directly
+      without using invoke-rc.d.  Based on a patch by Raphael Geissert.
+      (Closes: #381485)
 
   * debian/rules:
     + [RA] New check-tag target which runs all test cases in the new test
diff --git a/t/tests/6000_scripts-calls-init-script.desc 
b/t/tests/6000_scripts-calls-init-script.desc
new file mode 100644
index 0000000..d092bee
--- /dev/null
+++ b/t/tests/6000_scripts-calls-init-script.desc
@@ -0,0 +1,7 @@
+Testname: scripts-calls-init-script
+Version: 1.0
+Description: Test proper use of invoke-rc.d
+Test-For:
+ maintainer-script-calls-init-script-directly
+ script-calls-init-script-directly
+References: Debian Bug#381485
diff --git a/t/tests/scripts-calls-init-script/debian/bad 
b/t/tests/scripts-calls-init-script/debian/bad
new file mode 100755
index 0000000..86c80a7
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/bad
@@ -0,0 +1,2 @@
+#!/bin/sh
+/etc/init.d/ntp restart
diff --git a/t/tests/scripts-calls-init-script/debian/debian/install 
b/t/tests/scripts-calls-init-script/debian/debian/install
new file mode 100644
index 0000000..31e3a9e
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/debian/install
@@ -0,0 +1,4 @@
+bad          /etc/cron.daily
+other-action /etc/cron.daily
+test-first   /etc/cron.daily
+self-invoke  /etc/init.d
diff --git a/t/tests/scripts-calls-init-script/debian/debian/postinst 
b/t/tests/scripts-calls-init-script/debian/debian/postinst
new file mode 100644
index 0000000..3feaa42
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/debian/postinst
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -e
+
+update-rc.d self-invoke defaults >/dev/null
+/etc/init.d/self-invoke start
+
+#DEBHELPER#
diff --git a/t/tests/scripts-calls-init-script/debian/debian/postrm 
b/t/tests/scripts-calls-init-script/debian/debian/postrm
new file mode 100644
index 0000000..acba064
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/debian/postrm
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+if [ "remove" = "$1" ] ; then
+    update-rc.d self-invoke remove >/dev/null
+fi
+
+#DEBHELPER#
diff --git a/t/tests/scripts-calls-init-script/debian/other-action 
b/t/tests/scripts-calls-init-script/debian/other-action
new file mode 100755
index 0000000..cd58f75
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/other-action
@@ -0,0 +1,3 @@
+#!/bin/sh
+# Only supported invoke-rc.d actions are required to go through invoke-rc.d.
+/etc/init.d/foo frobnicate-the-bazerator
diff --git a/t/tests/scripts-calls-init-script/debian/self-invoke 
b/t/tests/scripts-calls-init-script/debian/self-invoke
new file mode 100755
index 0000000..dfceee5
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/self-invoke
@@ -0,0 +1,24 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          self-invoke
+# Required-Start:    
+# Required-Stop:     
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Test init script
+# Description:       Test init script.
+### END INIT INFO
+case "$1" in
+  start)
+    :
+    ;;
+  stop)
+    :
+    ;;
+  restart)
+    /etc/init.d/self-invoke start
+    ;;
+  force-reload)
+    :
+    ;;
+esac
diff --git a/t/tests/scripts-calls-init-script/debian/test-first 
b/t/tests/scripts-calls-init-script/debian/test-first
new file mode 100755
index 0000000..5019218
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/debian/test-first
@@ -0,0 +1,6 @@
+#!/bin/sh
+if which invoke-rc.d >/dev/null 2>&1 ; then
+    invoke-rc.d ntp restart
+else
+    /etc/init.d/ntp restart
+fi
diff --git a/t/tests/scripts-calls-init-script/tags 
b/t/tests/scripts-calls-init-script/tags
new file mode 100644
index 0000000..0fb370b
--- /dev/null
+++ b/t/tests/scripts-calls-init-script/tags
@@ -0,0 +1,2 @@
+E: scripts-calls-init-script: maintainer-script-calls-init-script-directly 
postinst:5
+W: scripts-calls-init-script: script-calls-init-script-directly 
./etc/cron.daily/bad:2

-- 
Debian package checker


-- 
To UNSUBSCRIBE, email to debian-lint-maint-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to