#!/usr/bin/perl -w # update-rcconf-guide # Copyright (c) 2004-2009 kamop@debian.org # =head1 NAME update-rcconf-guide - Create default guide file for rcconf =head1 SYNOPSIS B =head1 DESCRIPTION B creates the default guide file which B uses. B searches the package names corresponding to each service file in /etc/init.d directory from dpkg info files(/var/lib/dpkg/info/*.list) and get the description of these packages using apt-cache. B uses Short-Description in priority to the description if service files has Short-Description field. B writes those results to /var/lib/rcconf/guide.default file. You can write your own guide in user guide file(/var/lib/rcconf/guide) by hand. B refers Guides in /var/lib/rcconf/guide before those in /var/lib/rcconf/guide.default. If you install some packages after executed B, you need to re-create this file using B so as to refresh guide.default that includes new guides for installed new services. Notice: B was not executed when you installed B package. =head1 FILE =over 8 =item /var/lib/rcconf/guide.default Guide File update-rcconf-guide generates. =item /var/lib/rcconf/guide Guide File user(Administrator) can define. =back =head1 SEE ALSO rcconf(8) =head1 AUTHOR Atsushi KAMOSHIDA =cut use strict; use FileHandle; use DirHandle; my @unselects = ("\^\\\.\$", "\^\\\.\\\.\$", "\^rc\$", "\^rcS\$", "\^README\$", "\^skeleton\$", ".*\\\.dpkg-dist\$", ".*\\\.dpkg-old\$", ".*\\\.dpkg-bak\$", ".*\\\.sh\$"); my $APTCACHE_BIN = "/usr/bin/apt-cache"; my $GREP_BIN = "/bin/grep"; my $RCCONF_DIR = "/var/lib/rcconf"; my $GUIDE_FILE = $RCCONF_DIR."/guide.default"; my $INITD_DIR = "/etc/init.d"; if ( ! -d $RCCONF_DIR ) { die "Can't file rcconf dir($RCCONF_DIR).\n"; } print "Reading $INITD_DIR and getting package description ...\n"; my $initd_files_array = &read_initd_dir($INITD_DIR); my $filepath_hash = &create_dpkg_installed_filepath(); print "Writing package default guide to $GUIDE_FILE ...\n"; my $fh = FileHandle->new(">".$GUIDE_FILE); if ( ! defined($fh) ) { die "Can't open file: $GUIDE_FILE .\n"; } my $path; my $description_header; foreach my $initd_file ( @{$initd_files_array} ) { # print $initd_file."\n"; next if ( &check_unselect($initd_file, \@unselects) == 1 ); # print $initd_file."\n"; $path = $INITD_DIR."/".$initd_file; next if ( ! exists($filepath_hash->{$path}) ); $description_header = &get_description_header($filepath_hash->{$path}, $path); if ( $description_header ne "" ) { print $fh $initd_file." ".$description_header."\n"; } } undef $fh; print "Done.\n"; exit; ####################################################################### ## MODULE: get_description_header ## DESC: ## IN: ## OUT: ## OP: ## STATUS: ## END: sub get_description_header { my ($package, $path) = @_; ## if ( $package eq "" ) { die "arg(package) is null.\n"; } ## First, try to get Short-Description my $line = `$GREP_BIN '^\# Short-Description:' $path`; if ( $line ne "" ) { $line =~ /^\# Short-Description:\s*(.*)/; return $1; } if ( $package eq "tinyproxy" ) { printf "%s %s %s\n", $package, $path, $line; exit 1; } $line = `$APTCACHE_BIN show $package | $GREP_BIN '^Description:'`; $line =~ /^Description:\s*(.*)/; return $1; } ## get_description_header ####################################################################### ## MODULE: check_unselect ## DESC: Check if 'file' exists in unselects array. ## IN: ## OUT: results 0 := file is not in the array. ## 1 := file exists in the array. ## OP: ## STATUS: ## END: sub check_unselect{ my ($file, $unselects) = @_; ## return 1 if ( ! -x $INITD_DIR . "/" . $file ); my $unselect; foreach $unselect ( @{$unselects} ) { return 1 if ( $file =~ /$unselect/ ); } return 0; } ## check_unselect ####################################################################### ## MODULE: read_initd_dir ## DESC: Collect files in init.d/ directory. ## IN: ## OUT: ## OP: ## STATUS: ## END: sub read_initd_dir{ my ($initd_dir) = @_; ## if ( ( $initd_dir eq "" ) || ( ! -d $initd_dir ) ) { die "No such directory: $initd_dir .\n"; } my $dh = DirHandle->new($initd_dir); if ( ! defined($dh) ) { die "No such directory: $initd_dir .\n"; } my $file; my @dirs = (); while ( defined($file = $dh->read()) ) { push(@dirs, $file); } undef $dh; return(\@dirs); } ## read_initd_dir ####################################################################### ## MODULE: read_initd_dir ## DESC: Collect files in inet.d/ directory. ## IN: ## OUT: ## OP: ## STATUS: ## END: sub create_dpkg_installed_filepath { my $pid = open(my $fd, '-|', q{dpkg-query -S '/etc/init.d/*'}) // die(qq{fork+exec of "dpkg-query -S '/etc/init.d/*'" failed: $!}); my %filepath_hash; while (my $line = <$fd>) { my ($package, $file); chomp($line); ($package, $file) = split(m/: /, $line, 2); $filepath_hash{$file} = $package; } if (!close($fd)) { die("close of dpkg-query's stdout failed: $!") if $!; my $exit_code = ($? >> 8) & 0xff; my $signal = $? & 0x7f; if ($signal) { die(qq{dpkg-query -S '/etc/init.d/*' was killed by signal ${signal}}); } else { die(qq{dpkg-query -S '/etc/init.d/*' failed with exit code ${exit_code}}); } } return(\%filepath_hash); } ## create_dpkg_installed_filepath