[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

PaiPix feedback on /usr/sbin/update-rc.d...



Dear colleagues,

We have found a very inconvenient effect of the usual debian upgrade for a knoppix hard-disk installation. All services that are installed will become automatically started at boot time. This results from the fact that the links in /etc/rc0.d ... rc6.d that were erased in the live installation will be created automatically in the package upgrade process. I tried to look for solutions and I have found some suggestions PS: I have still quite a number of other patches to report but I will wait a bit not to monopolise this email listing.
 on the net that I have adapted.

In fact, the Debian people had the nice insight to force all packages to create the sysv rc?.d links trough the update-rc.d script. If we change this script we can control the process. However the information on the other number on (example S20mysql) links must be kept upon disabling the service to allow enabling it later.

This patch to update-rc.d defines the enable and disable commands.
To disable the services one has the (PaiPix) /etc/rcS.d/ directory as:

disabled.S05initrd-tools.sh    disabled.S39dns-clean
disabled.S07hdparm             disabled.S40hotplug
disabled.S15isapnp             disabled.S40networking
disabled.S18hwclockfirst.sh    disabled.S50hwclock.sh
disabled.S20module-init-tools  disabled.S70xfree86-common
disabled.S24raid2              disabled.S75sudo
disabled.S25brltty             README
disabled.S25mdadm-raid         S00knoppix-autoconfig

See also http://aamorimsrv.fis.fc.ul.pt/

All the best,
Antonio Amorim

PS: I have still quite a number of other patches to report but I will wait a bit not to monopolize this email listing.

--- /home/aamorim/update-rc.d.old	2005-01-10 15:17:28.000000000 +0000
+++ /usr/sbin/update-rc.d	2005-01-12 01:15:09.000000000 +0000
@@ -17,6 +17,8 @@
 usage: update-rc.d [-n] [-f] <basename> remove
        update-rc.d [-n] <basename> defaults [NN | sNN kNN]
        update-rc.d [-n] <basename> start|stop NN runlvl [runlvl] [...] .
+       update-rc.d [-n] <basename> disable
+       update-rc.d [-n] <basename> enable
 		-n: not really
 		-f: force
 EOF
@@ -54,6 +56,8 @@
 $_ = $ARGV[0];
 if    (/^remove$/)       { &checklinks ("remove"); }
 elsif (/^defaults$/)     { &defaults; &makelinks }
+elsif (/^enable$/)     { &checklinks ("enable"); }
+elsif (/^disable$/)     {  &checklinks ("disable"); }
 elsif (/^(start|stop)$/) { &startstop; &makelinks; }
 else                     { &usage; }
 
@@ -66,7 +70,7 @@
 sub is_link () {
     my ($op, $fn, $bn) = @_;
     if (! -l $fn) {
-	print STDERR "update-rc.d: warning: $fn is not a symbolic link\n";
+#	print STDERR "update-rc.d: warning: $fn is not a symbolic link\n";
 	return 0;
     } else {
 	$linkdst = readlink ($fn);
@@ -86,9 +90,54 @@
 
     print " Removing any system startup links for $initd/$bn ...\n"
 	if ($_[0] eq 'remove');
+    print " Disabling  any system startup links for $initd/$bn ...\n"
+	if ($_[0] eq 'disable');
+    print " Enabling  any system startup links for $initd/$bn ...\n"
+	if ($_[0] eq 'enable');
 
     $found = 0;
 
+
+    foreach $link (listoflinks($bn)) {
+        $found = 1;
+	$islnk = &is_link ($_[0], $link, $bn);
+	next if ($_[0] eq '');
+	if ($_[0] eq 'remove') {
+	  if (! $islnk && $link!~/disabled\./) {
+	    print "   $fn is not a link to ../init.d/$bn; not removing\n";
+	    next;
+	}
+	  print "   $link\n";
+	  next if ($notreally);
+	  unlink ("$link") ||   die("update-rc.d: unlink: $!\n");
+	  next;
+	}
+	if ($_[0] eq 'disable' && $link!~/disabled\./) {
+	  $link=~/etc\/rc([0-9S]).d\/(.*)$/;
+	  print "   disabling $link i.e. $link => /etc/rc$1.d/disabled.$2\n";
+	  next if ($notreally);
+	  system("rm -f $link && touch /etc/rc$1.d/disabled.$2");
+	  next;
+	}
+	if ($_[0] eq 'enable' && $link=~/disabled\./) {
+	  $link=~/etc\/rc([0-9S]).d\/disabled\.(.*)$/;
+	  print "   enabling $etcd${i.d}$link i.e. $link => /etc/rc$1.d/$2\n";
+	  print "rm -f ${i.d}${link} && ln -s /etc/init.d/$bn /etc/rc$1.d/$2\n";
+	  next if ($notreally);
+	  system("rm -f ${i.d}$link && ln -s ../init.d/$bn /etc/rc$1.d/$2");
+	  next;
+	}
+    }
+    $found;
+}
+
+
+sub listoflinks {
+    my ($i, $package, @links);
+    $package=shift;
+    $found = 0;
+    @links=();
+
     foreach $i (0..9, 'S') {
 	unless (chdir ("$etcd$i.d")) {
 	    next if ($i =~ m/^[789S]$/);
@@ -96,25 +145,16 @@
 	}
 	opendir(DIR, ".");
 	foreach $_ (readdir(DIR)) {
-	    next unless (/^[SK]\d\d$bn$/);
-	    $fn = "$etcd$i.d/$_";
-	    $found = 1;
-	    $islnk = &is_link ($_[0], $fn, $bn);
-	    next if ($_[0] ne '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");
+	    next unless (/((disabled\.)?[SK]\d\d$bn)$/);
+	    push (@links, "$etcd$i.d/$1");
+#	    print "DEBUG: added $etcd$i.d/$1\n";
 	}
 	closedir(DIR);
     }
-    $found;
+    return (@links);
 }
 
+
 # Process the arguments after the "defaults" keyword.
 
 sub defaults {
@@ -198,7 +238,8 @@
 	    next if ($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")
+	    (-e "$etcd$lvl.d/$links[$i]$bn")
+	      || symlink("../init.d/$bn", "$etcd$lvl.d/$links[$i]$bn")
 		|| die("update-rc.d: symlink: $!\n");
 	}
     }
#! /usr/bin/perl
#
# update-rc.d	Update the links in /etc/rc[0-9S].d/
#
# Version:	@(#)update-rc.d.pl  2.02  05-Mar-1998  miquels@cistron.nl
#

$initd = "/etc/init.d";
$etcd  = "/etc/rc";
$notreally = 0;

# 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 | sNN kNN]
       update-rc.d [-n] <basename> start|stop NN runlvl [runlvl] [...] .
       update-rc.d [-n] <basename> disable
       update-rc.d [-n] <basename> enable
		-n: not really
		-f: force
EOF
	exit (1);
}

# Check out options.

while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
	shift @ARGV;
	if (/^-n$/) { $notreally++; next }
	if (/^-f$/) { $force++; next }
	if (/^-h|--help$/) { &usage; }
	&usage("unknown option");
}

# Action.

&usage() if ($#ARGV < 1);
$bn = shift @ARGV;
if ($ARGV[0] ne 'remove') {
    if (! -f "$initd/$bn") {
	print STDERR "update-rc.d: $initd/$bn: file does not exist\n";
	exit (1);
    }
} 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);
    } else {
	printf STDERR "update-rc.d: $initd/$bn exists during rc.d purge (continuing)\n";
    }
}

$_ = $ARGV[0];
if    (/^remove$/)       { &checklinks ("remove"); }
elsif (/^defaults$/)     { &defaults; &makelinks }
elsif (/^enable$/)     { &checklinks ("enable"); }
elsif (/^disable$/)     {  &checklinks ("disable"); }
elsif (/^(start|stop)$/) { &startstop; &makelinks; }
else                     { &usage; }

exit (0);

# 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) {
#	print STDERR "update-rc.d: warning: $fn is not a symbolic link\n";
	return 0;
    } else {
	$linkdst = readlink ($fn);
	if (! defined $linkdst) {
	    die ("update-rc.d: error reading symbolic link: $!\n");
	}
	if (($linkdst ne "../init.d/$bn") && ($linkdst ne "../init.d/$bn")) {
	    print STDERR "update-rc.d: warning: $fn is not a link to ../init.d/$bn\n";
	    return 0;
	}
    }
    return 1;
}

sub checklinks {
    my ($i, $found, $fn, $islnk);

    print " Removing any system startup links for $initd/$bn ...\n"
	if ($_[0] eq 'remove');
    print " Disabling  any system startup links for $initd/$bn ...\n"
	if ($_[0] eq 'disable');
    print " Enabling  any system startup links for $initd/$bn ...\n"
	if ($_[0] eq 'enable');

    $found = 0;


    foreach $link (listoflinks($bn)) {
        $found = 1;
	$islnk = &is_link ($_[0], $link, $bn);
	next if ($_[0] eq '');
	if ($_[0] eq 'remove') {
	  if (! $islnk && $link!~/disabled\./) {
	    print "   $fn is not a link to ../init.d/$bn; not removing\n";
	    next;
	}
	  print "   $link\n";
	  next if ($notreally);
	  unlink ("$link") ||   die("update-rc.d: unlink: $!\n");
	  next;
	}
	if ($_[0] eq 'disable' && $link!~/disabled\./) {
	  $link=~/etc\/rc([0-9S]).d\/(.*)$/;
	  print "   disabling $link i.e. $link => /etc/rc$1.d/disabled.$2\n";
	  next if ($notreally);
	  system("rm -f $link && touch /etc/rc$1.d/disabled.$2");
	  next;
	}
	if ($_[0] eq 'enable' && $link=~/disabled\./) {
	  $link=~/etc\/rc([0-9S]).d\/disabled\.(.*)$/;
	  print "   enabling $etcd${i.d}$link i.e. $link => /etc/rc$1.d/$2\n";
	  print "rm -f ${i.d}${link} && ln -s /etc/init.d/$bn /etc/rc$1.d/$2\n";
	  next if ($notreally);
	  system("rm -f ${i.d}$link && ln -s ../init.d/$bn /etc/rc$1.d/$2");
	  next;
	}
    }
    $found;
}


sub listoflinks {
    my ($i, $package, @links);
    $package=shift;
    $found = 0;
    @links=();

    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, ".");
	foreach $_ (readdir(DIR)) {
	    next unless (/((disabled\.)?[SK]\d\d$bn)$/);
	    push (@links, "$etcd$i.d/$1");
#	    print "DEBUG: added $etcd$i.d/$1\n";
	}
	closedir(DIR);
    }
    return (@links);
}


# Process the arguments after the "defaults" keyword.

sub defaults {
    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[0] = $stoplinks[1] = $stoplinks[6] = "K$stop";
    $startlinks[2] = $startlinks[3] =
	$startlinks[4] = $startlinks[5] = "S$start";

    1;
}

# Process the arguments after the start or stop keyword.

sub startstop {

    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]);

	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 '.');
	&usage("action with list of runlevels not terminated by \`.'")
	    if ($level ne '.');
    }
    1;
}

# Create the links.

sub makelinks {
    my($t, $i);
    my @links;

    if (&checklinks) {
	print " System startup links for $initd/$bn already exist.\n";
	exit (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++) {
	    $lvl = $i;
	    $lvl = 'S' if ($i == 99);
	    next if ($links[$i] eq '');
	    print "   $etcd$lvl.d/$links[$i]$bn -> ../init.d/$bn\n";
	    next if ($notreally);
	    (-e "$etcd$lvl.d/$links[$i]$bn")
	      || symlink("../init.d/$bn", "$etcd$lvl.d/$links[$i]$bn")
		|| die("update-rc.d: symlink: $!\n");
	}
    }

    1;
}

Reply to: