If you try to sign into your
1password.com teams account with their
op command-line utility, you may find it a little reluctant to oblige:
→ op signin [ERROR] 2022/04/09 15:01:52 Output of 'op signin' is meant to be executed by your terminal. Please run 'eval $(op signin)'. You can use the '-f' flag to override this warning.
While you can use
-f (as the error hints), you may wonder how it is that
op signin knows that you haven't run it in an evaluating subshell. If I had to hazard a guess, it's looking at something like
isatty(3), a POSIX-mandated function that checks if a given file descriptor is a terminal (or teletype) devices. If you you call
isatty(0), you can tell if the input channel (
stdin) is attached to an interactive terminal.
In bash, you can use the
test -t (or
[ -t) predicate to determine if a file descriptor (by number) is hooked up to a tty device:
#!/bin/sh if test -t 0; then echo "Hello, Interactive User!" else echo "Hello, Batch User!" fi
0 is the numeric index of the first open file descriptor for a process; by POSIX semantics, the first three of these are (in order): standard input, standard output, and standard error.
test -t approach is easily fooled however; consider these two shell sessions:
$ ./is-a-tty Hello, Interactive User! $ echo 'something' | ./is-a-tty Hello, Batch User!
In the second invocation, echoing something into the process causes that process' standard input to be reopened to the output of the
echo command (its standard output). At that point, it ceases to be a terminal device and we follow the else branch.
With this knowledge, we can now workaround
op signin's little trick:
$ op signin | cat export OP_SESSION_ABCDEFGHIJKLMNOPQRSTUVWXYZ="... secret redacted ..." # This command is meant to be used with your shell's eval function. # Run 'eval $(op signin account)' to sign in to your 1Password account. # Use the --raw flag to only output the session token.
cat UNIX utility, when called with no arguments, prints its standard input to its standard output. It's a bit of an I/O no-op. Crucially, it robs
op signin of its tty output device, sidestepping the issue we first ran into)