EVERYTHING FROM THE OTHER REPO
This commit is contained in:
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if test $# -eq 0
|
||||
then
|
||||
echo "usage: $0 shellname [shellname ...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
file="$DPKG_ROOT/etc/shells"
|
||||
# I want this to be GUARANTEED to be on the same filesystem as $file
|
||||
tmpfile="${file}.tmp"
|
||||
|
||||
set -o noclobber
|
||||
|
||||
cleanup() {
|
||||
rm -f "$tmpfile"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
if ! cat "$file" > "$tmpfile"
|
||||
then
|
||||
cat 1>&2 <<EOF
|
||||
Either another instance of $0 is running, or it was previously interrupted.
|
||||
Please examine ${tmpfile} to see if it should be moved onto ${file}.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i
|
||||
do
|
||||
REALDIR="$(dirname "$(realpath -m "$i")")/$(basename "$i")"
|
||||
for j in "$i" "$REALDIR"
|
||||
do
|
||||
if ! grep -q "^${j}$" "$tmpfile"
|
||||
then
|
||||
echo "$j" >> "$tmpfile"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
chmod --reference="${file}" "${tmpfile}" || chmod $(stat -c %a "${file}") "${tmpfile}"
|
||||
chown --reference="${file}" "${tmpfile}" || chown $(stat -c %U "${file}") "${tmpfile}"
|
||||
|
||||
mv -Z "${tmpfile}" "${file}" || mv "${tmpfile}" "${file}"
|
||||
|
||||
trap "" EXIT
|
||||
exit 0
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
+190
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/perl
|
||||
# This file was preprocessed, do not edit!
|
||||
|
||||
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
BEGIN {
|
||||
eval qq{
|
||||
use File::Path qw(make_path remove_tree);
|
||||
use FileHandle;
|
||||
use Debconf::Log qw(:all);
|
||||
use Debconf::Db;
|
||||
use Debconf::Template;
|
||||
use Debconf::Config;
|
||||
use Debconf::AutoSelect qw(:all);
|
||||
use Debconf::Gettext;
|
||||
use Debconf::Path;
|
||||
};
|
||||
if ($@) {
|
||||
print STDERR "debconf: Perl may be unconfigured ($@) -- aborting\n";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (exists $ENV{DEBCONF_USE_CDEBCONF} and $ENV{DEBCONF_USE_CDEBCONF} ne '') {
|
||||
exec "/usr/lib/cdebconf/dpkg-preconfigure", @ARGV;
|
||||
}
|
||||
|
||||
chdir('/');
|
||||
|
||||
Debconf::Db->load;
|
||||
|
||||
my $apt=0;
|
||||
Debconf::Config->getopt(
|
||||
qq{Usage: dpkg-preconfigure [options] [debs]
|
||||
--apt Apt mode.},
|
||||
"apt" => \$apt,
|
||||
);
|
||||
|
||||
$|=1;
|
||||
|
||||
my @debs=@ARGV;
|
||||
@ARGV=();
|
||||
|
||||
my $have_tty=1;
|
||||
|
||||
if ($apt) {
|
||||
while (<STDIN>) {
|
||||
chomp;
|
||||
push @debs, $_ if length $_;
|
||||
}
|
||||
|
||||
exit unless @debs;
|
||||
|
||||
$have_tty=0 unless open (STDIN, "<", "/dev/tty");
|
||||
}
|
||||
elsif (! @debs) {
|
||||
print STDERR sprintf("dpkg-preconfigure: ".gettext("must specify some debs to preconfigure")), "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
my $apt_extracttemplates;
|
||||
if (-x '/usr/lib/apt/apt-extracttemplates') {
|
||||
$apt_extracttemplates = '/usr/lib/apt/apt-extracttemplates';
|
||||
} elsif (Debconf::Path::find('apt-extracttemplates')) {
|
||||
$apt_extracttemplates = 'apt-extracttemplates';
|
||||
} else {
|
||||
warn gettext("delaying package configuration, since apt-utils is not installed");
|
||||
exit;
|
||||
}
|
||||
|
||||
my $frontend=make_frontend();
|
||||
|
||||
if (! $have_tty && $frontend->need_tty) {
|
||||
print STDERR sprintf("dpkg-preconfigure: ".gettext("unable to re-open stdin: %s"), $!)."\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $tempdir='/var/cache/debconf/tmp.ci';
|
||||
remove_tree($tempdir, { safe => 1, keep_root => 1 });
|
||||
make_path($tempdir);
|
||||
|
||||
my ($package, $version, $template, $config);
|
||||
pipe(my $info_reader, my $info_writer) or die "debconf: pipe failed: $!";
|
||||
my $pid = fork();
|
||||
defined $pid or die "fork failed: $!";
|
||||
unless ($pid) {
|
||||
close($info_reader);
|
||||
|
||||
my $command_max=20000; # LINUX SPECIFIC!!
|
||||
my $static_len=length($apt_extracttemplates);
|
||||
my $len=$static_len;
|
||||
my @collect;
|
||||
my $progress=0;
|
||||
my $show_progress=($apt && @debs > 30 && -t STDERR);
|
||||
|
||||
sub apt_extracttemplates {
|
||||
my $apt_extracttemplates_pid = fork();
|
||||
my $error;
|
||||
if (not defined $apt_extracttemplates_pid) {
|
||||
$error = $!;
|
||||
} elsif (not $apt_extracttemplates_pid) {
|
||||
open(STDOUT, ">&", $info_writer)
|
||||
or die "debconf: redirect stdout failed: $!";
|
||||
exec($apt_extracttemplates, "--tempdir", $tempdir, @collect)
|
||||
or die "debconf: exec $apt_extracttemplates failed: $!";
|
||||
} else {
|
||||
my $child = waitpid($apt_extracttemplates_pid, 0);
|
||||
if ($child == -1) {
|
||||
$error = $!;
|
||||
} elsif ($?) {
|
||||
$error = $?;
|
||||
}
|
||||
}
|
||||
print STDERR sprintf("debconf: ".gettext("apt-extracttemplates failed: %s")."\n", $error) if defined $error;
|
||||
if ($show_progress) {
|
||||
$progress += @collect;
|
||||
printf "\r".gettext("Extracting templates from packages: %d%%"), $progress * 100 / @debs;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($show_progress) {
|
||||
STDOUT->autoflush(1);
|
||||
}
|
||||
foreach my $deb (@debs) {
|
||||
$len += length($deb) + 1;
|
||||
if ($len < $command_max && @collect < 30) {
|
||||
push @collect, $deb;
|
||||
}
|
||||
else {
|
||||
apt_extracttemplates();
|
||||
@collect=($deb);
|
||||
$len=$static_len + length($deb) + 1;
|
||||
}
|
||||
}
|
||||
apt_extracttemplates();
|
||||
print "\n" if $show_progress;
|
||||
exit;
|
||||
}
|
||||
close($info_writer);
|
||||
my @buffer=<$info_reader>;
|
||||
if ($apt && @buffer) {
|
||||
print gettext("Preconfiguring packages ...\n");
|
||||
}
|
||||
foreach my $line (@buffer) {
|
||||
($package, $version, $template, $config)=split /\s/, $line;
|
||||
|
||||
if (defined $template && length $template) {
|
||||
eval {
|
||||
Debconf::Template->load($template, $package)
|
||||
};
|
||||
unlink $template;
|
||||
if ($@) {
|
||||
print STDERR "$package ".sprintf(gettext("template parse error: %s"), $@)."\n";
|
||||
unlink $config;
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $line (@buffer) {
|
||||
($package, $version, $template, $config)=split /\s/, $line;
|
||||
|
||||
if (defined $config && length $config && -e $config) {
|
||||
debug user => sprintf("preconfiguring %s (%s)",$package,$version);
|
||||
chmod(0755, $config) or
|
||||
die sprintf(gettext("debconf: can't chmod: %s"), $!);
|
||||
$frontend->default_title($package);
|
||||
$frontend->info(undef);
|
||||
my $confmodule=make_confmodule($config, 'configure', $version);
|
||||
$confmodule->owner($package);
|
||||
1 while ($confmodule->communicate);
|
||||
if ($confmodule->exitcode > 0) {
|
||||
print STDERR sprintf(
|
||||
gettext("%s failed to preconfigure, with exit status %s"),
|
||||
$package, $confmodule->exitcode)."\n";
|
||||
}
|
||||
unlink $config;
|
||||
}
|
||||
}
|
||||
|
||||
$frontend->shutdown;
|
||||
|
||||
Debconf::Db->save;
|
||||
|
||||
remove_tree($tempdir, { safe => 1, keep_root => 1 });
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/perl
|
||||
# This file was preprocessed, do not edit!
|
||||
|
||||
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
if (exists $ENV{DEBCONF_USE_CDEBCONF} and $ENV{DEBCONF_USE_CDEBCONF} ne '') {
|
||||
exec "/usr/lib/cdebconf/dpkg-reconfigure", @ARGV;
|
||||
}
|
||||
|
||||
use Cwd;
|
||||
use Debconf::Db;
|
||||
use Debconf::Gettext;
|
||||
use Debconf::Template;
|
||||
use Debconf::Config;
|
||||
use Debconf::AutoSelect qw(:all);
|
||||
use Debconf::Log qw(:all);
|
||||
|
||||
Debconf::Config->priority('low');
|
||||
|
||||
my $unseen_only=0;
|
||||
my $force=0;
|
||||
my $default_priority=0;
|
||||
my $reload=1;
|
||||
Debconf::Config->getopt(
|
||||
gettext(qq{Usage: dpkg-reconfigure [options] packages
|
||||
-u, --unseen-only Show only not yet seen questions.
|
||||
--default-priority Use default priority instead of low.
|
||||
--force Force reconfiguration of broken packages.
|
||||
--no-reload Do not reload templates. (Use with caution.)}),
|
||||
"unseen-only|u" => \$unseen_only,
|
||||
"default-priority" => \$default_priority,
|
||||
"force" => \$force,
|
||||
"reload!" => \$reload,
|
||||
);
|
||||
|
||||
if ($> != 0) {
|
||||
print STDERR sprintf(gettext("%s must be run as root"), $0)."\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
Debconf::Db->load;
|
||||
|
||||
if ($default_priority) {
|
||||
Debconf::Config->priority(Debconf::Question->get('debconf/priority')->value);
|
||||
}
|
||||
|
||||
if (lc Debconf::Config->frontend eq 'noninteractive' &&
|
||||
! Debconf::Config->frontend_forced) {
|
||||
Debconf::Config->frontend('dialog');
|
||||
}
|
||||
|
||||
my $frontend=make_frontend();
|
||||
|
||||
unless ($unseen_only) {
|
||||
Debconf::Config->reshow(1);
|
||||
}
|
||||
|
||||
my @packages=@ARGV;
|
||||
if (! @packages) {
|
||||
print STDERR "$0: ".gettext("please specify a package to reconfigure")."\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
$ENV{DEBCONF_RECONFIGURE}=1;
|
||||
|
||||
my %initial_triggers=map { $_ => 1 } triggers_pending();
|
||||
|
||||
my $original_cwd=getcwd();
|
||||
|
||||
foreach my $pkg (@packages) {
|
||||
$frontend->default_title($pkg);
|
||||
$frontend->info(undef);
|
||||
|
||||
$_=`dpkg --status $pkg`;
|
||||
my ($version)=m/Version: (.*)\n/;
|
||||
my ($status)=m/Status: (.*)\n/;
|
||||
my ($package)=m/Package: (.*)\n/;
|
||||
my ($arch)=m/Architecture: (.*)\n/;
|
||||
if (! $force) {
|
||||
if (! defined $status || $status =~ m/not-installed$/) {
|
||||
print STDERR "$0: ".sprintf(gettext("%s is not installed"), $pkg)."\n";
|
||||
exit 1;
|
||||
}
|
||||
if ($status !~ m/ ok installed$/) {
|
||||
print STDERR "$0: ".sprintf(gettext("%s is broken or not fully installed"), $pkg)."\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
my @control_paths=`dpkg-query --control-path $pkg`;
|
||||
map { my $line = $_; chomp $line; $line } @control_paths;
|
||||
my $control_path = sub {
|
||||
my $file = shift;
|
||||
my $path = (grep { /\.\Q$file\E$/ } @control_paths)[0];
|
||||
chomp($path) if defined $path;
|
||||
return $path;
|
||||
};
|
||||
|
||||
if ($reload) {
|
||||
my $templates=$control_path->('templates');
|
||||
if ($templates and -e $templates) {
|
||||
Debconf::Template->load($templates, $pkg);
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $info (['prerm', 'upgrade', $version],
|
||||
['preinst', 'upgrade', $version],
|
||||
['config', 'reconfigure', $version],
|
||||
['postinst', 'configure', $version]) {
|
||||
my $script=shift @$info;
|
||||
my $path_script=$control_path->($script);
|
||||
|
||||
next unless $path_script and -x $path_script;
|
||||
|
||||
my $is_confmodule='';
|
||||
|
||||
$ENV{DPKG_MAINTSCRIPT_PACKAGE}=$package;
|
||||
$ENV{DPKG_MAINTSCRIPT_ARCH}=$arch;
|
||||
$ENV{DPKG_MAINTSCRIPT_NAME}=$script;
|
||||
|
||||
if ($script ne 'config') {
|
||||
open (my $in, "<", $path_script);
|
||||
while (<$in>) {
|
||||
if (/confmodule/i) {
|
||||
$is_confmodule=1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close $in;
|
||||
}
|
||||
|
||||
chdir('/');
|
||||
if ($script eq 'config' || $is_confmodule) {
|
||||
my $confmodule=make_confmodule($path_script, @$info);
|
||||
|
||||
$confmodule->owner($pkg);
|
||||
|
||||
1 while ($confmodule->communicate);
|
||||
|
||||
exit $confmodule->exitcode if $confmodule->exitcode > 0;
|
||||
}
|
||||
else {
|
||||
run_external($path_script, @$info);
|
||||
}
|
||||
chdir($original_cwd);
|
||||
}
|
||||
}
|
||||
|
||||
my @new_triggers;
|
||||
do {
|
||||
@new_triggers=();
|
||||
foreach my $trigpend (triggers_pending()) {
|
||||
push @new_triggers, $trigpend
|
||||
if not exists $initial_triggers{$trigpend};
|
||||
}
|
||||
if (@new_triggers) {
|
||||
chdir('/');
|
||||
run_external("dpkg", "--configure", @new_triggers);
|
||||
chdir($original_cwd);
|
||||
}
|
||||
} while (@new_triggers);
|
||||
|
||||
$frontend->shutdown;
|
||||
|
||||
Debconf::Db->save;
|
||||
|
||||
sub run_external {
|
||||
Debconf::Db->save;
|
||||
|
||||
delete $ENV{DEBIAN_HAS_FRONTEND};
|
||||
my $ret=system(@_);
|
||||
if (int($ret / 256) != 0) {
|
||||
exit int($ret / 256);
|
||||
}
|
||||
$ENV{DEBIAN_HAS_FRONTEND}=1;
|
||||
|
||||
Debconf::Db->load;
|
||||
}
|
||||
|
||||
sub triggers_pending {
|
||||
my @ret;
|
||||
local $_;
|
||||
|
||||
open (my $query, '-|', 'dpkg-query', '-W',
|
||||
'-f', '${Package} ${binary:Package}\t${Triggers-Pending}\n');
|
||||
while (<$query>) {
|
||||
chomp;
|
||||
my ($pkgnames, $triggers) = split /\t/;
|
||||
if (length $triggers) {
|
||||
my ($pkg, $binpkg) = split ' ', $pkgnames;
|
||||
push @ret, (length $binpkg ? $binpkg : $pkg);
|
||||
}
|
||||
}
|
||||
close $query;
|
||||
|
||||
return @ret;
|
||||
}
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
agetty
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+92
@@ -0,0 +1,92 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 1995 - 1998, Ian A. Murdock <imurdock@debian.org>
|
||||
# Copyright (C) 1998, 1999, Guy Maor
|
||||
# Copyright (C) 2002, Matthew Wilcox
|
||||
# Copyright (C) 2002, 2004, 2005, 2007, 2009 Clint Adams
|
||||
# Copyright (C) 2009 Manoj Srivasta
|
||||
#
|
||||
# Install the kernel on a Debian Linux system.
|
||||
#
|
||||
# This script is called from /usr/src/linux/arch/i386/boot/install.sh.
|
||||
# If you install it as /sbin/installkernel, you can do a "make install"
|
||||
# from a generic kernel source tree, and the image will be installed to
|
||||
# the proper place for Debian GNU/Linux.
|
||||
|
||||
set -e
|
||||
|
||||
# Parse the command line options. Of course, powerpc has to be all
|
||||
# different, and passes in a fifth argument, just because it is
|
||||
# "special". We ignore the fifth argument, and do not flag is as an
|
||||
# error, which it would be for any arch apart from powerpc
|
||||
if [ $# -eq 3 ] || [ $# -eq 4 ] || [ $# -eq 5 ] ; then
|
||||
img="$2"
|
||||
map="$3"
|
||||
ver="$1"
|
||||
if [ $# -ge 4 ] && [ -n "$4" ] ; then
|
||||
dir="$4"
|
||||
else
|
||||
dir="/boot"
|
||||
fi
|
||||
else
|
||||
echo "Usage: installkernel <version> <image> <System.map> <directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create backups of older versions before installing
|
||||
updatever () {
|
||||
if [ -f "$dir/$1-$ver" ] ; then
|
||||
mv "$dir/$1-$ver" "$dir/$1-$ver.old"
|
||||
fi
|
||||
|
||||
cat "$2" > "$dir/$1-$ver"
|
||||
|
||||
# This section is for backwards compatibility only
|
||||
if test -f "$dir/$1" || test -h "$dir/$1" ; then
|
||||
# The presence of "$dir/$1" is unusual in modern intallations, and
|
||||
# the results are mostly unused. So only recreate them if they
|
||||
# already existed.
|
||||
if test -L "$dir/$1" ; then
|
||||
# If we were using links, continue to use links, updating if
|
||||
# we need to.
|
||||
if [ "$(readlink -f ${dir}/${1})" = "${dir}/${1}-${ver}" ]; then
|
||||
# Yup, we need to change
|
||||
ln -sf "$1-$ver.old" "$dir/$1.old"
|
||||
else
|
||||
mv "$dir/$1" "$dir/$1.old"
|
||||
fi
|
||||
ln -sf "$1-$ver" "$dir/$1"
|
||||
else # No links
|
||||
mv "$dir/$1" "$dir/$1.old"
|
||||
cat "$2" > "$dir/$1"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
case "$(basename $img)" in
|
||||
"vmlinux"|"Image")
|
||||
img_dest=vmlinux
|
||||
;;
|
||||
*)
|
||||
img_dest=vmlinuz
|
||||
;;
|
||||
esac
|
||||
updatever $img_dest "$img"
|
||||
updatever System.map "$map"
|
||||
|
||||
config=$(dirname "$map")
|
||||
config="${config}/.config"
|
||||
if [ -f "$config" ] ; then
|
||||
updatever config "$config"
|
||||
fi
|
||||
|
||||
# If installing in the usual directory, run the same scripts that hook
|
||||
# into kernel package installation. Also make sure the PATH includes
|
||||
# /usr/sbin and /sbin, just as dpkg would.
|
||||
if [ "$dir" = "/boot" ]; then
|
||||
PATH="$PATH:/usr/sbin:/sbin" \
|
||||
run-parts --verbose --exit-on-error --arg="$ver" --arg="$dir/$img_dest-$ver" \
|
||||
/etc/kernel/postinst.d /usr/share/kernel/postinst.d
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+574
@@ -0,0 +1,574 @@
|
||||
#!/bin/sh
|
||||
# vim: ft=sh
|
||||
#
|
||||
# invoke-rc.d.sysvinit - Executes initscript actions
|
||||
#
|
||||
# SysVinit /etc/rc?.d version for Debian's sysvinit package
|
||||
#
|
||||
# Copyright (C) 2000,2001 Henrique de Moraes Holschuh <hmh@debian.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
# Constants
|
||||
RUNLEVELHELPER=/sbin/runlevel
|
||||
POLICYHELPER=$DPKG_ROOT/usr/sbin/policy-rc.d
|
||||
INITDPREFIX=/etc/init.d/
|
||||
RCDPREFIX=/etc/rc
|
||||
|
||||
# Options
|
||||
BEQUIET=
|
||||
MODE=
|
||||
ACTION=
|
||||
FALLBACK=
|
||||
NOFALLBACK=
|
||||
FORCE=
|
||||
RETRY=
|
||||
RETURNFAILURE=
|
||||
RC=
|
||||
is_systemd=
|
||||
is_openrc=
|
||||
SKIP_SYSTEMD_NATIVE=
|
||||
|
||||
# Shell options
|
||||
set +e
|
||||
|
||||
dohelp () {
|
||||
#
|
||||
# outputs help and usage
|
||||
#
|
||||
cat <<EOF
|
||||
|
||||
invoke-rc.d, Debian/SysVinit (/etc/rc?.d) initscript subsystem.
|
||||
Copyright (c) 2000,2001 Henrique de Moraes Holschuh <hmh@debian.org>
|
||||
|
||||
Usage:
|
||||
invoke-rc.d [options] <basename> <action> [extra parameters]
|
||||
|
||||
basename - Initscript ID, as per update-rc.d(8)
|
||||
action - Initscript action. Known actions are:
|
||||
start, [force-]stop, [try-]restart,
|
||||
[force-]reload, status
|
||||
WARNING: not all initscripts implement all of the above actions.
|
||||
|
||||
extra parameters are passed as is to the initscript, following
|
||||
the action (first initscript parameter).
|
||||
|
||||
Options:
|
||||
--quiet
|
||||
Quiet mode, no error messages are generated.
|
||||
--force
|
||||
Try to run the initscript regardless of policy and subsystem
|
||||
non-fatal errors.
|
||||
--try-anyway
|
||||
Try to run init script even if a non-fatal error is found.
|
||||
--disclose-deny
|
||||
Return status code 101 instead of status code 0 if
|
||||
initscript action is denied by local policy rules or
|
||||
runlevel constrains.
|
||||
--query
|
||||
Returns one of status codes 100-106, does not run
|
||||
the initscript. Implies --disclose-deny and --no-fallback.
|
||||
--no-fallback
|
||||
Ignores any fallback action requests by the policy layer.
|
||||
Warning: this is usually a very *bad* idea for any actions
|
||||
other than "start".
|
||||
--skip-systemd-native
|
||||
Exits before doing anything if a systemd environment is detected
|
||||
and the requested service is a native systemd unit.
|
||||
This is useful for maintainer scripts that want to defer systemd
|
||||
actions to deb-systemd-invoke
|
||||
--help
|
||||
Outputs help message to stdout
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
printerror () {
|
||||
#
|
||||
# prints an error message
|
||||
# $* - error message
|
||||
#
|
||||
if test x${BEQUIET} = x ; then
|
||||
echo `basename $0`: "$*" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
formataction () {
|
||||
#
|
||||
# formats a list in $* into $printaction
|
||||
# for human-friendly printing to stderr
|
||||
# and sets $naction to action or actions
|
||||
#
|
||||
printaction=`echo $* | sed 's/ /, /g'`
|
||||
if test $# -eq 1 ; then
|
||||
naction=action
|
||||
else
|
||||
naction=actions
|
||||
fi
|
||||
}
|
||||
|
||||
querypolicy () {
|
||||
#
|
||||
# queries policy database
|
||||
# returns: $RC = 104 - ok, run
|
||||
# $RC = 101 - ok, do not run
|
||||
# other - exit with status $RC, maybe run if $RETRY
|
||||
# initial status of $RC is taken into account.
|
||||
#
|
||||
|
||||
policyaction="${ACTION}"
|
||||
if test x${RC} = "x101" ; then
|
||||
if test "${ACTION}" = "start" || test "${ACTION}" = "restart" || test "${ACTION}" = "try-restart"; then
|
||||
policyaction="(${ACTION})"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${POLICYHELPER}" != x && test -x "${POLICYHELPER}" ; then
|
||||
FALLBACK=`${POLICYHELPER} ${BEQUIET} ${INITSCRIPTID} "${policyaction}" ${RL}`
|
||||
RC=$?
|
||||
formataction ${ACTION}
|
||||
case ${RC} in
|
||||
0) RC=104
|
||||
;;
|
||||
1) RC=105
|
||||
;;
|
||||
101) if test x${FORCE} != x ; then
|
||||
printerror Overriding policy-rc.d denied execution of ${printaction}.
|
||||
RC=104
|
||||
else
|
||||
printerror policy-rc.d denied execution of ${printaction}.
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test x${MODE} != xquery ; then
|
||||
case ${RC} in
|
||||
105) printerror policy-rc.d query returned \"behaviour undefined\",
|
||||
printerror assuming \"${printaction}\" is allowed.
|
||||
RC=104
|
||||
;;
|
||||
106) formataction ${FALLBACK}
|
||||
if test x${FORCE} = x ; then
|
||||
if test x${NOFALLBACK} = x ; then
|
||||
ACTION="${FALLBACK}"
|
||||
printerror executing ${naction} \"${printaction}\" instead due to policy-rc.d request.
|
||||
RC=104
|
||||
else
|
||||
printerror ignoring policy-rc.d fallback request: ${printaction}.
|
||||
RC=101
|
||||
fi
|
||||
else
|
||||
printerror ignoring policy-rc.d fallback request: ${printaction}.
|
||||
RC=104
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case ${RC} in
|
||||
100|101|102|103|104|105|106) ;;
|
||||
*) printerror WARNING: policy-rc.d returned unexpected error status ${RC}, 102 used instead.
|
||||
RC=102
|
||||
;;
|
||||
esac
|
||||
else
|
||||
if test ! -e "/sbin/init" ; then
|
||||
if test x${FORCE} != x ; then
|
||||
printerror "WARNING: No init system and policy-rc.d missing, but force specified so proceeding."
|
||||
else
|
||||
printerror "WARNING: No init system and policy-rc.d missing! Defaulting to block."
|
||||
RC=101
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x${RC} = x ; then
|
||||
RC=104
|
||||
fi
|
||||
fi
|
||||
return
|
||||
}
|
||||
|
||||
verifyparameter () {
|
||||
#
|
||||
# Verifies if $1 is not null, and $# = 1
|
||||
#
|
||||
if test $# -eq 0 ; then
|
||||
printerror syntax error: invalid empty parameter
|
||||
exit 103
|
||||
elif test $# -ne 1 ; then
|
||||
printerror syntax error: embedded blanks are not allowed in \"$*\"
|
||||
exit 103
|
||||
fi
|
||||
return
|
||||
}
|
||||
|
||||
##
|
||||
## main
|
||||
##
|
||||
|
||||
## Verifies command line arguments
|
||||
|
||||
if test $# -eq 0 ; then
|
||||
printerror syntax error: missing required parameter, --help assumed
|
||||
dohelp
|
||||
exit 103
|
||||
fi
|
||||
|
||||
state=I
|
||||
while test $# -gt 0 && test ${state} != III ; do
|
||||
case "$1" in
|
||||
--help) dohelp
|
||||
exit 0
|
||||
;;
|
||||
--quiet) BEQUIET=--quiet
|
||||
;;
|
||||
--force) FORCE=yes
|
||||
RETRY=yes
|
||||
;;
|
||||
--try-anyway)
|
||||
RETRY=yes
|
||||
;;
|
||||
--disclose-deny)
|
||||
RETURNFAILURE=yes
|
||||
;;
|
||||
--query) MODE=query
|
||||
RETURNFAILURE=yes
|
||||
;;
|
||||
--no-fallback)
|
||||
NOFALLBACK=yes
|
||||
;;
|
||||
--skip-systemd-native) SKIP_SYSTEMD_NATIVE=yes
|
||||
;;
|
||||
--*) printerror syntax error: unknown option \"$1\"
|
||||
exit 103
|
||||
;;
|
||||
*) case ${state} in
|
||||
I) verifyparameter $1
|
||||
INITSCRIPTID=$1
|
||||
;;
|
||||
II) verifyparameter $1
|
||||
ACTION=$1
|
||||
;;
|
||||
esac
|
||||
state=${state}I
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test ${state} != III ; then
|
||||
printerror syntax error: missing required parameter
|
||||
exit 103
|
||||
fi
|
||||
|
||||
#NOTE: It may not be obvious, but "$@" from this point on must expand
|
||||
#to the extra initscript parameters, except inside functions.
|
||||
|
||||
if test -d /run/systemd/system ; then
|
||||
is_systemd=1
|
||||
UNIT="${INITSCRIPTID%.sh}.service"
|
||||
elif test -f /run/openrc/softlevel ; then
|
||||
is_openrc=1
|
||||
elif test ! -f "${INITDPREFIX}${INITSCRIPTID}" ; then
|
||||
## Verifies if the given initscript ID is known
|
||||
## For sysvinit, this error is critical
|
||||
printerror unknown initscript, ${INITDPREFIX}${INITSCRIPTID} not found.
|
||||
fi
|
||||
|
||||
## Queries sysvinit for the current runlevel
|
||||
if [ ! -x ${RUNLEVELHELPER} ] || ! RL=`${RUNLEVELHELPER}`; then
|
||||
if [ -n "$is_systemd" ] && systemctl is-active --quiet sysinit.target; then
|
||||
# under systemd, the [2345] runlevels are only set upon reaching them;
|
||||
# if we are past sysinit.target (roughly equivalent to rcS), consider
|
||||
# this as runlevel 5 (this is only being used for validating rcN.d
|
||||
# symlinks, so the precise value does not matter much)
|
||||
RL=5
|
||||
else
|
||||
printerror "could not determine current runlevel"
|
||||
# this usually fails in schroots etc., ignore failure (#823611)
|
||||
RL=
|
||||
fi
|
||||
fi
|
||||
# strip off previous runlevel
|
||||
RL=${RL#* }
|
||||
|
||||
## Running ${RUNLEVELHELPER} to get current runlevel do not work in
|
||||
## the boot runlevel (scripts in /etc/rcS.d/), as /var/run/utmp
|
||||
## contains runlevel 0 or 6 (written at shutdown) at that point.
|
||||
if test x${RL} = x0 || test x${RL} = x6 ; then
|
||||
if ps -fp 1 | grep -q 'init boot' ; then
|
||||
RL=S
|
||||
fi
|
||||
fi
|
||||
|
||||
## Handles shutdown sequences VERY safely
|
||||
## i.e.: forget about policy, and do all we can to run the script.
|
||||
## BTW, why the heck are we being run in a shutdown runlevel?!
|
||||
if test x${RL} = x0 || test x${RL} = x6 ; then
|
||||
FORCE=yes
|
||||
RETRY=yes
|
||||
POLICYHELPER=
|
||||
BEQUIET=
|
||||
printerror "-----------------------------------------------------"
|
||||
printerror "WARNING: 'invoke-rc.d ${INITSCRIPTID} ${ACTION}' called"
|
||||
printerror "during shutdown sequence."
|
||||
printerror "enabling safe mode: initscript policy layer disabled"
|
||||
printerror "-----------------------------------------------------"
|
||||
fi
|
||||
|
||||
## Verifies the existance of proper S??initscriptID and K??initscriptID
|
||||
## *links* in the proper /etc/rc?.d/ directory
|
||||
verifyrclink () {
|
||||
#
|
||||
# verifies if parameters are non-dangling symlinks
|
||||
# all parameters are verified
|
||||
#
|
||||
doexit=
|
||||
while test $# -gt 0 ; do
|
||||
if test ! -L "$1" ; then
|
||||
printerror not a symlink: $1
|
||||
doexit=102
|
||||
fi
|
||||
if test ! -f "$1" ; then
|
||||
printerror dangling symlink: $1
|
||||
doexit=102
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test x${doexit} != x && test x${RETRY} = x; then
|
||||
exit ${doexit}
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
testexec () {
|
||||
#
|
||||
# returns true if any of the parameters is
|
||||
# executable (after following links)
|
||||
#
|
||||
while test $# -gt 0 ; do
|
||||
if test -x "$1" ; then
|
||||
return 0
|
||||
fi
|
||||
shift
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
RC=
|
||||
|
||||
###
|
||||
### LOCAL POLICY: Enforce that the script/unit is enabled. For SysV init
|
||||
### scripts, this needs a start entry in either runlevel S or current runlevel
|
||||
### to allow start or restart.
|
||||
if [ -n "$is_systemd" ]; then
|
||||
case ${ACTION} in
|
||||
start|restart|try-restart)
|
||||
# If a package ships both init script and systemd service file, the
|
||||
# systemd unit will not be enabled by the time invoke-rc.d is called
|
||||
# (with current debhelper sequence). This would make systemctl is-enabled
|
||||
# report the wrong status, and then the service would not be started.
|
||||
# This check cannot be removed as long as we support not passing --skip-systemd-native
|
||||
|
||||
if systemctl --quiet is-enabled "${UNIT}" 2>/dev/null || \
|
||||
ls ${RCDPREFIX}[S2345].d/S[0-9][0-9]${INITSCRIPTID} >/dev/null 2>&1; then
|
||||
RC=104
|
||||
elif systemctl --quiet is-active "${UNIT}" 2>/dev/null; then
|
||||
RC=104
|
||||
else
|
||||
RC=101
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# we do handle multiple links per runlevel
|
||||
# but we don't handle embedded blanks in link names :-(
|
||||
if test x${RL} != x ; then
|
||||
SLINK=`ls -d -Q ${RCDPREFIX}${RL}.d/S[0-9][0-9]${INITSCRIPTID} 2>/dev/null | xargs`
|
||||
KLINK=`ls -d -Q ${RCDPREFIX}${RL}.d/K[0-9][0-9]${INITSCRIPTID} 2>/dev/null | xargs`
|
||||
SSLINK=`ls -d -Q ${RCDPREFIX}S.d/S[0-9][0-9]${INITSCRIPTID} 2>/dev/null | xargs`
|
||||
|
||||
verifyrclink ${SLINK} ${KLINK} ${SSLINK}
|
||||
fi
|
||||
|
||||
case ${ACTION} in
|
||||
start|restart|try-restart)
|
||||
if testexec ${SLINK} ; then
|
||||
RC=104
|
||||
elif testexec ${KLINK} ; then
|
||||
RC=101
|
||||
elif testexec ${SSLINK} ; then
|
||||
RC=104
|
||||
else
|
||||
RC=101
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# test if /etc/init.d/initscript is actually executable
|
||||
_executable=
|
||||
if [ -n "$is_systemd" ]; then
|
||||
_executable=1
|
||||
elif testexec "${INITDPREFIX}${INITSCRIPTID}"; then
|
||||
_executable=1
|
||||
fi
|
||||
if [ "$_executable" = "1" ]; then
|
||||
if test x${RC} = x && test x${MODE} = xquery ; then
|
||||
RC=105
|
||||
fi
|
||||
|
||||
# call policy layer
|
||||
querypolicy
|
||||
case ${RC} in
|
||||
101|104)
|
||||
;;
|
||||
*) if test x${MODE} != xquery ; then
|
||||
printerror policy-rc.d returned error status ${RC}
|
||||
if test x${RETRY} = x ; then
|
||||
exit ${RC}
|
||||
else
|
||||
RC=102
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
###
|
||||
### LOCAL INITSCRIPT POLICY: non-executable initscript; deny exec.
|
||||
### (this is common sense, actually :^P )
|
||||
###
|
||||
RC=101
|
||||
fi
|
||||
|
||||
## Handles --query
|
||||
if test x${MODE} = xquery ; then
|
||||
exit ${RC}
|
||||
fi
|
||||
|
||||
|
||||
setechoactions () {
|
||||
if test $# -gt 1 ; then
|
||||
echoaction=true
|
||||
else
|
||||
echoaction=
|
||||
fi
|
||||
}
|
||||
getnextaction () {
|
||||
saction=$1
|
||||
shift
|
||||
ACTION="$@"
|
||||
}
|
||||
|
||||
## Executes initscript
|
||||
## note that $ACTION is a space-separated list of actions
|
||||
## to be attempted in order until one suceeds.
|
||||
if test x${FORCE} != x || test ${RC} -eq 104 ; then
|
||||
if [ -n "$is_systemd" ] || testexec "${INITDPREFIX}${INITSCRIPTID}" ; then
|
||||
RC=102
|
||||
setechoactions ${ACTION}
|
||||
while test ! -z "${ACTION}" ; do
|
||||
getnextaction ${ACTION}
|
||||
if test ! -z ${echoaction} ; then
|
||||
printerror executing initscript action \"${saction}\"...
|
||||
fi
|
||||
|
||||
if [ -n "$is_systemd" ]; then
|
||||
if [ "$SKIP_SYSTEMD_NATIVE" = yes ] ; then
|
||||
case $(systemctl show --value --property SourcePath "${UNIT}") in
|
||||
/etc/init.d/*)
|
||||
;;
|
||||
*)
|
||||
# We were asked to skip native systemd units, and this one was not generated by the sysv generator
|
||||
# exit cleanly
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
_state=$(systemctl -p LoadState show "${UNIT}" 2>/dev/null)
|
||||
|
||||
case $saction in
|
||||
start|restart|try-restart)
|
||||
[ "$_state" != "LoadState=masked" ] || exit 0
|
||||
systemctl $sctl_args "${saction}" "${UNIT}" && exit 0
|
||||
;;
|
||||
stop|status)
|
||||
systemctl $sctl_args "${saction}" "${UNIT}" && exit 0
|
||||
;;
|
||||
reload)
|
||||
[ "$_state" != "LoadState=masked" ] || exit 0
|
||||
_canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
|
||||
# Don't block on reload requests during bootup and shutdown
|
||||
# from units/hooks and simply schedule the task.
|
||||
if ! systemctl --quiet is-system-running; then
|
||||
sctl_args="--no-block"
|
||||
fi
|
||||
if [ "$_canreload" = "CanReload=no" ]; then
|
||||
"${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0
|
||||
else
|
||||
systemctl $sctl_args reload "${UNIT}" && exit 0
|
||||
fi
|
||||
;;
|
||||
force-stop)
|
||||
systemctl --signal=KILL kill "${UNIT}" && exit 0
|
||||
;;
|
||||
force-reload)
|
||||
[ "$_state" != "LoadState=masked" ] || exit 0
|
||||
_canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
|
||||
if [ "$_canreload" = "CanReload=no" ]; then
|
||||
systemctl $sctl_args restart "${UNIT}" && exit 0
|
||||
else
|
||||
systemctl $sctl_args reload "${UNIT}" && exit 0
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# We try to run non-standard actions by running
|
||||
# the init script directly.
|
||||
"${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
elif [ -n "$is_openrc" ]; then
|
||||
rc-service "${INITSCRIPTID}" "${saction}" && exit 0
|
||||
else
|
||||
"${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0
|
||||
fi
|
||||
RC=$?
|
||||
|
||||
if test ! -z "${ACTION}" ; then
|
||||
printerror action \"${saction}\" failed, trying next action...
|
||||
fi
|
||||
done
|
||||
printerror initscript ${INITSCRIPTID}, action \"${saction}\" failed.
|
||||
if [ -n "$is_systemd" ] && [ "$saction" = start -o "$saction" = restart -o "$saction" = "try-restart" ]; then
|
||||
systemctl status --full --no-pager "${UNIT}" || true
|
||||
fi
|
||||
exit ${RC}
|
||||
fi
|
||||
exit 102
|
||||
fi
|
||||
|
||||
## Handles --disclose-deny and denied "status" action (bug #381497)
|
||||
if test ${RC} -eq 101 && test x${RETURNFAILURE} = x ; then
|
||||
if test "x${ACTION%% *}" = "xstatus"; then
|
||||
printerror emulating initscript action \"status\", returning \"unknown\"
|
||||
RC=4
|
||||
else
|
||||
RC=0
|
||||
fi
|
||||
else
|
||||
formataction ${ACTION}
|
||||
printerror initscript ${naction} \"${printaction}\" not executed.
|
||||
fi
|
||||
|
||||
exit ${RC}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+746
@@ -0,0 +1,746 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# pam-auth-update: update /etc/pam.d/common-* from /usr/share/pam-configs
|
||||
#
|
||||
# Update the /etc/pam.d/common-* files based on the per-package profiles
|
||||
# provided in /usr/share/pam-configs/ taking into consideration user's
|
||||
# preferences (as determined via debconf prompting).
|
||||
#
|
||||
# Written by Steve Langasek <steve.langasek@canonical.com>
|
||||
#
|
||||
# Copyright (C) 2008 Canonical Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of version 3 of the GNU General Public License as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# # This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
# USA.
|
||||
|
||||
use strict;
|
||||
use Debconf::Client::ConfModule ':all';
|
||||
use IPC::Open2 'open2';
|
||||
|
||||
version('2.0');
|
||||
my $capb=capb('backup escape');
|
||||
|
||||
my $inputdir = '/usr/share/pam-configs';
|
||||
my $template = 'libpam-runtime/profiles';
|
||||
my $errtemplate = 'libpam-runtime/conflicts';
|
||||
my $overridetemplate = 'libpam-runtime/override';
|
||||
my $blanktemplate = 'libpam-runtime/no_profiles_chosen';
|
||||
my $titletemplate = 'libpam-runtime/title';
|
||||
my $confdir = '/etc/pam.d';
|
||||
my $savedir = '/var/lib/pam';
|
||||
my (%profiles, @sorted, @enabled, @conflicts, @new, %removals, %to_disable, %to_enable);
|
||||
my $force = 0;
|
||||
my $package = 0;
|
||||
my $priority = 'high';
|
||||
my %md5sums = (
|
||||
'auth' => ['8d4fe17e66ba25de16a117035d1396aa'],
|
||||
'account' => ['3c0c362eaf3421848b679d63fd48c3fa'],
|
||||
'password' => [
|
||||
'4d5c92d595a46b69cd61f18feb4c0574',
|
||||
'50fce2113dfda83ac8bdd5a6e706caec',
|
||||
'4bd7610f2e85f8ddaef79c7db7cb49eb',
|
||||
'9ba753d0824276b44bcadfee1f87b6bc',
|
||||
],
|
||||
'session' => [
|
||||
'f297c731a467822cbd86e1283263e8a3',
|
||||
'240fb92986c885b327cdb21dd641da8c',
|
||||
'4a25673e8b36f1805219027d3be02cd2',
|
||||
'9e633425b1878897695217ecaf75e204',
|
||||
],
|
||||
'session-noninteractive' => [
|
||||
'ad2b78ce1498dd637ef36469430b6ac6',
|
||||
'53c1ede0bf4c07879d3582d875917545',
|
||||
],
|
||||
);
|
||||
my @invalid_modules = ('pam_tally');
|
||||
|
||||
# use a '--force' arg to specify that /etc/pam.d should be overwritten;
|
||||
# used only on upgrades where the postinst has already determined that the
|
||||
# checksums match. Module packages other than libpam-runtime itself must
|
||||
# NEVER use this option! Document with big skullses and crossboneses! It
|
||||
# needs to be exposed for libpam-runtime because that's the package that
|
||||
# decides whether we have a pristine config to be converted, and knows
|
||||
# whether the version being upgraded from is one for which the conversion
|
||||
# should be done.
|
||||
|
||||
while ($#ARGV >= 0) {
|
||||
my $opt = shift;
|
||||
if ($opt eq '--force') {
|
||||
$force = 1;
|
||||
} elsif ($opt eq '--package') {
|
||||
$package = 1;
|
||||
} elsif ($opt eq '--root') {
|
||||
my $rootdir = shift @ARGV;
|
||||
$savedir = "${rootdir}$savedir";
|
||||
$confdir = "${rootdir}$confdir";
|
||||
$inputdir = "${rootdir}$inputdir";
|
||||
} elsif ($opt eq '--remove') {
|
||||
while ($#ARGV >= 0) {
|
||||
last if ($ARGV[0] =~ /^--/);
|
||||
$removals{shift @ARGV} = 1;
|
||||
}
|
||||
# --remove implies --package
|
||||
$package = 1 if (keys(%removals));
|
||||
} elsif ($opt eq '--disable') {
|
||||
while ($#ARGV >= 0) {
|
||||
last if ($ARGV[0] =~ /^--/);
|
||||
$to_disable{shift @ARGV} = 1;
|
||||
}
|
||||
# --disable implies --package
|
||||
$package = 1 if (keys(%to_disable));
|
||||
} elsif ($opt eq '--enable') {
|
||||
while ($#ARGV >= 0) {
|
||||
last if ($ARGV[0] =~ /^--/);
|
||||
$to_enable{shift @ARGV} = 1;
|
||||
}
|
||||
# --enable implies --package
|
||||
$package = 1 if (keys(%to_enable));
|
||||
}
|
||||
}
|
||||
|
||||
opendir(DIR, $inputdir) || die "could not open config directory: $!";
|
||||
while (my $profile = readdir(DIR)) {
|
||||
next if ($profile eq '.' || $profile eq '..' || $profile =~ m/~$/ || $profile =~ m/^#.+#$/);
|
||||
%{$profiles{$profile}} = parse_pam_profile($inputdir . '/' . $profile);
|
||||
if (defined $profiles{$profile}{'disabled'} and $profiles{$profile}{'disabled'}) {
|
||||
delete $profiles{$profile};
|
||||
}
|
||||
}
|
||||
closedir DIR;
|
||||
|
||||
$priority = 'medium' if ($package);
|
||||
|
||||
x_loadtemplatefile('/var/lib/dpkg/info/libpam-runtime.templates','libpam-runtime');
|
||||
|
||||
# always sort by priority, so we have consistency and don't have to
|
||||
# shuffle later
|
||||
@sorted = sort { $profiles{$b}->{'Priority'} <=> $profiles{$a}->{'Priority'}
|
||||
|| $b cmp $a }
|
||||
keys(%profiles);
|
||||
# If we're being called for package removal, filter out those options here
|
||||
@sorted = grep { !$removals{$_} } @sorted;
|
||||
|
||||
subst($template, 'profile_names', join(', ',@sorted));
|
||||
subst($template, 'profiles',
|
||||
join(', ', map { $profiles{$_}->{'Name'} } @sorted));
|
||||
|
||||
my $diff = diff_profiles($confdir,$savedir);
|
||||
|
||||
if ($diff) {
|
||||
@enabled = grep { !$removals{$_} } @{$diff->{'mods'}};
|
||||
} else {
|
||||
@enabled = split(/, /,get($template));
|
||||
}
|
||||
|
||||
# find out what we've seen, so we can ignore those defaults
|
||||
my %seen;
|
||||
if (-e $savedir . '/seen') {
|
||||
open(SEEN,$savedir . '/seen') or die("open(${savedir}/seen) failed: $!");
|
||||
while (<SEEN>) {
|
||||
chomp;
|
||||
$seen{$_} = 1;
|
||||
}
|
||||
close(SEEN);
|
||||
}
|
||||
|
||||
# filter out any options that are no longer available for any reason
|
||||
@enabled = grep { $profiles{$_} } @enabled;
|
||||
|
||||
# add configs to enable
|
||||
push(@enabled,
|
||||
grep { $to_enable{$_} } @sorted);
|
||||
|
||||
# Disable anything explicitly disabled
|
||||
@enabled = grep {!$to_disable{$_} } @enabled;
|
||||
# And we've seen anything we disable
|
||||
foreach my $i (keys %to_disable) {
|
||||
$seen{$i} = 1;
|
||||
}
|
||||
|
||||
# an empty module set is an error, so in that case grab all the defaults
|
||||
if (!@enabled) {
|
||||
%seen = ();
|
||||
$priority = 'high' unless ($force);
|
||||
}
|
||||
|
||||
|
||||
# add any previously-unseen configs
|
||||
push(@enabled,
|
||||
grep { $profiles{$_}->{'Default'} eq 'yes' && !$seen{$_} } @sorted);
|
||||
@enabled = sort { $profiles{$b}->{'Priority'} <=> $profiles{$a}->{'Priority'}
|
||||
|| $b cmp $a }
|
||||
@enabled;
|
||||
my $prev = '';
|
||||
@enabled = grep { $_ ne $prev && (($prev) = $_) } @enabled;
|
||||
|
||||
# Do we have any new options to show? If not, we shouldn't reprompt the
|
||||
# user, at any priority level, unless explicitly called.
|
||||
@new = grep { !$seen{$_} } @sorted;
|
||||
|
||||
settitle($titletemplate);
|
||||
|
||||
# if diff_profiles() fails, and we weren't passed a 'force' argument
|
||||
# (because this isn't an upgrade from an old version, or the checksum
|
||||
# didn't match, or we're being called by some other module package), prompt
|
||||
# the user whether to override. If the user declines (the default), we
|
||||
# never again manage this config unless manually called with '--force'.
|
||||
if (!$diff && !$force) {
|
||||
input('high',$overridetemplate);
|
||||
go();
|
||||
$force = 1 if (get($overridetemplate) eq 'true');
|
||||
}
|
||||
|
||||
if (!$diff && !$force) {
|
||||
print STDERR <<EOF;
|
||||
|
||||
pam-auth-update: Local modifications to /etc/pam.d/common-*, not updating.
|
||||
pam-auth-update: Run pam-auth-update --force to override.
|
||||
|
||||
EOF
|
||||
exit;
|
||||
}
|
||||
|
||||
umask(0022);
|
||||
|
||||
do {
|
||||
@conflicts = ();
|
||||
|
||||
if (@new || !$package) {
|
||||
fset($template,'seen','false');
|
||||
}
|
||||
set($template,join(', ', @enabled));
|
||||
|
||||
input($priority,$template);
|
||||
go();
|
||||
|
||||
@enabled = split(/, /, get($template));
|
||||
|
||||
# in case of conflicts, automatically unset the lower priority
|
||||
# item of each pair
|
||||
foreach my $elem (@enabled)
|
||||
{
|
||||
for (my $i=$#enabled; $i >= 0; $i--)
|
||||
{
|
||||
my $conflict = $enabled[$i];
|
||||
if ($profiles{$elem}->{'Conflicts'}->{$conflict}) {
|
||||
splice(@enabled,$i,1);
|
||||
my $desc = $profiles{$elem}->{'Name'}
|
||||
. ', ' . $profiles{$conflict}->{'Name'};
|
||||
push(@conflicts,$desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (@conflicts) {
|
||||
subst($errtemplate, 'conflicts', join("\\n", @conflicts));
|
||||
input('high',$errtemplate);
|
||||
}
|
||||
set($template, join(', ', @enabled));
|
||||
if (!@enabled) {
|
||||
input('high',$blanktemplate);
|
||||
# we can only end up here by user error, but give them another
|
||||
# shot at selecting a correct config anyway.
|
||||
fset($template,'seen','false');
|
||||
}
|
||||
} while (@conflicts || !@enabled);
|
||||
|
||||
# the decision has been made about what configs to use, so even if
|
||||
# something fails after this, we shouldn't go munging the default
|
||||
# options again. Save the list of known configs to /var/lib/pam.
|
||||
open(SEEN,"> $savedir/seen") or die("open(${savedir}/seen) failed: $!");
|
||||
for my $i (@sorted) {
|
||||
print SEEN "$i\n";
|
||||
}
|
||||
close(SEEN) or die("close(${savedir}/seen) failed: $!");
|
||||
|
||||
# @enabled now contains our list of profiles to use for piecing together
|
||||
# a config
|
||||
# we have:
|
||||
# - templates into which we insert the specialness
|
||||
# - magic comments denoting the beginning and end of our managed block;
|
||||
# looking at only the functional config lines would potentially let us
|
||||
# handle more cases, at the expense of much greater complexity, so
|
||||
# pass on this at least for the first round
|
||||
# - a representation of the autogenerated config stored in /var/lib/pam,
|
||||
# that we can diff against in order to account for changed options or
|
||||
# manually dropped modules
|
||||
# - a hash describing the local modifications the user has made to the
|
||||
# config; these are always preserved unless manually overridden with
|
||||
# the --force option
|
||||
|
||||
write_profiles(\%profiles, \@enabled, $confdir, $savedir, $diff, $force);
|
||||
|
||||
|
||||
# take a single line from a stock config, and merge it with the
|
||||
# information about local admin edits
|
||||
sub merge_one_line
|
||||
{
|
||||
my ($line,$diff,$count) = @_;
|
||||
my (@opts,$modline);
|
||||
|
||||
my ($adds,$removes);
|
||||
|
||||
$line =~ /^((\[[^]]+\]|\w+)\s+\S+)\s*(.*)/;
|
||||
|
||||
@opts = split(/\s+/,$3);
|
||||
$modline = $1;
|
||||
$modline =~ s/end/$count/g;
|
||||
if ($diff) {
|
||||
my $mod = $modline;
|
||||
$mod =~ s/(\[[^0-9]*)[0-9]+(.*\])/$1$2/g;
|
||||
$adds = \%{$diff->{'add'}{$mod}};
|
||||
$removes = \%{$diff->{'remove'}{$mod}};
|
||||
} else {
|
||||
$adds = $removes = undef;
|
||||
}
|
||||
|
||||
for (my $i = 0; $i <= $#opts; $i++) {
|
||||
if ($adds->{$opts[$i]}) {
|
||||
delete $adds->{$opts[$i]};
|
||||
}
|
||||
if ($removes->{$opts[$i]}) {
|
||||
splice(@opts,$i,1);
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
return $modline . " " . join(' ',@opts,sort keys(%{$adds})) . "\n";
|
||||
}
|
||||
|
||||
# return the lines for a given config name, type, and position in the stack
|
||||
sub lines_for_module_and_type
|
||||
{
|
||||
my ($profiles, $mod, $type, $modpos) = @_;
|
||||
if ($modpos == 0 && $profiles->{$mod}{$type . '-Initial'}) {
|
||||
return $profiles->{$mod}{$type . '-Initial'};
|
||||
}
|
||||
return $profiles->{$mod}{$type};
|
||||
}
|
||||
|
||||
# create a single PAM config from the indicated template and selections,
|
||||
# writing to a new file
|
||||
sub create_from_template
|
||||
{
|
||||
my($template,$dest,$profiles,$enabled,$diff,$type) = @_;
|
||||
my $state = 0;
|
||||
my $uctype = ucfirst($type);
|
||||
$type =~ s/-noninteractive//;
|
||||
|
||||
open(INPUT,$template) || return 0;
|
||||
open(OUTPUT,">$dest") || return 0;
|
||||
|
||||
while (<INPUT>) {
|
||||
if ($state == 1) {
|
||||
if (/^# here's the fallback if no module succeeds/) {
|
||||
print OUTPUT;
|
||||
$state++;
|
||||
}
|
||||
next;
|
||||
}
|
||||
if ($state == 3) {
|
||||
if (/^# end of pam-auth-update config/) {
|
||||
print OUTPUT;
|
||||
$state++;
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
print OUTPUT;
|
||||
|
||||
my ($pattern,$val);
|
||||
if ($state == 0) {
|
||||
$pattern = '^# here are the per-package modules \(the "Primary" block\)';
|
||||
$val = 'Primary';
|
||||
} elsif ($state == 2) {
|
||||
$pattern = '^# and here are more per-package modules \(the "Additional" block\)';
|
||||
$val = 'Additional';
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
|
||||
if (/$pattern/) {
|
||||
my $i = 0;
|
||||
my $count = 0;
|
||||
# first we need to get a count of lines that we're
|
||||
# going to output, so we can fix up the jumps correctly
|
||||
for my $mod (@{$enabled}) {
|
||||
my $output;
|
||||
next if (!$profiles->{$mod}{$uctype . '-Type'});
|
||||
next if $profiles->{$mod}{$uctype . '-Type'} ne $val;
|
||||
$output = lines_for_module_and_type($profiles, $mod, $uctype, $i++);
|
||||
# bypasses a perl warning about @_, sigh
|
||||
my @tmparr = split("\n+",$output);
|
||||
$count += @tmparr;
|
||||
}
|
||||
|
||||
# in case anything tries to jump in the 'additional'
|
||||
# block, let's try not to jump off the stack...
|
||||
$count-- if ($val eq 'Additional');
|
||||
|
||||
# no primary block, so output a stock pam_permit line
|
||||
# to keep the stack intact
|
||||
if ($val eq 'Primary' && $count == 0)
|
||||
{
|
||||
print OUTPUT "$type\t[default=1]\t\t\tpam_permit.so\n";
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
for my $mod (@{$enabled}) {
|
||||
my $output;
|
||||
my @output;
|
||||
next if (!$profiles->{$mod}{$uctype . '-Type'});
|
||||
next if $profiles->{$mod}{$uctype . '-Type'} ne $val;
|
||||
$output = lines_for_module_and_type($profiles, $mod, $uctype, $i++);
|
||||
for my $line (split("\n",$output)) {
|
||||
$line = merge_one_line($line,$diff,
|
||||
$count);
|
||||
print OUTPUT "$type\t$line";
|
||||
$count--;
|
||||
}
|
||||
}
|
||||
$state++;
|
||||
}
|
||||
}
|
||||
close(INPUT);
|
||||
close(OUTPUT) or die("close($dest) failed: $!");
|
||||
|
||||
if ($state < 4) {
|
||||
unlink($dest);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# take a template file, strip out everything between the markers, and
|
||||
# return the md5sum of the remaining contents. Used for testing for
|
||||
# local modifications of the boilerplate.
|
||||
sub get_template_md5sum
|
||||
{
|
||||
my($template) = @_;
|
||||
my $state = 0;
|
||||
|
||||
open(INPUT,$template) || return '';
|
||||
my($md5sum_fd,$output_fd);
|
||||
my $pid = open2($md5sum_fd, $output_fd, 'md5sum');
|
||||
return '' if (!$pid);
|
||||
|
||||
while (<INPUT>) {
|
||||
if ($state == 1) {
|
||||
if (/^# here's the fallback if no module succeeds/) {
|
||||
print $output_fd $_;
|
||||
$state++;
|
||||
}
|
||||
next;
|
||||
}
|
||||
if ($state == 3) {
|
||||
if (/^# end of pam-auth-update config/) {
|
||||
print $output_fd $_;
|
||||
$state++;
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
print $output_fd $_;
|
||||
|
||||
my ($pattern,$val);
|
||||
if ($state == 0) {
|
||||
$pattern = '^# here are the per-package modules \(the "Primary" block\)';
|
||||
} elsif ($state == 2) {
|
||||
$pattern = '^# and here are more per-package modules \(the "Additional" block\)';
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
|
||||
if (/$pattern/) {
|
||||
$state++;
|
||||
}
|
||||
}
|
||||
close(INPUT);
|
||||
close($output_fd);
|
||||
my $md5sum = <$md5sum_fd>;
|
||||
close($md5sum_fd);
|
||||
waitpid $pid, 0;
|
||||
|
||||
$md5sum = (split(/\s+/,$md5sum))[0];
|
||||
return $md5sum;
|
||||
}
|
||||
|
||||
# merge a set of module declarations into a set of new config files,
|
||||
# using the information returned from diff_profiles().
|
||||
sub write_profiles
|
||||
{
|
||||
my($profiles,$enabled,$confdir,$savedir,$diff,$force) = @_;
|
||||
|
||||
if (! -d $savedir) {
|
||||
mkdir($savedir);
|
||||
}
|
||||
|
||||
# because we can't atomically replace both /var/lib/pam/$foo and
|
||||
# /etc/pam.d/common-$foo at the same time, take steps to make this
|
||||
# somewhat robust
|
||||
for my $type ('auth','account','password','session',
|
||||
'session-noninteractive')
|
||||
{
|
||||
my $target = $confdir . '/common-' . $type;
|
||||
my $template = $target;
|
||||
my $dest = $template . '.pam-new';
|
||||
|
||||
my $diff = $diff;
|
||||
if ($diff) {
|
||||
$diff = \%{$diff->{$type}};
|
||||
}
|
||||
|
||||
# Detect if the template is unmodified, and if so, use
|
||||
# the version from /usr/share. Depends on knowing the
|
||||
# md5sums of the originals.
|
||||
my $md5sum = get_template_md5sum($template);
|
||||
for my $i (@{$md5sums{$type}}) {
|
||||
if ($md5sum eq $i) {
|
||||
$template = '/usr/share/pam/common-' . $type;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# first, write out the new config
|
||||
if (!create_from_template($template,$dest,$profiles,$enabled,
|
||||
$diff,$type))
|
||||
{
|
||||
if (!$force) {
|
||||
return 0;
|
||||
}
|
||||
$template = '/usr/share/pam/common-' . $type;
|
||||
if (!create_from_template($template,$dest,$profiles,
|
||||
$enabled,$diff,$type))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# then write out the saved config
|
||||
if (!open(OUTPUT, "> $savedir/$type.new")) {
|
||||
unlink($dest);
|
||||
return 0;
|
||||
}
|
||||
my $i = 0;
|
||||
my $uctype = ucfirst($type);
|
||||
for my $mod (@{$enabled}) {
|
||||
my $output;
|
||||
next if (!$profiles->{$mod}{$uctype . '-Type'});
|
||||
next if ($profiles->{$mod}{$uctype . '-Type'} eq 'Additional');
|
||||
|
||||
$output = lines_for_module_and_type($profiles, $mod, $uctype, $i++);
|
||||
if ($output) {
|
||||
print OUTPUT "Module: $mod\n";
|
||||
print OUTPUT $output . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# no primary block, so output a stock pam_permit line
|
||||
if ($i == 0)
|
||||
{
|
||||
print OUTPUT "Module: null\n";
|
||||
print OUTPUT "[default=1]\t\t\tpam_permit.so\n";
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
for my $mod (@{$enabled}) {
|
||||
my $output;
|
||||
next if (!$profiles->{$mod}{$uctype . '-Type'});
|
||||
next if ($profiles->{$mod}{$uctype . '-Type'} eq 'Primary');
|
||||
|
||||
$output = lines_for_module_and_type($profiles, $mod, $uctype, $i++);
|
||||
if ($output) {
|
||||
print OUTPUT "Module: $mod\n";
|
||||
print OUTPUT $output . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
close(OUTPUT) or die("close($dest) failed: $!");
|
||||
|
||||
# then do the renames, back-to-back
|
||||
# we have to use system because File::Copy is in
|
||||
# perl-modules, not perl-base
|
||||
if (-e $target && $force) {
|
||||
system('cp','-f',$target,$target . '.pam-old') == 0
|
||||
or die("cp -f ${target} ${target}.pam.old failed");
|
||||
}
|
||||
rename($dest,$target)
|
||||
or die("rename($dest, $target) failed: $!");
|
||||
rename("$savedir/${type}.new","$savedir/$type")
|
||||
or die("rename(${savedir}/${type}.new, ${savedir}/${type}) failed: $!");
|
||||
}
|
||||
|
||||
# at the end of a successful write, reset the 'seen' flag and the
|
||||
# value of the debconf override question.
|
||||
fset($overridetemplate,'seen','false');
|
||||
set($overridetemplate,'false');
|
||||
}
|
||||
|
||||
# reconcile the current config in /etc/pam.d with the saved ones in
|
||||
# /var/lib/pam; returns a hash of profile names and the corresponding
|
||||
# options that should be added/removed relative to the stock config.
|
||||
# returns false if any of the markers are missing that permit a merge,
|
||||
# or on any other failure.
|
||||
sub diff_profiles
|
||||
{
|
||||
my ($sourcedir,$savedir) = @_;
|
||||
my (%diff);
|
||||
|
||||
@{$diff{'mods'}} = ();
|
||||
# Load the saved config from /var/lib/pam, then iterate through all
|
||||
# lines in the current config that are in the managed block.
|
||||
# If anything fails here, just return immediately since we then
|
||||
# have nothing to merge; instead, the caller will decide later
|
||||
# whether to force an overwrite.
|
||||
for my $type ('auth','account','password','session',
|
||||
'session-noninteractive')
|
||||
{
|
||||
my (@saved,$modname);
|
||||
|
||||
open(SAVED,$savedir . '/' . $type) || return 0;
|
||||
while (<SAVED>) {
|
||||
if (/^Module: (.*)/) {
|
||||
$modname = $1;
|
||||
next;
|
||||
}
|
||||
chomp;
|
||||
# trim out the destination of any jumps; this saves
|
||||
# us from having to re-parse everything just to fix
|
||||
# up the jump lengths, when changes to these will
|
||||
# already show up as inconsistencies elsewhere
|
||||
s/(\[[^0-9]*)[0-9]+(.*\])/$1$2/g;
|
||||
s/(\[.*)end(.*\])/$1$2/g;
|
||||
my (@temp) = ($modname,$_);
|
||||
push(@saved,\@temp);
|
||||
}
|
||||
close(SAVED);
|
||||
|
||||
my $state = 0;
|
||||
my (@prev_opts,$curmod);
|
||||
my $realtype = $type;
|
||||
$realtype =~ s/-noninteractive//;
|
||||
|
||||
open(CURRENT,$sourcedir . '/common-' . $type) || return 0;
|
||||
while (<CURRENT>) {
|
||||
if ($state == 0) {
|
||||
$state = 1
|
||||
if (/^# here are the per-package modules \(the "Primary" block\)/);
|
||||
next;
|
||||
}
|
||||
if ($state == 1) {
|
||||
s/^$realtype\s+//;
|
||||
if (/^# here's the fallback if no module succeeds/) {
|
||||
$state = 2;
|
||||
next;
|
||||
}
|
||||
}
|
||||
if ($state == 2) {
|
||||
$state = 3
|
||||
if (/^# and here are more per-package modules \(the "Additional" block\)/);
|
||||
next;
|
||||
}
|
||||
if ($state == 3) {
|
||||
last if (/^# end of pam-auth-update config/);
|
||||
s/^$realtype\s+//;
|
||||
}
|
||||
|
||||
my $found = 0;
|
||||
my $curopts;
|
||||
while (!$found && $#saved >= 0) {
|
||||
my $line;
|
||||
($modname,$line) = @{$saved[0]};
|
||||
shift(@saved);
|
||||
$line =~ /^((\[[^]]+\]|\w+)\s+\S+)\s*(.*)/;
|
||||
@prev_opts = split(/\s+/,$3);
|
||||
$curmod = $1;
|
||||
# FIXME: the key isn't derived from the config
|
||||
# name, so collisions are possible if more
|
||||
# than one config references the same module
|
||||
|
||||
$_ =~ s/(\[[^0-9]*)[0-9]+(.*\])/$1$2/g;
|
||||
# check if this is a match for the current line
|
||||
if ($_ =~ /^\Q$curmod\E\s*(.*)$/) {
|
||||
$found = 1;
|
||||
$curopts = $1;
|
||||
push(@{$diff{'mods'}},$modname);
|
||||
}
|
||||
}
|
||||
|
||||
# there's a line in the live config that doesn't
|
||||
# correspond to anything from the saved config.
|
||||
# treat this as a failure; it's very error-prone
|
||||
# to decide what to do with an added line that
|
||||
# didn't come from a package.
|
||||
return 0 if (!$found);
|
||||
|
||||
for my $opt (split(/\s+/,$curopts)) {
|
||||
my $found = 0;
|
||||
for (my $i = 0; $i <= $#prev_opts; $i++) {
|
||||
if ($prev_opts[$i] eq $opt) {
|
||||
$found = 1;
|
||||
splice(@prev_opts,$i,1);
|
||||
}
|
||||
}
|
||||
$diff{$type}{'add'}{$curmod}{$opt} = 1 if (!$found);
|
||||
}
|
||||
for my $opt (@prev_opts) {
|
||||
$diff{$type}{'remove'}{$curmod}{$opt} = 1;
|
||||
}
|
||||
}
|
||||
close(CURRENT);
|
||||
|
||||
# we couldn't parse the config, so the merge fails
|
||||
return 0 if ($state < 3);
|
||||
}
|
||||
return \%diff;
|
||||
}
|
||||
|
||||
# simple function to parse a provided config file, in pseudo-RFC822
|
||||
# format,
|
||||
sub parse_pam_profile
|
||||
{
|
||||
my ($profile) = $_[0];
|
||||
my $fieldname;
|
||||
my %profile;
|
||||
open(PROFILE, $profile) || die "could not read profile $profile: $!";
|
||||
while (<PROFILE>) {
|
||||
if (/^(\S+):\s+(.*)\s*$/) {
|
||||
$fieldname = $1;
|
||||
# compatibility with the first implementation round;
|
||||
# "Auth-Final" is now just called "Auth"
|
||||
$fieldname =~ s/-Final$//;
|
||||
if ($fieldname eq 'Conflicts') {
|
||||
foreach my $elem (split(/, /, $2)) {
|
||||
$profile{'Conflicts'}->{$elem} = 1;
|
||||
}
|
||||
} else {
|
||||
$profile{$fieldname} = $2;
|
||||
}
|
||||
} else {
|
||||
chomp;
|
||||
s/^\s+//;
|
||||
s/\s+$//;
|
||||
$profile{$fieldname} .= "\n$_" if ($_);
|
||||
if (grep { $profile{$fieldname} =~ /$_/} @invalid_modules) {
|
||||
$profile{'disabled'} = 1;
|
||||
}
|
||||
$profile{$fieldname} =~ s/^[\n\s]+//;
|
||||
}
|
||||
}
|
||||
close(PROFILE);
|
||||
if (!defined($profile{'Session-Interactive-Only'}) or $profile{'Session-Interactive-Only'} ne 'yes') {
|
||||
$profile{'Session-noninteractive-Type'} = $profile{'Session-Type'};
|
||||
$profile{'Session-noninteractive'} = $profile{'Session'};
|
||||
$profile{'Session-noninteractive-Initial'} = $profile{'Session-Initial'};
|
||||
}
|
||||
return %profile;
|
||||
}
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
=head1 NAME
|
||||
|
||||
pam_getenv - get environment variables from /etc/environment
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
pam_getenv B<[-l] [-s]> I<env_var>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This tool will print out the value of I<env_var> from F</etc/environment>. It will attempt to expand environment variable references in the definition of I<env_var> but will fail if PAM items are expanded.
|
||||
|
||||
The B<-l> option indicates the script should return an environment variable related to default locale information.
|
||||
|
||||
The B<-s> option indicates that the script should return an
|
||||
system default environment variable.
|
||||
|
||||
Currently neither the B<-l> or B<-s> options do anything. They are
|
||||
included because future versions of Debian may have a separate
|
||||
repository for the initial environment used by init scripts and for
|
||||
system locale information. These options will allow this script to be
|
||||
a stable interface even in that environment.
|
||||
|
||||
=cut
|
||||
|
||||
# Copyright 2004 by Sam Hartman
|
||||
# This script may be copied under the terms of the GNU GPL
|
||||
# version 2, or at your option any later version.
|
||||
|
||||
use strict;
|
||||
use vars qw(*CONFIGFILE *ENVFILE);
|
||||
|
||||
sub read_line($) {
|
||||
my $fh = shift;
|
||||
my $line;
|
||||
local $_;
|
||||
line: while (<$fh>) {
|
||||
chomp;
|
||||
s/^\s+//;
|
||||
s/\#.*$//;
|
||||
next if $_ eq "";
|
||||
if (s/\\\s*$//) {
|
||||
$line .= $_;
|
||||
next line;
|
||||
}
|
||||
|
||||
$line .= $_;
|
||||
last;
|
||||
}
|
||||
$line;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub parse_line($) {
|
||||
my $var;
|
||||
my (%x, @x);
|
||||
local $_ = shift;
|
||||
return undef unless defined $_ and s/(\S+)\s//;
|
||||
$var->{Name} = $1;
|
||||
s/^\s*//;
|
||||
@x = split(/=([^"\s]\S*|"[^"]*")\s*/, $_);
|
||||
unless (scalar(@x)%2 == 0) {
|
||||
push @x, undef;
|
||||
}
|
||||
%x = @x;
|
||||
@{$var}{"Default", "Override"} =
|
||||
@x{"DEFAULT", "OVERRIDE"};
|
||||
$var;
|
||||
}
|
||||
|
||||
sub expand_val($) {
|
||||
my ($val) = @_;
|
||||
return undef unless $val;
|
||||
die "Cannot handle PAM items\n" if /(?<!\\)\@/;
|
||||
$val =~ s/(?<!\\)\$\{([^}]+)\}/$ENV{$1}||""/eg;
|
||||
return $val;
|
||||
}
|
||||
|
||||
my $lookup;
|
||||
|
||||
while ($_ = shift) {
|
||||
next if $_ eq "-s";
|
||||
next if $_ eq "-l";
|
||||
$lookup = $_;
|
||||
last;
|
||||
}
|
||||
unless (defined $lookup) {
|
||||
die "Usage: pam_getenv [-l] [-s] env_var\n";
|
||||
}
|
||||
|
||||
my %allvars;
|
||||
|
||||
open (CONFIGFILE, "/etc/security/pam_env.conf")
|
||||
or die "Cannot open environment file: $!\n";
|
||||
|
||||
while (my $var = parse_line(read_line(\*CONFIGFILE))) {
|
||||
my $val;
|
||||
unless ($val = expand_val($var->{Override})) {
|
||||
$val = expand_val($var->{Default});
|
||||
}
|
||||
$allvars{$var->{Name}} = $val;
|
||||
}
|
||||
|
||||
if (open (ENVFILE, "/etc/environment")) {
|
||||
while (my $line = read_line(\*ENVFILE)) {
|
||||
$line =~ s/^export //;
|
||||
$line =~ /(.*?)=(.+)/ or next;
|
||||
my ($var, $val) = ($1, $2);
|
||||
# This is bizarre logic (" and ' match each other, quotes are only
|
||||
# significant at the start and end of the string, and the trailing quote
|
||||
# may be omitted), but it's what pam_env does.
|
||||
$val =~ s/^["'](.*?)["']?$/$1/;
|
||||
$allvars{$var} = $val;
|
||||
}
|
||||
}
|
||||
|
||||
if (exists $allvars{$lookup}) {
|
||||
print $allvars{$lookup}, "\n";
|
||||
exit(0);
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONF=/etc/security/namespace.conf
|
||||
|
||||
# Match logic of process_line(), except lines with $HOME are ignored
|
||||
# skip the leading white space, rip off the comments, ignore empty lines
|
||||
sed -e 's/^[ ]*//g' -e 's/#.*//g' -e '/.*\$HOME.*/d' -e '/^$/d' < $CONF | \
|
||||
while read polydir instance_prefix method uids; do
|
||||
if [ ! -e "$instance_prefix" ]; then
|
||||
echo "mkdir $instance_prefix"
|
||||
mkdir --parents --mode=0 -Z "$instance_prefix"
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if test $# -eq 0
|
||||
then
|
||||
echo "usage: $0 shellname [shellname ...]" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
file="$DPKG_ROOT/etc/shells"
|
||||
# I want this to be GUARANTEED to be on the same filesystem as $file
|
||||
tmpfile="${file}.tmp"
|
||||
otmpfile="${file}.tmp2"
|
||||
|
||||
set -o noclobber
|
||||
|
||||
cleanup() {
|
||||
rm -f "$tmpfile" "$otmpfile"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
if ! cat "$file" > "$tmpfile"
|
||||
then
|
||||
cat 1>&2 <<EOF
|
||||
Either another instance of $0 is running, or it was previously interrupted.
|
||||
Please examine ${tmpfile} to see if it should be moved onto ${file}.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# this is supposed to be reliable, not pretty
|
||||
for i
|
||||
do
|
||||
REALDIR="$(dirname "$(realpath -m "$i")")/$(basename "$i")"
|
||||
for j in "$i" "$REALDIR"
|
||||
do
|
||||
grep -v "^${j}$" "$tmpfile" > "$otmpfile" || true
|
||||
mv "$otmpfile" "$tmpfile"
|
||||
done
|
||||
done
|
||||
|
||||
chmod --reference="${file}" "${tmpfile}" || chmod $(stat -c %a "${file}") "${tmpfile}"
|
||||
chown --reference="${file}" "${tmpfile}" || chown $(stat -c %U "${file}") "${tmpfile}"
|
||||
|
||||
mv -Z "${tmpfile}" "${file}" || mv "${tmpfile}" "${file}"
|
||||
|
||||
trap "" EXIT
|
||||
exit 0
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+219
@@ -0,0 +1,219 @@
|
||||
#!/bin/sh
|
||||
|
||||
###########################################################################
|
||||
# /usr/bin/service
|
||||
#
|
||||
# A convenient wrapper for the /etc/init.d init scripts.
|
||||
#
|
||||
# This script is a modified version of the /sbin/service utility found on
|
||||
# Red Hat/Fedora systems (licensed GPLv2+).
|
||||
#
|
||||
# Copyright (C) 2006 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2008 Canonical Ltd.
|
||||
# * August 2008 - Dustin Kirkland <kirkland@canonical.com>
|
||||
# Copyright (C) 2013 Michael Stapelberg <stapelberg@debian.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# On Debian GNU/Linux systems, the complete text of the GNU General
|
||||
# Public License can be found in `/usr/share/common-licenses/GPL-2'.
|
||||
###########################################################################
|
||||
|
||||
|
||||
is_ignored_file() {
|
||||
case "$1" in
|
||||
skeleton | README | *.dpkg-dist | *.dpkg-old | rc | rcS | single | reboot | bootclean.sh)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
VERSION="`basename $0` ver. 1.69~deb13u1"
|
||||
USAGE="Usage: `basename $0` < option > | --status-all | \
|
||||
[ service_name [ command | --full-restart ] ]"
|
||||
SERVICE=
|
||||
ACTION=
|
||||
SERVICEDIR="/etc/init.d"
|
||||
OPTIONS=
|
||||
is_systemd=
|
||||
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "${USAGE}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d /run/systemd/system ]; then
|
||||
is_systemd=1
|
||||
fi
|
||||
|
||||
cd /
|
||||
while [ $# -gt 0 ]; do
|
||||
case "${1}" in
|
||||
--help | -h | --h* )
|
||||
echo "${USAGE}" >&2
|
||||
exit 0
|
||||
;;
|
||||
--version | -V )
|
||||
echo "${VERSION}" >&2
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
|
||||
cd ${SERVICEDIR}
|
||||
for SERVICE in * ; do
|
||||
case "${SERVICE}" in
|
||||
functions | halt | killall | single| linuxconf| kudzu)
|
||||
;;
|
||||
*)
|
||||
if ! is_ignored_file "${SERVICE}" \
|
||||
&& [ -x "${SERVICEDIR}/${SERVICE}" ]; then
|
||||
out=$(env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" status 2>&1)
|
||||
retval=$?
|
||||
if echo "$out" | grep -Fiq "usage:"; then
|
||||
#printf " %s %-60s %s\n" "[?]" "$SERVICE:" "unknown" 1>&2
|
||||
echo " [ ? ] $SERVICE" 1>&2
|
||||
continue
|
||||
else
|
||||
if [ "$retval" = "0" -a -n "$out" ]; then
|
||||
#printf " %s %-60s %s\n" "[+]" "$SERVICE:" "running"
|
||||
echo " [ + ] $SERVICE"
|
||||
continue
|
||||
else
|
||||
#printf " %s %-60s %s\n" "[-]" "$SERVICE:" "NOT running"
|
||||
echo " [ - ] $SERVICE"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
#env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" status
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
exit 0
|
||||
elif [ $# -eq 2 -a "${2}" = "--full-restart" ]; then
|
||||
SERVICE="${1}"
|
||||
# On systems using systemd, we just perform a normal restart:
|
||||
# A restart with systemd is already a full restart.
|
||||
if [ -n "$is_systemd" ]; then
|
||||
ACTION="restart"
|
||||
else
|
||||
if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
|
||||
env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" stop
|
||||
env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" start
|
||||
exit $?
|
||||
fi
|
||||
fi
|
||||
elif [ -z "${SERVICE}" ]; then
|
||||
SERVICE="${1}"
|
||||
elif [ -z "${ACTION}" ]; then
|
||||
ACTION="${1}"
|
||||
else
|
||||
OPTIONS="${OPTIONS} ${1}"
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
run_via_sysvinit() {
|
||||
# Otherwise, use the traditional sysvinit
|
||||
if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
|
||||
exec env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" ${ACTION} ${OPTIONS}
|
||||
else
|
||||
echo "${SERVICE}: unrecognized service" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
update_openrc_started_symlinks() {
|
||||
# Skip native openrc-run files
|
||||
grep -q '^#! */\(usr/\)\?sbin/openrc-run' $SERVICEDIR/$SERVICE && return
|
||||
# maintain the symlinks of /run/openrc/started so that
|
||||
# rc-status works with the service command as well
|
||||
if [ -d /run/openrc/started ] ; then
|
||||
case "${ACTION}" in
|
||||
start)
|
||||
if [ ! -h /run/openrc/started/$SERVICE ] ; then
|
||||
ln -s $SERVICEDIR/$SERVICE /run/openrc/started/$SERVICE || true
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
rm /run/openrc/started/$SERVICE || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# When this machine is running systemd, standard service calls are turned into
|
||||
# systemctl calls.
|
||||
if [ -n "$is_systemd" ]
|
||||
then
|
||||
UNIT="${SERVICE%.sh}.service"
|
||||
|
||||
case "${ACTION}" in
|
||||
restart|status|try-restart)
|
||||
exec systemctl $sctl_args ${ACTION} ${UNIT}
|
||||
;;
|
||||
start|stop)
|
||||
# Follow the principle of least surprise for SysV people:
|
||||
# When running "service foo stop" and foo happens to be a service that
|
||||
# has one or more .socket files, we also stop the .socket units.
|
||||
# Users who need more control will use systemctl directly.
|
||||
for unit in $(systemctl list-unit-files --full --type=socket 2>/dev/null | sed -ne 's/\.socket\s*[a-z]*\s*$/.socket/p'); do
|
||||
if [ "$(systemctl -p Triggers show $unit)" = "Triggers=${UNIT}" ]; then
|
||||
systemctl $sctl_args ${ACTION} $unit
|
||||
fi
|
||||
done
|
||||
exec systemctl $sctl_args ${ACTION} ${UNIT}
|
||||
;;
|
||||
reload)
|
||||
_canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
|
||||
# Don't block on reload requests during bootup and shutdown
|
||||
# from units/hooks and simply schedule the task.
|
||||
if ! systemctl --quiet is-system-running; then
|
||||
sctl_args="--no-block"
|
||||
fi
|
||||
if [ "$_canreload" = "CanReload=no" ]; then
|
||||
# The reload action falls back to the sysv init script just in case
|
||||
# the systemd service file does not (yet) support reload for a
|
||||
# specific service.
|
||||
run_via_sysvinit
|
||||
else
|
||||
exec systemctl $sctl_args reload "${UNIT}"
|
||||
fi
|
||||
;;
|
||||
force-stop)
|
||||
exec systemctl --signal=KILL kill "${UNIT}"
|
||||
;;
|
||||
force-reload)
|
||||
_canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
|
||||
if [ "$_canreload" = "CanReload=no" ]; then
|
||||
exec systemctl $sctl_args restart "${UNIT}"
|
||||
else
|
||||
exec systemctl $sctl_args reload "${UNIT}"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# We try to run non-standard actions by running
|
||||
# the init script directly.
|
||||
run_via_sysvinit
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
update_openrc_started_symlinks
|
||||
run_via_sysvinit
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
# turn shadow passwords on on a Debian system
|
||||
|
||||
set -e
|
||||
|
||||
shadowon () {
|
||||
set -e
|
||||
|
||||
if [ -n "$DPKG_ROOT" ] \
|
||||
&& cmp "${DPKG_ROOT}/etc/passwd" "${DPKG_ROOT}/usr/share/base-passwd/passwd.master" 2>/dev/null \
|
||||
&& cmp "${DPKG_ROOT}/etc/group" "${DPKG_ROOT}/usr/share/base-passwd/group.master" 2>/dev/null; then
|
||||
# If dpkg is run with --force-script-chrootless and if /etc/passwd
|
||||
# and /etc/group are unchanged, we avoid the chroot() call by manually
|
||||
# processing the files. This produces bit-by-bit identical results
|
||||
# compared to the normal case as shown by the CI setup at
|
||||
# https://salsa.debian.org/helmutg/dpkg-root-demo/-/jobs
|
||||
for f in passwd group; do
|
||||
cp -a "${DPKG_ROOT}/etc/$f" "${DPKG_ROOT}/etc/$f-"
|
||||
done
|
||||
chmod 600 "${DPKG_ROOT}/etc/passwd-"
|
||||
sed -i 's/^\([^:]\+\):\*:/\1:x:/' "${DPKG_ROOT}/etc/group" "${DPKG_ROOT}/etc/passwd"
|
||||
[ -n "$SOURCE_DATE_EPOCH" ] && epoch=$SOURCE_DATE_EPOCH || epoch=$(date +%s)
|
||||
sed "s/^\([^:]\+\):.*/\1:*:$((epoch/60/60/24)):0:99999:7:::/" "${DPKG_ROOT}/etc/passwd" > "${DPKG_ROOT}/etc/shadow"
|
||||
sed "s/^\([^:]\+\):.*/\1:*::/" "${DPKG_ROOT}/etc/group" > "${DPKG_ROOT}/etc/gshadow"
|
||||
touch "${DPKG_ROOT}/etc/.pwd.lock"
|
||||
chmod 600 "${DPKG_ROOT}/etc/.pwd.lock"
|
||||
else
|
||||
pwck -q -r
|
||||
grpck -r
|
||||
pwconv
|
||||
grpconv
|
||||
fi
|
||||
chown root:root "${DPKG_ROOT}/etc/passwd" "${DPKG_ROOT}/etc/group"
|
||||
chmod 644 "${DPKG_ROOT}/etc/passwd" "${DPKG_ROOT}/etc/group"
|
||||
chown root:shadow "${DPKG_ROOT}/etc/shadow" "${DPKG_ROOT}/etc/gshadow"
|
||||
chmod 640 "${DPKG_ROOT}/etc/shadow" "${DPKG_ROOT}/etc/gshadow"
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
"on")
|
||||
if shadowon ; then
|
||||
echo Shadow passwords are now on.
|
||||
else
|
||||
echo Please correct the error and rerun \`$0 on\'
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"off")
|
||||
echo E: Turning shadow passwords off is no longer supported.
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo Usage: $0 on
|
||||
;;
|
||||
esac
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#! /bin/sh
|
||||
# Usage: tarcat volume1 volume2 ...
|
||||
# concatenates a GNU tar multi-volume archive into a single tar archive.
|
||||
# Author: Bruno Haible <bruno@clisp.org>, Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
# dump_type FILE [N]
|
||||
# Print type character from block N (default 0) of tar archive FILE
|
||||
dump_type() {
|
||||
dd if="$1" skip=${2:-0} bs=512 count=1 2>/dev/null |
|
||||
tr '\0' ' ' |
|
||||
cut -c157
|
||||
}
|
||||
|
||||
case `dump_type "$1"` in
|
||||
[gx]) PAX=1;;
|
||||
esac
|
||||
|
||||
cat "$1"
|
||||
shift
|
||||
for f
|
||||
do
|
||||
SKIP=0
|
||||
T=`dump_type "$f"`
|
||||
if [ -n "$PAX" ]; then
|
||||
if [ "$T" = "g" ]; then
|
||||
# Global extended header.... 2 blocks
|
||||
# Extended header........... 2 blocks
|
||||
# Ustar header.............. 1 block
|
||||
# FIXME: This calculation is will fail for very long file names.
|
||||
SKIP=5
|
||||
fi
|
||||
else
|
||||
if [ "$T" = "V" ]; then
|
||||
T=`dump_type "$f" 1`
|
||||
fi
|
||||
if [ "$T" = "M" ]; then
|
||||
SKIP=$(($SKIP + 1))
|
||||
fi
|
||||
fi
|
||||
dd skip=$SKIP if="$f"
|
||||
done
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+543
@@ -0,0 +1,543 @@
|
||||
#! /usr/bin/perl
|
||||
# vim: ft=perl
|
||||
#
|
||||
# update-rc.d Update the links in /etc/rc[0-9S].d/
|
||||
#
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
# NB: All Perl modules used here must be in perl-base. Specifically, depending
|
||||
# on modules in perl-modules is not okay! See bug #716923
|
||||
|
||||
my $initd = "/etc/init.d";
|
||||
my $etcd = "/etc/rc";
|
||||
my $dpkg_root = $ENV{DPKG_ROOT} // '';
|
||||
|
||||
# Print usage message and die.
|
||||
|
||||
sub usage {
|
||||
print STDERR "update-rc.d: error: @_\n" if ($#_ >= 0);
|
||||
print STDERR <<EOF;
|
||||
usage: update-rc.d [-f] <basename> remove
|
||||
update-rc.d [-f] <basename> defaults
|
||||
update-rc.d [-f] <basename> defaults-disabled
|
||||
update-rc.d <basename> disable|enable [S|2|3|4|5]
|
||||
-f: force
|
||||
|
||||
The disable|enable API is not stable and might change in the future.
|
||||
EOF
|
||||
exit (1);
|
||||
}
|
||||
|
||||
exit main(@ARGV);
|
||||
|
||||
sub info {
|
||||
print STDOUT "update-rc.d: @_\n";
|
||||
}
|
||||
|
||||
sub warning {
|
||||
print STDERR "update-rc.d: warning: @_\n";
|
||||
}
|
||||
|
||||
sub error {
|
||||
print STDERR "update-rc.d: error: @_\n";
|
||||
exit (1);
|
||||
}
|
||||
|
||||
sub error_code {
|
||||
my $rc = shift;
|
||||
print STDERR "update-rc.d: error: @_\n";
|
||||
exit ($rc);
|
||||
}
|
||||
|
||||
sub make_path {
|
||||
my ($path) = @_;
|
||||
my @dirs = ();
|
||||
my @path = split /\//, $path;
|
||||
map { push @dirs, $_; mkdir join('/', @dirs), 0755; } @path;
|
||||
}
|
||||
|
||||
# Given a script name, return any runlevels except 0 or 6 in which the
|
||||
# script is enabled. If that gives nothing and the script is not
|
||||
# explicitly disabled, return 6 if the script is disabled in runlevel
|
||||
# 0 or 6.
|
||||
sub script_runlevels {
|
||||
my ($scriptname) = @_;
|
||||
my @links=<"$dpkg_root/etc/rc[S12345].d/S[0-9][0-9]$scriptname">;
|
||||
if (@links) {
|
||||
return map(substr($_, 7, 1), @links);
|
||||
} elsif (! <"$dpkg_root/etc/rc[S12345].d/K[0-9][0-9]$scriptname">) {
|
||||
@links=<"$dpkg_root/etc/rc[06].d/K[0-9][0-9]$scriptname">;
|
||||
return ("6") if (@links);
|
||||
} else {
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
# Map the sysvinit runlevel to that of openrc.
|
||||
sub openrc_rlconv {
|
||||
my %rl_table = (
|
||||
"S" => "sysinit",
|
||||
"1" => "recovery",
|
||||
"2" => "default",
|
||||
"3" => "default",
|
||||
"4" => "default",
|
||||
"5" => "default",
|
||||
"6" => "off" );
|
||||
|
||||
my %seen; # return unique runlevels
|
||||
return grep !$seen{$_}++, map($rl_table{$_}, @_);
|
||||
}
|
||||
|
||||
sub systemd_reload {
|
||||
if (length $ENV{DPKG_ROOT}) {
|
||||
# if we operate on a chroot from the outside, do not attempt to reload
|
||||
return;
|
||||
}
|
||||
if (-d "/run/systemd/system") {
|
||||
system("systemctl", "daemon-reload");
|
||||
}
|
||||
}
|
||||
|
||||
# Creates the necessary links to enable/disable a SysV init script (fallback if
|
||||
# no insserv/rc-update exists)
|
||||
sub make_sysv_links {
|
||||
my ($scriptname, $action) = @_;
|
||||
|
||||
# for "remove" we cannot rely on the init script still being present, as
|
||||
# this gets called in postrm for purging. Just remove all symlinks.
|
||||
if ("remove" eq $action) { unlink($_) for
|
||||
glob("$dpkg_root/etc/rc?.d/[SK][0-9][0-9]$scriptname"); return; }
|
||||
|
||||
# if the service already has any links, do not touch them
|
||||
# numbers we don't care about, but enabled/disabled state we do
|
||||
return if glob("$dpkg_root/etc/rc?.d/[SK][0-9][0-9]$scriptname");
|
||||
|
||||
# for "defaults", parse Default-{Start,Stop} and create these links
|
||||
my ($lsb_start_ref, $lsb_stop_ref) = parse_def_start_stop("$dpkg_root/etc/init.d/$scriptname");
|
||||
my $start = $action eq "defaults-disabled" ? "K" : "S";
|
||||
foreach my $lvl (@$lsb_start_ref) {
|
||||
make_path("$dpkg_root/etc/rc$lvl.d");
|
||||
my $l = "$dpkg_root/etc/rc$lvl.d/${start}01$scriptname";
|
||||
symlink("../init.d/$scriptname", $l);
|
||||
}
|
||||
|
||||
foreach my $lvl (@$lsb_stop_ref) {
|
||||
make_path("$dpkg_root/etc/rc$lvl.d");
|
||||
my $l = "$dpkg_root/etc/rc$lvl.d/K01$scriptname";
|
||||
symlink("../init.d/$scriptname", $l);
|
||||
}
|
||||
}
|
||||
|
||||
# Creates the necessary links to enable/disable the service (equivalent of an
|
||||
# initscript) in systemd.
|
||||
sub make_systemd_links {
|
||||
my ($scriptname, $action) = @_;
|
||||
|
||||
# If called by systemctl (via systemd-sysv-install), do nothing to avoid
|
||||
# an endless loop.
|
||||
if (defined($ENV{_SKIP_SYSTEMD_NATIVE}) && $ENV{_SKIP_SYSTEMD_NATIVE} == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
# If systemctl is available, let's use that to create the symlinks.
|
||||
if (-x "$dpkg_root/bin/systemctl" || -x "$dpkg_root/usr/bin/systemctl") {
|
||||
my $systemd_root = '/';
|
||||
if ($dpkg_root ne '') {
|
||||
$systemd_root = $dpkg_root;
|
||||
}
|
||||
# Set this env var to avoid loop in systemd-sysv-install.
|
||||
local $ENV{SYSTEMCTL_SKIP_SYSV} = 1;
|
||||
# Use --quiet to mimic the old update-rc.d behaviour.
|
||||
system("systemctl", "--root=$systemd_root", "--quiet", "$action", "$scriptname");
|
||||
return;
|
||||
}
|
||||
|
||||
# In addition to the insserv call we also enable/disable the service
|
||||
# for systemd by creating the appropriate symlink in case there is a
|
||||
# native systemd service. In case systemd is not installed we do this
|
||||
# on our own instead of using systemctl.
|
||||
my $service_path;
|
||||
if (-f "/etc/systemd/system/$scriptname.service") {
|
||||
$service_path = "/etc/systemd/system/$scriptname.service";
|
||||
} elsif (-f "/lib/systemd/system/$scriptname.service") {
|
||||
$service_path = "/lib/systemd/system/$scriptname.service";
|
||||
} elsif (-f "/usr/lib/systemd/system/$scriptname.service") {
|
||||
$service_path = "/usr/lib/systemd/system/$scriptname.service";
|
||||
}
|
||||
if (defined($service_path)) {
|
||||
my $changed_sth;
|
||||
open my $fh, '<', $service_path or error("unable to read $service_path");
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
if (/^\s*WantedBy=(.+)$/i) {
|
||||
my $wants_dir = "/etc/systemd/system/$1.wants";
|
||||
my $service_link = "$wants_dir/$scriptname.service";
|
||||
if ("enable" eq $action) {
|
||||
make_path($wants_dir);
|
||||
symlink($service_path, $service_link);
|
||||
} else {
|
||||
unlink($service_link) if -e $service_link;
|
||||
}
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
}
|
||||
}
|
||||
|
||||
sub create_sequence {
|
||||
my $force = (@_);
|
||||
my $insserv = "$dpkg_root/usr/lib/insserv/insserv";
|
||||
# Fallback for older insserv package versions [2014-04-16]
|
||||
$insserv = "/sbin/insserv" if ( -x "$dpkg_root/sbin/insserv");
|
||||
# If insserv is not configured it is not fully installed
|
||||
my $insserv_installed = -x "$dpkg_root$insserv" && -e "$dpkg_root/etc/insserv.conf";
|
||||
my @opts;
|
||||
push(@opts, '-f') if $force;
|
||||
# Add force flag if initscripts is not installed
|
||||
# This enables inistcripts-less systems to not fail when a facility is missing
|
||||
unshift(@opts, '-f') unless is_initscripts_installed();
|
||||
if ( $dpkg_root ne '' ) {
|
||||
push( @opts,
|
||||
'--path', "$dpkg_root/etc/init.d",
|
||||
'--override', "$dpkg_root/etc/insserv/overrides/",
|
||||
'--insserv-dir', "$dpkg_root/etc/init.d",
|
||||
'--config', "$dpkg_root/etc/insserv.conf" );
|
||||
}
|
||||
|
||||
my $openrc_installed = -x "$dpkg_root/sbin/openrc";
|
||||
|
||||
my $sysv_insserv ={};
|
||||
$sysv_insserv->{remove} = sub {
|
||||
my ($scriptname) = @_;
|
||||
if ( -f "$dpkg_root/etc/init.d/$scriptname" ) {
|
||||
return system($insserv, @opts, "-r", $scriptname) >> 8;
|
||||
} else {
|
||||
# insserv removes all dangling symlinks, no need to tell it
|
||||
# what to look for.
|
||||
my $rc = system($insserv, @opts) >> 8;
|
||||
error_code($rc, "insserv rejected the script header") if $rc;
|
||||
}
|
||||
};
|
||||
$sysv_insserv->{defaults} = sub {
|
||||
my ($scriptname) = @_;
|
||||
if ( -f "$dpkg_root/etc/init.d/$scriptname" ) {
|
||||
my $rc = system($insserv, @opts, $scriptname) >> 8;
|
||||
error_code($rc, "insserv rejected the script header") if $rc;
|
||||
} else {
|
||||
error("initscript does not exist: /etc/init.d/$scriptname");
|
||||
}
|
||||
};
|
||||
$sysv_insserv->{defaults_disabled} = sub {
|
||||
my ($scriptname) = @_;
|
||||
return if glob("$dpkg_root/etc/rc?.d/[SK][0-9][0-9]$scriptname");
|
||||
if ( -f "$dpkg_root/etc/init.d/$scriptname" ) {
|
||||
my $rc = system($insserv, @opts, $scriptname) >> 8;
|
||||
error_code($rc, "insserv rejected the script header") if $rc;
|
||||
} else {
|
||||
error("initscript does not exist: /etc/init.d/$scriptname");
|
||||
}
|
||||
sysv_toggle("disable", $scriptname);
|
||||
};
|
||||
$sysv_insserv->{toggle} = sub {
|
||||
my ($action, $scriptname) = (shift, shift);
|
||||
sysv_toggle($action, $scriptname, @_);
|
||||
|
||||
# Call insserv to resequence modified links
|
||||
my $rc = system($insserv, @opts, $scriptname) >> 8;
|
||||
error_code($rc, "insserv rejected the script header") if $rc;
|
||||
};
|
||||
|
||||
my $sysv_plain = {};
|
||||
$sysv_plain->{remove} = sub {
|
||||
my ($scriptname) = @_;
|
||||
make_sysv_links($scriptname, "remove");
|
||||
};
|
||||
$sysv_plain->{defaults} = sub {
|
||||
my ($scriptname) = @_;
|
||||
make_sysv_links($scriptname, "defaults");
|
||||
};
|
||||
$sysv_plain->{defaults_disabled} = sub {
|
||||
my ($scriptname) = @_;
|
||||
make_sysv_links($scriptname, "defaults-disabled");
|
||||
};
|
||||
$sysv_plain->{toggle} = sub {
|
||||
my ($action, $scriptname) = (shift, shift);
|
||||
sysv_toggle($action, $scriptname, @_);
|
||||
};
|
||||
|
||||
my $systemd = {};
|
||||
$systemd->{remove} = sub {
|
||||
systemd_reload;
|
||||
};
|
||||
$systemd->{defaults} = sub {
|
||||
systemd_reload;
|
||||
};
|
||||
$systemd->{defaults_disabled} = sub {
|
||||
systemd_reload;
|
||||
};
|
||||
$systemd->{toggle} = sub {
|
||||
my ($action, $scriptname) = (shift, shift);
|
||||
make_systemd_links($scriptname, $action);
|
||||
systemd_reload;
|
||||
};
|
||||
|
||||
# Should we check exit codeS?
|
||||
my $openrc = {};
|
||||
$openrc->{remove} = sub {
|
||||
my ($scriptname) = @_;
|
||||
system("rc-update", "-qqa", "delete", $scriptname);
|
||||
|
||||
};
|
||||
$openrc->{defaults} = sub {
|
||||
my ($scriptname) = @_;
|
||||
# OpenRC does not distinguish halt and reboot. They are handled
|
||||
# by /etc/init.d/transit instead.
|
||||
return if ("halt" eq $scriptname || "reboot" eq $scriptname);
|
||||
# no need to consider default disabled runlevels
|
||||
# because everything is disabled by openrc by default
|
||||
my @rls=script_runlevels($scriptname);
|
||||
if ( @rls ) {
|
||||
system("rc-update", "add", $scriptname, openrc_rlconv(@rls));
|
||||
}
|
||||
};
|
||||
$openrc->{defaults_disabled} = sub {
|
||||
# In openrc everything is disabled by default
|
||||
};
|
||||
$openrc->{toggle} = sub {
|
||||
my ($action, $scriptname) = (shift, shift);
|
||||
my (@toggle_lvls, $start_lvls, $stop_lvls, @symlinks);
|
||||
my $lsb_header = lsb_header_for_script($scriptname);
|
||||
|
||||
# Extra arguments to disable|enable action are runlevels. If none
|
||||
# given parse LSB info for Default-Start value.
|
||||
if ($#_ >= 0) {
|
||||
@toggle_lvls = @_;
|
||||
} else {
|
||||
($start_lvls, $stop_lvls) = parse_def_start_stop($lsb_header);
|
||||
@toggle_lvls = @$start_lvls;
|
||||
if ($#toggle_lvls < 0) {
|
||||
error("$scriptname Default-Start contains no runlevels, aborting.");
|
||||
}
|
||||
}
|
||||
my %openrc_act = ( "disable" => "del", "enable" => "add" );
|
||||
system("rc-update", $openrc_act{$action}, $scriptname,
|
||||
openrc_rlconv(@toggle_lvls))
|
||||
};
|
||||
|
||||
my @sequence;
|
||||
if ($insserv_installed) {
|
||||
push @sequence, $sysv_insserv;
|
||||
}
|
||||
else {
|
||||
push @sequence, $sysv_plain;
|
||||
}
|
||||
# OpenRC has to be after sysv_{insserv,plain} because it depends on them to synchronize
|
||||
# states.
|
||||
if ($openrc_installed) {
|
||||
push @sequence, $openrc;
|
||||
}
|
||||
push @sequence, $systemd;
|
||||
|
||||
return @sequence;
|
||||
}
|
||||
|
||||
## Dependency based
|
||||
sub main {
|
||||
my @args = @_;
|
||||
my $scriptname;
|
||||
my $action;
|
||||
my $force = 0;
|
||||
|
||||
while($#args >= 0 && ($_ = $args[0]) =~ /^-/) {
|
||||
shift @args;
|
||||
if (/^-f$/) { $force = 1; next }
|
||||
if (/^-h|--help$/) { usage(); }
|
||||
usage("unknown option");
|
||||
}
|
||||
|
||||
usage("not enough arguments") if ($#args < 1);
|
||||
|
||||
my @sequence = create_sequence($force);
|
||||
|
||||
$scriptname = shift @args;
|
||||
$action = shift @args;
|
||||
if ("remove" eq $action) {
|
||||
foreach my $init (@sequence) {
|
||||
$init->{remove}->($scriptname);
|
||||
}
|
||||
} elsif ("defaults" eq $action || "start" eq $action ||
|
||||
"stop" eq $action) {
|
||||
# All start/stop/defaults arguments are discarded so emit a
|
||||
# message if arguments have been given and are in conflict
|
||||
# with Default-Start/Default-Stop values of LSB comment.
|
||||
if ("start" eq $action || "stop" eq $action) {
|
||||
cmp_args_with_defaults($scriptname, $action, @args);
|
||||
}
|
||||
foreach my $init (@sequence) {
|
||||
$init->{defaults}->($scriptname);
|
||||
}
|
||||
} elsif ("defaults-disabled" eq $action) {
|
||||
foreach my $init (@sequence) {
|
||||
$init->{defaults_disabled}->($scriptname);
|
||||
}
|
||||
} elsif ("disable" eq $action || "enable" eq $action) {
|
||||
foreach my $init (@sequence) {
|
||||
$init->{toggle}->($action, $scriptname, @args);
|
||||
}
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_def_start_stop {
|
||||
my $script = shift;
|
||||
my (%lsb, @def_start_lvls, @def_stop_lvls);
|
||||
|
||||
open my $fh, '<', $script or error("unable to read $script");
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
if (m/^### BEGIN INIT INFO\s*$/) {
|
||||
$lsb{'begin'}++;
|
||||
}
|
||||
elsif (m/^### END INIT INFO\s*$/) {
|
||||
$lsb{'end'}++;
|
||||
last;
|
||||
}
|
||||
elsif ($lsb{'begin'} and not $lsb{'end'}) {
|
||||
if (m/^# Default-Start:\s*(\S?.*)$/) {
|
||||
@def_start_lvls = split(' ', $1);
|
||||
}
|
||||
if (m/^# Default-Stop:\s*(\S?.*)$/) {
|
||||
@def_stop_lvls = split(' ', $1);
|
||||
}
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
|
||||
return (\@def_start_lvls, \@def_stop_lvls);
|
||||
}
|
||||
|
||||
sub lsb_header_for_script {
|
||||
my $name = shift;
|
||||
|
||||
foreach my $file ("/etc/insserv/overrides/$name", "/etc/init.d/$name",
|
||||
"/usr/share/insserv/overrides/$name") {
|
||||
return $file if -s $file;
|
||||
}
|
||||
|
||||
error("cannot find a LSB script for $name");
|
||||
}
|
||||
|
||||
sub cmp_args_with_defaults {
|
||||
my ($name, $act) = (shift, shift);
|
||||
my ($lsb_start_ref, $lsb_stop_ref, $arg_str, $lsb_str);
|
||||
my (@arg_start_lvls, @arg_stop_lvls, @lsb_start_lvls, @lsb_stop_lvls);
|
||||
|
||||
($lsb_start_ref, $lsb_stop_ref) = parse_def_start_stop("/etc/init.d/$name");
|
||||
@lsb_start_lvls = @$lsb_start_ref;
|
||||
@lsb_stop_lvls = @$lsb_stop_ref;
|
||||
return if (!@lsb_start_lvls and !@lsb_stop_lvls);
|
||||
|
||||
warning "start and stop actions are no longer supported; falling back to defaults";
|
||||
my $start = $act eq 'start' ? 1 : 0;
|
||||
my $stop = $act eq 'stop' ? 1 : 0;
|
||||
|
||||
# The legacy part of this program passes arguments starting with
|
||||
# "start|stop NN x y z ." but the insserv part gives argument list
|
||||
# starting with sequence number (ie. strips off leading "start|stop")
|
||||
# Start processing arguments immediately after the first seq number.
|
||||
my $argi = $_[0] eq $act ? 2 : 1;
|
||||
|
||||
while (defined $_[$argi]) {
|
||||
my $arg = $_[$argi];
|
||||
|
||||
# Runlevels 0 and 6 are always stop runlevels
|
||||
if ($arg eq 0 or $arg eq 6) {
|
||||
$start = 0; $stop = 1;
|
||||
} elsif ($arg eq 'start') {
|
||||
$start = 1; $stop = 0; $argi++; next;
|
||||
} elsif ($arg eq 'stop') {
|
||||
$start = 0; $stop = 1; $argi++; next;
|
||||
} elsif ($arg eq '.') {
|
||||
next;
|
||||
}
|
||||
push(@arg_start_lvls, $arg) if $start;
|
||||
push(@arg_stop_lvls, $arg) if $stop;
|
||||
} continue {
|
||||
$argi++;
|
||||
}
|
||||
|
||||
if ($#arg_start_lvls != $#lsb_start_lvls or
|
||||
join("\0", sort @arg_start_lvls) ne join("\0", sort @lsb_start_lvls)) {
|
||||
$arg_str = @arg_start_lvls ? "@arg_start_lvls" : "none";
|
||||
$lsb_str = @lsb_start_lvls ? "@lsb_start_lvls" : "none";
|
||||
warning "start runlevel arguments ($arg_str) do not match",
|
||||
"$name Default-Start values ($lsb_str)";
|
||||
}
|
||||
if ($#arg_stop_lvls != $#lsb_stop_lvls or
|
||||
join("\0", sort @arg_stop_lvls) ne join("\0", sort @lsb_stop_lvls)) {
|
||||
$arg_str = @arg_stop_lvls ? "@arg_stop_lvls" : "none";
|
||||
$lsb_str = @lsb_stop_lvls ? "@lsb_stop_lvls" : "none";
|
||||
warning "stop runlevel arguments ($arg_str) do not match",
|
||||
"$name Default-Stop values ($lsb_str)";
|
||||
}
|
||||
}
|
||||
|
||||
sub sysv_toggle {
|
||||
my ($act, $name) = (shift, shift);
|
||||
my (@toggle_lvls, $start_lvls, $stop_lvls, @symlinks);
|
||||
my $lsb_header = lsb_header_for_script($name);
|
||||
|
||||
# Extra arguments to disable|enable action are runlevels. If none
|
||||
# given parse LSB info for Default-Start value.
|
||||
if ($#_ >= 0) {
|
||||
@toggle_lvls = @_;
|
||||
} else {
|
||||
($start_lvls, $stop_lvls) = parse_def_start_stop($lsb_header);
|
||||
@toggle_lvls = @$start_lvls;
|
||||
if ($#toggle_lvls < 0) {
|
||||
error("$name Default-Start contains no runlevels, aborting.");
|
||||
}
|
||||
}
|
||||
|
||||
# Find symlinks in rc.d directories. Refuse to modify links in runlevels
|
||||
# not used for normal system start sequence.
|
||||
for my $lvl (@toggle_lvls) {
|
||||
if ($lvl !~ /^[S2345]$/) {
|
||||
warning("$act action will have no effect on runlevel $lvl");
|
||||
next;
|
||||
}
|
||||
push(@symlinks, $_) for glob("$dpkg_root/etc/rc$lvl.d/[SK][0-9][0-9]$name");
|
||||
}
|
||||
|
||||
if (!@symlinks) {
|
||||
error("no runlevel symlinks to modify, aborting!");
|
||||
}
|
||||
|
||||
# Toggle S/K bit of script symlink.
|
||||
for my $cur_lnk (@symlinks) {
|
||||
my $sk;
|
||||
my @new_lnk = split(//, $cur_lnk);
|
||||
|
||||
if ("disable" eq $act) {
|
||||
$sk = rindex($cur_lnk, '/S') + 1;
|
||||
next if $sk < 1;
|
||||
$new_lnk[$sk] = 'K';
|
||||
} else {
|
||||
$sk = rindex($cur_lnk, '/K') + 1;
|
||||
next if $sk < 1;
|
||||
$new_lnk[$sk] = 'S';
|
||||
}
|
||||
|
||||
rename($cur_lnk, join('', @new_lnk)) or error($!);
|
||||
}
|
||||
}
|
||||
|
||||
# Try to determine if initscripts is installed
|
||||
sub is_initscripts_installed {
|
||||
# Check if mountkernfs is available. We cannot make inferences
|
||||
# using the running init system because we may be running in a
|
||||
# chroot
|
||||
return glob("$dpkg_root/etc/rcS.d/S??mountkernfs.sh");
|
||||
}
|
||||
Executable
+156
@@ -0,0 +1,156 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright 2021 Helmut Grohne <helmut@subdivi.de>
|
||||
|
||||
# A "hashset" is a shell variable containing a sequence of elements separated
|
||||
# and surrounded by hash (#) characters. None of the elements may contain a
|
||||
# hash character. The character is thus chosen, because it initiates a comment
|
||||
# in /etc/shells. All variables ending in _SHELLS in this file are hashsets.
|
||||
|
||||
set -e
|
||||
|
||||
# Check whether hashset $1 contains element $2.
|
||||
hashset_contains() {
|
||||
case "$1" in
|
||||
*"#$2#"*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$VERBOSE" = 1 ]; then
|
||||
echo "$*"
|
||||
fi
|
||||
}
|
||||
|
||||
ROOT=${DPKG_ROOT:-}
|
||||
VERBOSE=0
|
||||
NOACT=0
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--help)
|
||||
cat <<EOF
|
||||
usage: $0 [options]
|
||||
|
||||
--no-act Do not move the actual update into place
|
||||
--verbose Be more verbose
|
||||
--root DIR Operate on the given chroot, defaults to /
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
--no-act)
|
||||
NOACT=1
|
||||
;;
|
||||
--root)
|
||||
shift
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "missing argument to --root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
ROOT=$1
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=1
|
||||
;;
|
||||
*)
|
||||
echo "unrecognized option $1" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
PKG_DIR="$ROOT/usr/share/debianutils/shells.d"
|
||||
STATE_FILE="$ROOT/var/lib/shells.state"
|
||||
TEMPLATE_ETC_FILE="$ROOT/usr/share/debianutils/shells"
|
||||
TARGET_ETC_FILE="$ROOT/etc/shells"
|
||||
SOURCE_ETC_FILE="$TARGET_ETC_FILE"
|
||||
NEW_ETC_FILE="$TARGET_ETC_FILE.tmp"
|
||||
NEW_STATE_FILE="$STATE_FILE.tmp"
|
||||
|
||||
if ! test -e "$SOURCE_ETC_FILE"; then
|
||||
SOURCE_ETC_FILE="$TEMPLATE_ETC_FILE"
|
||||
fi
|
||||
|
||||
PKG_SHELLS='#'
|
||||
LC_COLLATE=C.UTF-8 # glob in reproducible order
|
||||
for f in "$TEMPLATE_ETC_FILE" "$PKG_DIR/"*; do
|
||||
test -f "$f" || continue
|
||||
while IFS='#' read -r line _; do
|
||||
[ -n "$line" ] || continue
|
||||
if ! hashset_contains "$PKG_SHELLS" "$line"; then
|
||||
PKG_SHELLS="$PKG_SHELLS$line#"
|
||||
fi
|
||||
realshell=$(dpkg-realpath --root "$ROOT" "$(dirname "$line")")/$(basename "$line")
|
||||
if ! hashset_contains "$PKG_SHELLS" "$realshell"; then
|
||||
PKG_SHELLS="$PKG_SHELLS$realshell#"
|
||||
fi
|
||||
done < "$f"
|
||||
done
|
||||
|
||||
STATE_SHELLS='#'
|
||||
if [ -e "$STATE_FILE" ] ; then
|
||||
while IFS='#' read -r line _; do
|
||||
[ -n "$line" ] && STATE_SHELLS="$STATE_SHELLS$line#"
|
||||
done < "$STATE_FILE"
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -f "$NEW_ETC_FILE" "$NEW_STATE_FILE"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
: > "$NEW_ETC_FILE"
|
||||
ETC_SHELLS='#'
|
||||
while IFS= read -r line; do
|
||||
shell=${line%%#*}
|
||||
# copy all comment lines, packaged shells and local additions
|
||||
if [ -z "$shell" ] ||
|
||||
hashset_contains "$PKG_SHELLS" "$shell" ||
|
||||
! hashset_contains "$STATE_SHELLS" "$shell"; then
|
||||
if [ -z "$shell" ] || ! hashset_contains "$ETC_SHELLS" "$shell"; then
|
||||
echo "$line" >> "$NEW_ETC_FILE"
|
||||
ETC_SHELLS="$ETC_SHELLS$shell#"
|
||||
fi
|
||||
else
|
||||
log "removing shell $shell"
|
||||
fi
|
||||
done < "$SOURCE_ETC_FILE"
|
||||
|
||||
: > "$NEW_STATE_FILE"
|
||||
saved_IFS=$IFS
|
||||
IFS='#'
|
||||
set -f
|
||||
# shellcheck disable=SC2086 # word splitting intended, globbing disabled
|
||||
set -- ${PKG_SHELLS###}
|
||||
set +f
|
||||
IFS=$saved_IFS
|
||||
for shell; do
|
||||
echo "$shell" >> "$NEW_STATE_FILE"
|
||||
# add shells that are neither already present nor locally removed
|
||||
if ! hashset_contains "$ETC_SHELLS" "$shell" &&
|
||||
! hashset_contains "$STATE_SHELLS" "$shell"; then
|
||||
echo "$shell" >> "$NEW_ETC_FILE"
|
||||
log "adding shell $shell"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$NOACT" = 0 ]; then
|
||||
if [ -e "$STATE_FILE" ]; then
|
||||
chmod --reference="${STATE_FILE}" "${NEW_STATE_FILE}" || chmod $(stat -c %a "${STATE_FILE}") "${NEW_STATE_FILE}"
|
||||
chown --reference="${STATE_FILE}" "${NEW_STATE_FILE}" || chown $(stat -c %U "${STATE_FILE}") "${NEW_STATE_FILE}"
|
||||
else
|
||||
chmod 0644 "$NEW_STATE_FILE"
|
||||
fi
|
||||
chmod --reference="${SOURCE_ETC_FILE}" "${NEW_ETC_FILE}" || chmod $(stat -c %a "${SOURCE_ETC_FILE}") "${NEW_ETC_FILE}"
|
||||
chown --reference="${SOURCE_ETC_FILE}" "${NEW_ETC_FILE}" || chown $(stat -c %U "${SOURCE_ETC_FILE}") "${NEW_ETC_FILE}"
|
||||
sync -d "$NEW_ETC_FILE" "$NEW_STATE_FILE"
|
||||
mv -Z "${NEW_ETC_FILE}" "${TARGET_ETC_FILE}" || mv "${NEW_ETC_FILE}" "${TARGET_ETC_FILE}"
|
||||
sync "$TARGET_ETC_FILE"
|
||||
sync "$(dirname "$TARGET_ETC_FILE")"
|
||||
mv "$NEW_STATE_FILE" "$STATE_FILE"
|
||||
sync "$STATE_FILE"
|
||||
sync "$(dirname "$STATE_FILE")"
|
||||
trap "" EXIT
|
||||
fi
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
vipw
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Reference in New Issue
Block a user