4

I just noticed that no matter which cryptsetup FDs are forwarded to /dev/null it still shows prompt for password. For example this still shows prompt:

cryptsetyp luksOpen /dev/sdXY name >/dev/null 2>/dev/null

How can you display in terminal message that cannot be redirected to file using standard redirection?

I'd like to get such functionality in bash script as I use stdout to return result to mother script but I'd still like to display interactive prompt - is it possible to do so using bash?

  • You're asking for an explanation, so a solution wouldn't address that. However, if you want to circumvent password input from terminal and force cryptsetup to read the password from standard input, use the --key-file=- option. This however won't strip trailing newline characters like it does for terminal password sources. – David Foerster Oct 21 '17 at 20:04
3

Presumably, It writes directly to /dev/tty (at any rate, you can get the same behavior)

#!/bin/bash

# set up the new file descriptor
# I have no idea why this needs exec, please tell me.
exec 3> /dev/tty

# test
echo "Stdout"
echo "Stderr" >&2
echo "Directly to tty" >&3

alternatively, you can simply do:

echo "Directly to tty" >/dev/tty

$ ./foo.sh >/dev/null 2>/dev/null
Directly to tty 

read still works if you do this.

  • what does exec 3> /file do? In a sense why there's eval. – Lapsio Oct 21 '17 at 19:49
  • It sets up the new file descriptor. Editing to clarify. – SIGSTACKFAULT Oct 21 '17 at 19:51
  • I mean why not just 3> /file without exec. – Lapsio Oct 21 '17 at 19:53
  • 1
    I haven't the foggiest idea. It just doesn't work. – SIGSTACKFAULT Oct 21 '17 at 19:54
  • 1
    Exec is required because it's part of the shell syntax (e.g. run help exec in bash). Normally a redirection only affects a single command's file descriptors. You are redirecting the shell's file descriptors, which is a distinct operation. – Kevin Oct 21 '17 at 20:18
6

If you strace it, you will probably see that it uses /dev/tty directly.

...
open("/dev/tty", O_RDWR)                = 6
ioctl(6, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(6, "Enter passphrase for .......: ", 30) = 30
ioctl(6, SNDCTL_TMR_CONTINUE or TCSETSF, {B38400 opost isig icanon -echo ...}) = 0
...

In the source code (utils_crypt.c):

static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
                long timeout)
{
[...]
        /* Read and write to /dev/tty if available */
        infd = open("/dev/tty", O_RDWR);
        if (infd == -1) {
                infd = STDIN_FILENO;
                outfd = STDERR_FILENO;
        } else
                outfd = infd;

        if (tcgetattr(infd, &orig))
                goto out_err;

So it tests for /dev/tty by opening it, and if that works it uses that. If it fails, it falls back to regular stdin, stdout, and then you wouldn't see the prompt anymore.

As for the /dev/tty, it's the terminal of the process, for more detail see man 4 tty.

  • Relevant xkcd: xkcd.com/292 – SIGSTACKFAULT Oct 21 '17 at 19:50
  • @Blacksilver I wouldn't say it's bad practice. It probably has something to do with security. After all it's really critical app security wise. The harder it is to hijack output the better. – Lapsio Oct 21 '17 at 19:56
  • Yeah, I know. I'm just doing my obligatory duty. – SIGSTACKFAULT Oct 21 '17 at 19:58
  • And now I don't know why exactly did they use tty directly and what are security implications and I can't find the answer. My whole day is ruined now in blind desire for useless knowledge... – Lapsio Oct 21 '17 at 20:03
  • @Blacksilver: Goto is required in languages like C which don't have C++ destructors nor the try/finally of higher-level languages. If you don't use goto, you have to duplicate your cleanup logic, which is messy and error-prone. – Kevin Oct 21 '17 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.