home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / sbin / update-rc.d < prev    next >
Encoding:
Text File  |  2007-04-10  |  5.4 KB  |  226 lines

  1. #! /usr/bin/perl
  2. #
  3. # update-rc.d    Update the links in /etc/rc[0-9S].d/
  4. #
  5.  
  6. $initd = "/etc/init.d";
  7. $etcd  = "/etc/rc";
  8. $notreally = 0;
  9.  
  10. # Print usage message and die.
  11.  
  12. sub usage {
  13.     print STDERR "update-rc.d: error: @_\n" if ($#_ >= 0);
  14.     print STDERR <<EOF;
  15. usage: update-rc.d [-n] [-f] <basename> remove
  16.        update-rc.d [-n] <basename> defaults|multiuser [NN | sNN kNN]
  17.        update-rc.d [-n] <basename> start|stop NN runlvl [runlvl] [...] .
  18.         -n: not really
  19.         -f: force
  20. EOF
  21.     exit (1);
  22. }
  23.  
  24. # Check out options.
  25.  
  26. while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
  27.     shift @ARGV;
  28.     if (/^-n$/) { $notreally++; next }
  29.     if (/^-f$/) { $force++; next }
  30.     if (/^-h|--help$/) { &usage; }
  31.     &usage("unknown option");
  32. }
  33.  
  34. # Action.
  35.  
  36. &usage() if ($#ARGV < 1);
  37. $bn = shift @ARGV;
  38. if ($ARGV[0] ne 'remove') {
  39.     if (! -f "$initd/$bn") {
  40.     print STDERR "update-rc.d: $initd/$bn: file does not exist\n";
  41.     exit (1);
  42.     }
  43. } elsif (-f "$initd/$bn") {
  44.     if (!$force) {
  45.     printf STDERR "update-rc.d: $initd/$bn exists during rc.d purge (use -f to force)\n";
  46.     exit (1);
  47.     }
  48. }
  49.  
  50. $_ = $ARGV[0];
  51. if    (/^remove$/)       { &checklinks ("remove"); }
  52. elsif (/^defaults$/)     { &defaults; &makelinks }
  53. elsif (/^multiuser$/)    { &multiuser; &makelinks }
  54. elsif (/^(start|stop)$/) { &startstop; &makelinks; }
  55. else                     { &usage; }
  56.  
  57. exit (0);
  58.  
  59. # Check if there are links in /etc/rc[0-9S].d/ 
  60. # Remove if the first argument is "remove" and the links 
  61. # point to $bn.
  62.  
  63. sub is_link () {
  64.     my ($op, $fn, $bn) = @_;
  65.     if (! -l $fn) {
  66.     print STDERR "update-rc.d: warning: $fn is not a symbolic link\n";
  67.     return 0;
  68.     } else {
  69.     $linkdst = readlink ($fn);
  70.     if (! defined $linkdst) {
  71.         die ("update-rc.d: error reading symbolic link: $!\n");
  72.     }
  73.     if (($linkdst ne "../init.d/$bn") && ($linkdst ne "$initd/$bn")) {
  74.         print STDERR "update-rc.d: warning: $fn is not a link to ../init.d/$bn or $initd/$bn\n";
  75.         return 0;
  76.     }
  77.     }
  78.     return 1;
  79. }
  80.  
  81. sub checklinks {
  82.     my ($i, $found, $fn, $islnk);
  83.  
  84.     print " Removing any system startup links for $initd/$bn ...\n"
  85.     if ($_[0] eq 'remove');
  86.  
  87.     $found = 0;
  88.  
  89.     foreach $i (0..9, 'S') {
  90.     unless (chdir ("$etcd$i.d")) {
  91.         next if ($i =~ m/^[789S]$/);
  92.         die("update-rc.d: chdir $etcd$i.d: $!\n");
  93.     }
  94.     opendir(DIR, ".");
  95.     foreach $_ (readdir(DIR)) {
  96.         next unless (/^[SK]\d\d$bn$/);
  97.         $fn = "$etcd$i.d/$_";
  98.         $found = 1;
  99.         $islnk = &is_link ($_[0], $fn, $bn);
  100.         next if ($_[0] ne 'remove');
  101.         if (! $islnk) {
  102.         print "   $fn is not a link to ../init.d/$bn; not removing\n"; 
  103.         next;
  104.         }
  105.         print "   $etcd$i.d/$_\n";
  106.         next if ($notreally);
  107.         unlink ("$etcd$i.d/$_") ||
  108.         die("update-rc.d: unlink: $!\n");
  109.     }
  110.     closedir(DIR);
  111.     }
  112.     $found;
  113. }
  114.  
  115. # Process the arguments after the "defaults" keyword.
  116.  
  117. sub defaults {
  118.     my ($start, $stop) = (20, 20);
  119.  
  120.     &usage ("defaults takes only one or two codenumbers") if ($#ARGV > 2);
  121.     $start = $stop = $ARGV[1] if ($#ARGV >= 1);
  122.     $stop  =         $ARGV[2] if ($#ARGV >= 2);
  123.     &usage ("codenumber must be a number between 0 and 99")
  124.     if ($start !~ /^\d\d?$/ || $stop  !~ /^\d\d?$/);
  125.  
  126.     $start = sprintf("%02d", $start);
  127.     $stop  = sprintf("%02d", $stop);
  128.  
  129.     $stoplinks[0] = $stoplinks[1] = $stoplinks[6] = "K$stop";
  130.     $startlinks[2] = $startlinks[3] =
  131.     $startlinks[4] = $startlinks[5] = "S$start";
  132.  
  133.     1;
  134. }
  135.  
  136. # Process the arguments after the "multiuser" keyword.
  137.  
  138. sub multiuser {
  139.     my ($start, $stop) = (20, 20);
  140.  
  141.     &usage ("multiuser takes only one or two codenumbers") if ($#ARGV > 2);
  142.     $start = $stop = $ARGV[1] if ($#ARGV >= 1);
  143.     $stop  =         $ARGV[2] if ($#ARGV >= 2);
  144.     &usage ("codenumber must be a number between 0 and 99")
  145.     if ($start !~ /^\d\d?$/ || $stop  !~ /^\d\d?$/);
  146.  
  147.     $start = sprintf("%02d", $start);
  148.     $stop  = sprintf("%02d", $stop);
  149.  
  150.     $stoplinks[1] = "K$stop";
  151.     $startlinks[2] = $startlinks[3] =
  152.     $startlinks[4] = $startlinks[5] = "S$start";
  153.  
  154.     1;
  155. }
  156.  
  157. # Process the arguments after the start or stop keyword.
  158.  
  159. sub startstop {
  160.  
  161.     my($letter, $NN, $level);
  162.  
  163.     while ($#ARGV >= 0) {
  164.     if    ($ARGV[0] eq 'start') { $letter = 'S'; }
  165.     elsif ($ARGV[0] eq 'stop')  { $letter = 'K' }
  166.     else {
  167.         &usage("expected start|stop");
  168.     }
  169.  
  170.     if ($ARGV[1] !~ /^\d\d?$/) {
  171.         &usage("expected NN after $ARGV[0]");
  172.     }
  173.     $NN = sprintf("%02d", $ARGV[1]);
  174.  
  175.     shift @ARGV; shift @ARGV;
  176.     $level = shift @ARGV;
  177.     do {
  178.         if ($level !~ m/^[0-9S]$/) {
  179.         &usage(
  180.                "expected runlevel [0-9S] (did you forget \".\" ?)");
  181.         }
  182.         if (! -d "$etcd$level.d") {
  183.         print STDERR
  184.             "update-rc.d: $etcd$level.d: no such directory\n";
  185.         exit(1);
  186.         }
  187.         $level = 99 if ($level eq 'S');
  188.         $startlinks[$level] = "$letter$NN" if ($letter eq 'S');
  189.         $stoplinks[$level]  = "$letter$NN" if ($letter eq 'K');
  190.     } while (($level = shift @ARGV) ne '.');
  191.     &usage("action with list of runlevels not terminated by \`.'")
  192.         if ($level ne '.');
  193.     }
  194.     1;
  195. }
  196.  
  197. # Create the links.
  198.  
  199. sub makelinks {
  200.     my($t, $i);
  201.     my @links;
  202.  
  203.     if (&checklinks) {
  204.     print " System startup links for $initd/$bn already exist.\n";
  205.     exit (0);
  206.     }
  207.     print " Adding system startup for $initd/$bn ...\n";
  208.  
  209.     # nice unreadable perl mess :)
  210.  
  211.     for($t = 0; $t < 2; $t++) {
  212.     @links = $t ? @startlinks : @stoplinks;
  213.     for($i = 0; $i <= $#links; $i++) {
  214.         $lvl = $i;
  215.         $lvl = 'S' if ($i == 99);
  216.         next if ($links[$i] eq '');
  217.         print "   $etcd$lvl.d/$links[$i]$bn -> ../init.d/$bn\n";
  218.         next if ($notreally);
  219.         symlink("../init.d/$bn", "$etcd$lvl.d/$links[$i]$bn")
  220.         || die("update-rc.d: symlink: $!\n");
  221.     }
  222.     }
  223.  
  224.     1;
  225. }
  226.