fix(installer): fix `sudo` check for users with password or without privileges
The previous check only worked if the user could run `sudo` without typing the
password, which is almost none (I checked in Google Cloud Shell so I failed to
notice this).
This new check works whether the user has no sudo privileges, or if it has,
whether they have to type in the password or not.
It should really be easier to check if the user doesn't have privilege without
having to make them type the password.
Diff
1diff --git a/tools/install.sh b/tools/install.sh
2index d3be1ace4570e476734355fc022dbcafb87868c0..b7498fa6433e6f528d2e4392ef85f8bcce064a2d 100755
3--- a/tools/install.sh
4+++ b/tools/install.sh
5@@ -56,6 +56,28 @@ command_exists() {
6 command -v "$@" >/dev/null 2>&1
7 }
8 9+user_can_sudo() {
10+ # The following command has 3 parts:
11+ #
12+ # 1. Run `sudo` with `-v`. Does the following:
13+ # • with privilege: asks for a password immediately.
14+ # • without privilege: exits with error code 1 and prints the message:
15+ # Sorry, user <username> may not run sudo on <hostname>
16+ #
17+ # 2. Pass `-S` to `sudo` to tell it to get the password from stdin
18+ # instead of from a tty, and pipe `true` to `sudo`, since it doesn't
19+ # output anything. This will make sudo exit with error code 1 and print
20+ # the message:
21+ # sudo: no password was provided
22+ #
23+ # 3. Check for the words "may not run sudo" in the output to really tell
24+ # whether the user has privileges or not. For that we have to make sure
25+ # to run `sudo` in the default locale (with `LANG=`) so that the message
26+ # stays consistent regardless of the user's locale.
27+ #
28+ true | LANG= sudo -v -S 2>&1 | grep -q "may not run sudo"
29+}
30+
31 # The [ -t 1 ] check only works when the function is not called from
32 # a subshell (like in `$(...)` or `(...)`, so this hack redefines the
33 # function at the top level to always return false when stdout is not
34@@ -360,8 +382,16 @@ EOF
3536 echo "Changing your shell to $zsh..."
3738- # Check if user has sudo privileges and run `chsh` or `sudo chsh`
39- if LANG= sudo -l -U "$USER" 2>/dev/null | grep -q "is not allowed to run"; then
40+ # Check if user has sudo privileges to run `chsh` with or without `sudo`
41+ #
42+ # This allows the call to succeed without password on systems where the
43+ # user does not have a password but does have sudo privileges, like in
44+ # Google Cloud Shell.
45+ #
46+ # On systems that don't have a user with passwordless sudo, the user will
47+ # be prompted for the password either way, so this shouldn't cause any issues.
48+ #
49+ if user_can_sudo; then
50 chsh -s "$zsh" "$USER" # run chsh normally
51 else
52 sudo -k chsh -s "$zsh" "$USER" # -k forces the password prompt