Hi Arne,
Arne Wichmann wrote:
> [Subject: Bug#538822: Ping]
Please keep in mind that these appear as emails in a crowded inbox, so
the subject line can be a good place to put valuable context.
> So, this is now unhandled for more than 9 months after it seemed almost
> fixed. What are the problemsat the moment?
Thanks for a ping. This is a complex one.
If /bin/sh is locally diverted, upgrading dash or bash within squeeze
would just not work (it produces file conflicts). So this is a
somewhat esoteric bug.
For squeeze -> wheezy upgrades:
- if bash is upgraded first, it respects the diversion and removes
/bin/sh.distrib instead of /bin/sh. Then when the updated dash is
unpacked it would respect the diversion, too and replace
/bin/sh.distrib instead of /bin/sh. No problem.
Except that postinst does not cope with local diversions, which is
easy enough to fix (fixed on the experimental branch already).
- if dash is upgraded first, there is a file conflict. No go.
So a versioned Pre-Depends by dash on bash should be enough to deal
with the unpack-time part of squeeze -> wheezy upgrades, and all
that's left is to work out what dash.postinst should do.
If we had time to update debootstrap and cdebootstrap (multistrap
requires manual work anyway so it isn't relevant here), we could even
avoid that Pre-Depends[*] and that would be the Right Thing to do.
Going one step down in invasiveness:
* Keep /bin/sh in dash's files list for the sake of the initial
bootstrap.
* In dash's preinst, ensure that /bin/sh is diverted on behalf of a
package other than dash, so whereever the sysadmin has chosen to
make /bin/sh point, the package does not have to change it (already
done in experimental).
Likewise in bash's preinst (already done in sid).
* Use existing well-tested maintainer script magic to handle upgrades
from versions in which both bash and dash had the /bin/sh symlink
in their files list.
That doesn't sound so bad to me. The main question is how to handle
UI for configuration of where the /bin/sh symlink points.
How about something along these lines (against the packaging on the
debian-experimental branch)?
---
[*] Will go into that in a separate message.
debian/dash.config | 8 +--
debian/dash.postinst | 156 ++++++++++++++++------------------------------
debian/dash.preinst.c | 20 +++---
debian/dash.templates.in | 12 +++-
4 files changed, 76 insertions(+), 120 deletions(-)
diff --git i/debian/dash.config w/debian/dash.config
index b000f2d9..7528f741 100644
--- i/debian/dash.config
+++ w/debian/dash.config
@@ -35,11 +35,5 @@ if [ "$1" = configure ] && [ -z "$2" ]; then
esac
fi
-# if "configuring and for the first time and bash is already installed"
-if [ "$1" = configure ] && [ -z "$2" ] && dpkg-query -W bash >/dev/null; then
- # bash is pulling in dash
- db_input high dash/sh || true
-else
- db_input low dash/sh || true
-fi
+db_input low dash/sh || true
db_go
diff --git i/debian/dash.postinst w/debian/dash.postinst
index 799a4237..846524c5 100644
--- i/debian/dash.postinst
+++ w/debian/dash.postinst
@@ -3,7 +3,7 @@ set -e
# $1: dfile, $2: link target, $3: distrib
replace_with_link() {
- dfile=$1; ltarget=$2; distrib=$3
+ dfile=$1; ltarget=$2; distrib=${3:-$dfile.distrib}
temp=$dfile.tmp
# Safely create a symlink to $ltarget at $dfile, first
# making a backup of $dfile (the file being diverted)
@@ -20,90 +20,6 @@ replace_with_link() {
mv -f "$temp" "$dfile"
}
-claim_binsh() {
- dfile=$1 ltarget=$2 distrib=${3:-$dfile.distrib}
- diverter=$(dpkg-divert --listpackage $dfile)
- truename=$(dpkg-divert --truename $dfile)
-
- if [ "$diverter" = dash ]; then
- # good.
- return
- fi
-
- if [ "$diverter" = LOCAL ]; then
- # The sysadmin wants it this way. Who am I to argue?
- return
- fi
-
- if [ "$diverter" != bash ]; then
- # Let dpkg-divert error out; we are not taking
- # over the diversion, unless we added it
- # ourselves on behalf of bash.
- dpkg-divert --package dash --remove $dfile
- echo "This should never be reached"
- exit 1
- fi
-
- dpkg-divert --package bash --remove $dfile
- dpkg-divert --package dash --divert $distrib --add $dfile
- # remove the old equivalent of $distrib, if it existed.
- if [ -n "$truename" ]; then
- rm -f "$truename"
- fi
- replace_with_link $dfile $ltarget $distrib
-}
-
-unclaim_binsh() {
- dfile=$1 ltarget=$2 distrib=${3:-$dfile.distrib}
- diverter=$(dpkg-divert --listpackage $dfile)
- truename=$(dpkg-divert --truename $dfile)
-
- if [ "$diverter" != dash ]; then
- # good.
- return
- fi
-
- # Donate the diversion and sh symlink to the bash package.
- ltarget=$(echo $ltarget | sed s/dash/bash/)
- dpkg-divert --package dash --remove $dfile
- dpkg-divert --package bash --divert $distrib --add $dfile
- if [ -n "$truename" ]; then
- rm -f "$truename"
- fi
- replace_with_link $dfile $ltarget $distrib
-}
-
-initial_binsh_setup() {
- dfile=$1 ltarget=$2 distrib=${3:-$dfile.distrib} ashfile=$4
- diverter=$(dpkg-divert --listpackage $dfile)
- truename=$(dpkg-divert --truename $dfile)
-
- if [ -z "$diverter" ]; then
- # good.
- return
- fi
-
- if [ "$diverter" = ash ]; then
- dpkg-divert --package ash --remove $dfile
- dpkg-divert --package dash --divert $distrib --add $dfile
-
- if [ "$truename" != "$distrib" ] && [ -e "$truename" ]; then
- mv "$truename" "$distrib"
- fi
- replace_with_link $dfile $ltarget
- return
- fi
-
- if
- [ -h $dfile ] &&
- [ -f $dfile ] &&
- [ -f $ashfile ] &&
- cmp $dfile $ashfile
- then
- replace_with_link $dfile $ltarget
- fi
-}
-
add_shell() {
if ! type add-shell > /dev/null 2>&1; then
return
@@ -112,36 +28,74 @@ add_shell() {
add-shell /bin/dash
}
+# This should never happen.
+if [ ! -e /bin/sh ]; then
+ ln -s dash /bin/sh
+fi
+
+test "$1" = 'configure' || exit 0
+
debconf=
if [ -f /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
debconf=yes
fi
-if [ "$1" = configure ] && [ -z "$2" ]; then
- initial_binsh_setup /bin/sh dash '' /bin/ash
- initial_binsh_setup /usr/share/man/man1/sh.1.gz dash.1.gz \
- /usr/share/man/man1/sh.distrib.1.gz \
- /usr/share/man/man1/ash.1.gz
- add_shell
-elif [ "$1" = configure ] && dpkg --compare-versions "$2" lt 0.4.18; then
+if [ -z "$2" ] || dpkg --compare-versions "$2" lt 0.4.18; then
add_shell
fi
+shell=
if [ $debconf ]; then
db_get dash/sh
- if [ "$RET" = true ]; then
- claim_binsh /bin/sh dash
- claim_binsh /usr/share/man/man1/sh.1.gz dash.1.gz \
- /usr/share/man/man1/sh.distrib.1.gz
- else
- unclaim_binsh /bin/sh dash
- unclaim_binsh /usr/share/man/man1/sh.1.gz dash.1.gz \
- /usr/share/man/man1/sh.distrib.1.gz
+ shell=$RET
+fi
+
+case $shell in
+/bin/sh | sh)
+ # Leave /bin/sh as is.
+ shell=
+ ;;
+true)
+ # "Use dash as the default system shell (/bin/sh)?" Yes.
+ shell=dash
+ ;;
+false)
+ # "Use dash as the default system shell (/bin/sh)?" No.
+ shell=bash
+ ;;
+esac
+
+case $shell in
+/*)
+ if [ ! -f "$shell" ] || [ ! -x "$shell" ]; then
+ echo >&2 "dash.postinst: shell $shell not found or unusable"
+ exit 1
fi
+ shellname=${shell##*/}
+ replace_with_link /bin/sh $shell
+ replace_with_link /usr/share/man/man1/sh.1.gz $shellname.1.gz \
+ /usr/share/man/man1/sh.distrib.1.gz
+ ;;
+"")
+ # Nothing to do (hoorah!)
+ ;;
+*)
+ if [ ! -f "/bin/$shell" ] || [ ! -x "/bin/$shell" ]; then
+ echo >&2 "dash.postinst: shell $shell not found or unusable"
+ exit 1
+ fi
+ shellname=${shell##*/}
+ replace_with_link /bin/sh $shell
+ replace_with_link /usr/share/man/man1/sh.1.gz $shellname.1.gz \
+ /usr/share/man/man1/sh.distrib.1.gz
+ ;;
+esac
+
+if [ $debconf ]; then
+ db_set dash/sh ''
fi
-test "$1" = 'configure' || exit 0
test -x /usr/bin/update-menus || exit 0
test -z "$2" || dpkg --compare-versions "$2" lt 0.5.2-3 || exit 0
exec update-menus
diff --git i/debian/dash.preinst.c w/debian/dash.preinst.c
index 966b65de..200c1be4 100644
--- i/debian/dash.preinst.c
+++ w/debian/dash.preinst.c
@@ -47,7 +47,6 @@ static void reset_diversion(const char *package, const char
*file,
"--divert", distrib, "--add", file, NULL};
run(remove_old_diversion);
run(new_diversion);
- copy(file, distrib);
}
static int undiverted(const char *path)
@@ -78,6 +77,17 @@ static int undiverted(const char *path)
int main(int argc, char *argv[])
{
+ /* /bin/sh needs to point to a valid target. */
+ if (access("/bin/sh", X_OK)) {
+ copy("/bin/sh", "/bin/sh.distrib")
+ copy("/usr/share/man/man1/sh.1.gz",
+ "/usr/share/man/man1/sh.distrib.1.gz");
+
+ force_symlink("dash", "/bin/sh", "/bin/sh.temp");
+ force_symlink("dash.1.gz", "/usr/share/man/man1/sh.1.gz",
+ "/usr/share/man/man1/sh.1.gz.temp");
+ }
+
/*
* To help with bootstrapping Debian, the dash package includes
* symlinks for /bin/sh and the sh(1) manpage in its data.tar.
@@ -95,13 +105,5 @@ int main(int argc, char *argv[])
if (undiverted("/usr/share/man/man1/sh.1.gz"))
reset_diversion("bash", "/usr/share/man/man1/sh.1.gz",
"/usr/share/man/man1/sh.distrib.1.gz");
-
- /* /bin/sh needs to point to a valid target. */
- if (access("/bin/sh", X_OK)) {
- force_symlink("dash", "/bin/sh", "/bin/sh.temp");
- force_symlink("dash.1.gz", "/usr/share/man/man1/sh.1.gz",
- "/usr/share/man/man1/sh.1.gz.temp");
- }
-
return 0;
}
diff --git i/debian/dash.templates.in w/debian/dash.templates.in
index dfaf25db..9d9961b6 100644
--- i/debian/dash.templates.in
+++ w/debian/dash.templates.in
@@ -7,14 +7,20 @@
# Even minor modifications require translation updates and such
# changes should be coordinated with translators and reviewers.
Template: dash/sh
-Type: boolean
-Default: true
-_Description: Use dash as the default system shell (/bin/sh)?
+Type: string
+_Description: What shell should be the default system shell (/bin/sh)?
The system shell is the default command interpreter for shell scripts.
.
Using dash as the system shell will improve the system's overall
performance. It does not alter the shell presented to interactive
users.
+ .
+ For historical reasons, 'true' is a synonym for dash and 'false'
+ means bash.
+ .
+ If this value is left empty (recommended), the target of the /bin/sh
+ symlink is left unchanged. The target of that symbolic link is
+ completely under the control of the system admin.
# _Description: Install dash as /bin/sh?
# The default /bin/sh shell on Debian and Debian-based systems is bash.
# .
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]