21

I'm using here-documents in a bash script to automate installation and setup where a password is required many times. I enter the password once and the script passes it to the various commands. In most instances the here-document approach handles this fine. However, in one case I get this error:

Enter VNC password: stty: standard input: Inappropriate ioctl for device
Verify password:    
stty: standard input: Inappropriate ioctl for device

Please notice that this error message is from x11vnc -storepassword (not from sudo.)

My problem is related to x11vnc -storepasswd and here's my code:

sudo x11vnc -storepasswd ~/.vnc/passwd << ENDDOC
password
password
y
ENDDOC

That obviously (from the error) does not work. I would appreciate a working example of how to implement sudo x11vnc -storepasswd ~/.vnc/passwd in a script.

In case it helps, the prompts look like this:

Enter VNC password:
Verify password:
Write password to /home/user/.vnc/passwd? [y]/n n

Will using expect be a better solution? If so, how would I use it in this case? (I have never used expect before but I have looked at a lot of examples since posting this question and I cannot get expect to work on my own.)

MountainX
  • 17,948

3 Answers3

7

Another option to avoid those warning messages is to execute x11vnc in a pseudo-terminal created by a UNIX command (see Using pseudo-terminals (pty) to control interactive programs). This can be done with the script command or tools such as pdip ("Programmed Dialogue with Interactive Programs").

The warning messages on Mac OS X 10.6.8 for not providing a pseudo-terminal for x11vnc:

# x11vnc 0.9.14
sudo x11vnc -storepasswd ~/.vnc/passwd << ENDDOC
password
password
y
ENDDOC

Enter VNC password: stty: stdin isn't a terminal

Verify password:

stty: stdin isn't a terminal

Write password to ~/.vnc/passwd? [y]/n Password written to: ~/.vnc/passwd

Solutions using the script command:

# GNU script command
sudo script -q -c 'x11vnc -storepasswd ~/.vnc/passwd' <<ENDDOC /dev/null
password
password
y
ENDDOC

... or ...

printf '%s\n' 'password' 'password' 'y' | sudo script -q -c 'x11vnc -storepasswd ~/.vnc/passwd' /dev/null

FreeBSD script command

sudo script -q /dev/null x11vnc -storepasswd ~/.vnc/passwd <<ENDDOC password password y ENDDOC

kalou
  • 71
5

x11vnc expects its standard input to be a terminal, and it changes the terminal mode to avoid echoing the password as you're typing. When standard input isn't a terminal, the stty calls to turn echo off and back on fail, hence the warning that you see.

Expect is indeed a solution. Try this script (untested):

#!/usr/bin/expect -f
spawn x11vnc -storepasswd ~/.vnc/passwd
expect "password:" {send "swordfish" "\r"}
expect "password:" {send "swordfish" "\r"}
expect "Write*\?" {send "y\r"}

Alternatively, if you can, use an authentication method other than RFB (-passwdfile, or an SSL client certificate).

  • Thanks. However, the error is not coming from sudo it is coming from x11vnc -storepassword. I've been trying various expect approaches and I can't seem to get it right. An example using expect to enter a password for x11vnc -storepassword would be greatly appreciated. I'll update my question to avoid further confusion. – MountainX Jul 11 '13 at 23:25
  • @MountainX Right, sorry, I'd misread the question. Here's an expect script (completely untested). – Gilles 'SO- stop being evil' Jul 11 '13 at 23:45
  • Thank you. Your untested script gave me a few additional clues, but ultimately it also does not run without errors. The error is simply Enter VNC password: usage: send [args] string on the line expect "password:" {send "swordfish" "\r"}. I'm not sure how to fix that. Expect seems to be a very picky tool because I've been fooling with this particular problem for hours without working results yet. – MountainX Jul 12 '13 at 00:56
  • The error (above comment) was coming from send "swordfish" "\r" and it was resolved by send "swordfish\r". However, the solution still doesn't work. No password is written to ~/.vnc/passwd. I am still clueless as to why. As I said, I've been seeing this result in spite of trying everything I can think of so far. – MountainX Jul 12 '13 at 01:04
  • 1
    BTW, the same commands used in your expect solution work when entered manually. They do not work in this expect script or any variation of it that I have tried so far. – MountainX Jul 12 '13 at 01:07
  • I am getting following error: spawn: command not found, line 3: expect: command not found should I put it into .zshrc file? – alper Aug 22 '20 at 17:40
  • @alper This an an expect script, not a shell script. You need to write the code to a file, make it executable, and execute it. And you need to install expect. – Gilles 'SO- stop being evil' Aug 22 '20 at 17:49
  • I have a related error but don't understand the actual error msg: Password for brando9: stty: 'standard input': Inappropriate ioctl for device, what does it mean? – Charlie Parker Nov 25 '22 at 19:23
  • @CharlieParker Programs that want to read a password usually set the terminal in non-echo mode. If the standard input is not a terminal, they try and fail. An “ioctl” is an instruction to do something on a device other than read and write. Only terminals support the “turn off echo’ ioctl, not regular files or pipes. – Gilles 'SO- stop being evil' Nov 25 '22 at 19:43
  • @Gilles'SO-stopbeingevil' so how do I let the command accept my password? This echo $SU_PASSWORD | /afs/cs/software/bin/reauth used to work but idk what change when I last ran that command. It only let's me type it manually as a human :/ – Charlie Parker Nov 25 '22 at 19:47
  • 1
    @CharlieParker Ask this as a question. (And I personally wouldn't know, I'm not familiar with this reauth command (is that a standard thing of AFS? If not you'll need to explain where it's from).) – Gilles 'SO- stop being evil' Nov 25 '22 at 19:50
  • @Gilles'SO-stopbeingevil' sure I will. One quick question while I do that. How do you set the terminal into "echo mode"? (addressing Programs that want to read a password usually set the terminal in non-echo mode. suggestion/comment). – Charlie Parker Nov 25 '22 at 19:51
  • @CharlieParker Also, since you've found this answer, I assume you've tried to adapt the expect script and failed. Include your attempt in your question and the error messages. – Gilles 'SO- stop being evil' Nov 25 '22 at 19:51
  • @CharlieParker Echo mode is the default. You can use stty -echo or stty echo to toggle it. But that won't help you here. The program wants to talk to the terminal. – Gilles 'SO- stop being evil' Nov 25 '22 at 19:52
  • why won't stty echo won't help me here? (btw, very grateful for your responses) – Charlie Parker Nov 25 '22 at 19:56
  • I'm trying to attempt your suggested solution but when I man the spawn and expect command in my (interactive) terminal the man page says there is no entry for those commands. I'm puzzled, why is that happening? I think perhaps just a little more details in your answer would help, cuz I'm not sure what your script is concretely doing (though I expect conceptually it's finding a way to send the password to a command so that "it works" regardless if one is a tty). – Charlie Parker Nov 25 '22 at 20:10
  • ok I think the expect solution won't work because the HPC server I have doesn't let me apt install it or run sudo. So I will try your other ssh solution you suggested though I'm not sure how to start but I will try. – Charlie Parker Nov 25 '22 at 20:17
1

Sudo has an option -S that allows it to read the passwd from STDIN.

[user@evil ~]$ tail -1 /etc/shadow
tail: cannot open `/etc/shadow' for reading: Permission denied
[user@evil ~]$ echo 'P@ssW3rd!' | sudo -S tail -1 /etc/shadow
nfsnobody:!!:15891::::::

Here is an example script to demonstrate the process:

#!/bin/bash

function hr {
    perl -e 'print "-" x 80, "\n";'
}

hr
read -p "Please enter your sudo password: " -s sudopasswd
echo

hr
echo "-sudo run: tail -1 /etc/shadow"
tail -1 /etc/shadow

hr
echo "+sudo run: tail -1 /etc/shadow"
echo "$sudopasswd" | sudo -S tail -1 /etc/shadow

hr
echo "-sudo run: ls -la /root/"
ls -la /root/

hr
echo "+sudo run: ls -la /root/"
echo "$sudopasswd" | sudo -S ls -la /root/

hr

Your script, would simply need to do something like:

read -p "Please enter your sudo password: " -s sudopasswd
echo "$sudopasswd" | sudo -S x11vnc -storepasswd ~/.vnc/passwd 

This would allow you to use sudo commands in your script without having to hardcode a password.

Alternatively, you could add your user, or a subset of users, the capability to run x11vnc with sudo, without a password, but adding a line like this to /etc/sudoers:

user    ALL=(root) NOPASSWD: /path/to/x11vnc

Or create a vncusers group, add users to that group, and add the following to /etc/sudoers:

%vncusers    ALL=(root) NOPASSWD: /path/to/x11vnc
Tim Kennedy
  • 19,697