Server IP : 85.214.239.14 / Your IP : 3.147.42.34 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /usr/share/insserv/ |
Upload File : |
#!/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 $null $x-display-manager ); 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_remote_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"); } if (!exists $checked{'$syslog'} && $scriptinfo{$initdscript}->{'need_syslog'}) { warning("script $short possibly missing dependency on \$syslog"); } 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"); info("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'})); unless ( @startrl || @stoprl) { error("script $short do not start or stop in any runlevels"); } # Scripts starting in rcS.d/ normally do not stop or only stop # during hald and shutdown. elsif ((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)) { # Some obvious errors (runlevels 2-5 are equivalent in Debian) if (array_equal(['3', '5'], \@startrl) || array_equal(['3', '4', '5'], \@startrl)) { error("script $short have inconsistent start runlevels: ", join(" ", @startrl)); } else { 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_remote_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_remote_fs'} = 1 if m%awk%; $lsbinfo{'need_remote_fs'} = 1 if m%which%; } close(INIT); # When running on bellini.debian.org, check if $syslog is needed my $objdumpinfo = dirname($initdscript) . "/../objdump-info"; if ( -f $objdumpinfo) { print "Checking for syslog symbol\n"; if (open(OBJDUMP, "<", $objdumpinfo)) { while (<OBJDUMP>) { $lsbinfo{'need_syslog'} = 1 if /GLIBC.* syslog/; } close OBJDUMP; } } # 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"; }