0

I have a bash script that invokes openconnect, which then turns around and reads 4 lines from stdin. These are (in order): group, password, authentication type, and one-time passcode.

I can programmatically get the values for the first 3, but the one-time passcode changes each time. Is there a way to write a script that can redirect stdin for the first 3 values (printf "%s\n%s\n%s\n" $group $password $auth) then have the program read the last line (the one-time passcode) as keyboard input?

#!/bin/bash

set -e

type="GROUP_SUBSTITUTED"
pass=`pass password_substituted`
auth="1"

echo -e "$type\n$pass\n$auth" |
  sudo openconnect \
  -u username_substituted \
  -i tun1 \
  vpn.substituted.url

In the above script, I pass 3 of the 4 things openconnect prompts for, but when it prompts for the 4th value (the one-time passcode) it immediately swallows an empty string instead of waiting for keyboard input.

2 Answers2

3

You can use exec to temporarily redirect a file descriptor.

exec 3<&0 < filename # save old stdin in FD 3, redirect stdin from file
command1
command2
command3
exec <&3 3<- # restore stdin from FD 3
command4

Or you can wrap some commands in braces and redirect that block:

{ 
    command1
    command2
    command3
} < filename
command4
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You can probably just use bash's read, :

read group    < instream # or however you get it
read password < instream
read auth     < instream
read code

read code will default to reading from stdio. Then you can just reference $group, $password, $auth, and $code as normal variables. read will pull in one line at a time.

If you want to create custom file/IO handlers refer to one of the existing SO questions: How do file descriptors work? for instance.

a p
  • 3,098
  • 2
  • 24
  • 46