]> arthur.barton.de Git - bup.git/commitdiff
Only change LC_CTYPE for bup-python itself, not sh or subprocesses
authorRob Browning <rlb@defaultvalue.org>
Thu, 26 Dec 2019 00:18:32 +0000 (18:18 -0600)
committerRob Browning <rlb@defaultvalue.org>
Sat, 11 Jan 2020 20:39:27 +0000 (14:39 -0600)
With the previous approach, bash would complain on systems that don't
provide the ISO-8859-1 locale (python always supports it), and those
complaints would break some tests.

In any case, since the original hack was only intended to affect
bup-python, try to make that the case.  Specify the LC_CTYPE only to
python via env (so bash won't see it), and then undo the environment
changes at the top of cmd/bup so they won't affect unrelated
subprocesses.

Thanks to Johannes Berg for reporting the problem and helping devise
the fix.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Tested-by: Rob Browning <rlb@defaultvalue.org>
cmd/bup
cmd/python-cmd.sh
lib/bup/compat.py

diff --git a/cmd/bup b/cmd/bup
index 8c78570dcb7e75b5fe58dc4bd4337cdbee5ea8d4..e8462dffdb406ac2db6909a09ab38ebe14908f62 100755 (executable)
--- a/cmd/bup
+++ b/cmd/bup
@@ -16,16 +16,18 @@ exec "$script_home/bup-python" "$0" ${1+"$@"}
 # end of bup preamble
 
 from __future__ import absolute_import, print_function
-import errno, re, sys, os, subprocess, signal, getopt
+import errno, getopt, os, re, select, signal, subprocess, sys
+from subprocess import PIPE
+
+from bup.compat import environ, restore_lc_env
 
 if sys.version_info[0] != 2 \
-   and not os.environ.get('BUP_ALLOW_UNEXPECTED_PYTHON_VERSION') == 'true':
+   and not environ.get(b'BUP_ALLOW_UNEXPECTED_PYTHON_VERSION') == b'true':
     print('error: bup may crash with python versions other than 2, or eat your data',
           file=sys.stderr)
     sys.exit(2)
 
-from subprocess import PIPE
-import select
+restore_lc_env()
 
 from bup import compat, path, helpers
 from bup.compat import add_ex_tb, add_ex_ctx, wrap_main
index 39ec997a48a61e9eb1c246072e303ad8fc199d2e..3cedf2ddf0785577b6d2eba46720ca113c15d46a 100644 (file)
@@ -13,27 +13,36 @@ done
 script_home="$(cd "$(dirname "$cmdpath")" && pwd -P)"
 cd "$top"
 
+bup_libdir="$script_home/../lib"  # bup_libdir will be adjusted during install
+export PYTHONPATH="$bup_libdir${PYTHONPATH:+:$PYTHONPATH}"
+
 # Force python to use ISO-8859-1 (aka Latin 1), a single-byte
 # encoding, to help avoid any manipulation of data from system APIs
 # (paths, users, groups, command line arguments, etc.)
 
-# Preserve for selective use
-if [ "${LC_CTYPE+x}" ]; then export BUP_LC_CTYPE="$LC_CTYPE"; fi
-if [ "${LC_ALL+x}" ]; then
-    export BUP_LC_ALL="$LC_ALL"
-    export LC_COLLATE="$LC_ALL"
-    export LC_MONETARY="$LC_ALL"
-    export LC_NUMERIC="$LC_ALL"
-    export LC_TIME="$LC_ALL"
-    export LC_MESSAGES="$LC_ALL"
-    unset LC_ALL
-fi
-
 export PYTHONCOERCECLOCALE=0  # Perhaps not necessary, but shouldn't hurt
-export LC_CTYPE=ISO-8859-1
 
-bup_libdir="$script_home/../lib"  # bup_libdir will be adjusted during install
-
-export PYTHONPATH="$bup_libdir${PYTHONPATH:+:$PYTHONPATH}"
+# We can't just export LC_CTYPE directly here because the locale might
+# not exist outside python, and then bash (at least) may be cranky.
 
-exec @bup_python@ "$@"
+if [ "${LC_ALL+x}" ]; then
+    unset LC_ALL
+    exec env \
+         BUP_LC_ALL="$LC_ALL" \
+         LC_COLLATE="$LC_ALL" \
+         LC_MONETARY="$LC_ALL" \
+         LC_NUMERIC="$LC_ALL" \
+         LC_TIME="$LC_ALL" \
+         LC_MESSAGES="$LC_ALL" \
+         LC_CTYPE=ISO-8859-1 \
+         @bup_python@ "$@"
+elif [ "${LC_CTYPE+x}" ]; then
+    exec env \
+         BUP_LC_CTYPE="$LC_CTYPE" \
+         LC_CTYPE=ISO-8859-1 \
+         @bup_python@ "$@"
+else
+    exec env \
+         LC_CTYPE=ISO-8859-1 \
+         @bup_python@ "$@"
+fi
index a8aead44a0bc49168945a0301a937272f9940150..f5f9dc0ffa3801632d74dbca79e3bfa67104a4a9 100644 (file)
@@ -139,6 +139,25 @@ else:  # Python 2
         assert type(y) in (bytes, buffer)
         return buffer(x) + y
 
+
+def restore_lc_env():
+    # Once we're up and running with iso-8859-1, undo the bup-python
+    # LC_CTYPE hackery, so we don't affect unrelated subprocesses.
+    bup_lc_all = environ.get(b'BUP_LC_ALL')
+    if bup_lc_all:
+        del environ[b'LC_COLLATE']
+        del environ[b'LC_CTYPE']
+        del environ[b'LC_MONETARY']
+        del environ[b'LC_NUMERIC']
+        del environ[b'LC_TIME']
+        del environ[b'LC_MESSAGES']
+        del environ[b'LC_MESSAGES']
+        environ[b'LC_ALL'] = bup_lc_all
+        return
+    bup_lc_ctype = environ.get(b'BUP_LC_CTYPE')
+    if bup_lc_ctype:
+        environ[b'LC_CTYPE'] = bup_lc_ctype
+
 def wrap_main(main):
     """Run main() and raise a SystemExit with the return value if it
     returns, pass along any SystemExit it raises, convert