Originally, "tty" had two definitions: the hardware (now the emulator) and the driver (interfaced through /dev/pty* or /dev/tty*).
The hardware/emulator was/is responsible for:
- Taking a stream of data and presenting it; this included interpreting control sequences like "move cursor left", "blinking cursor", "clear-screen" although these control sequences were often different among manufacturers.
- Sending keycodes for keys typed by the user; most of these were standard ASCII characters, but some terminals sent propriety keycodes for even standard keys.
The 'tty' driver was responsible for:
- Managing the buffering, in raw or canonical mode; for example, buffering a line of characters until Enter is pressed.
- Managing the control flow; e.g. being able to stop/continue with Cntl-s/Cntl-q.
- Translating propriety keycodes to standard ASCII, where applicable.
- Intercepting certain control characters (like Cntl-c and Backspace) and processing them appropriately (send SIGINT on a Cntl-c or signal an EOF on Cntl-d.
- Canonical display of characters, for example, if
echo
is turned off, then do not send feedback (character typed) back to the terminal.
The terminfo and termcap databases managed what terminal control characters should be sent for an operation (like 'clear-screen'). These control sequences were/are not interpreted by the driver, but by the hardware/emulator.
The flip-flopping between "must have mode 777" and "must have mode 775" is caused by strace
.
screen
is usually a setuid or setgid program. It gains extra privileges when it is executed, which is uses to create socket files and/or modify utmp.
When a process is being traced, setuid and setgid are disabled. The tracing process, controlled by the less-privileged user, can take over the traced process so it must run without its extra privileges to avoid giving the original user too much power.
screen
detects whether it is being run with setuid privileges, setgid privileges, or neither, and adjusts its expectation of the directory permissions accordingly.
So this creates a class of problems that can't be easily debugged with strace
.
But if you're root, there is a workaround! If the tracing process is running as root, then the traced process can gain privileges normally. So here's what you do:
- Open 2 new terminals
- In the first terminal, log in to the remote machine as root
- In the second terminal, log in to the remote machine as normal user
- Use
ps
to get the PID of the normal user's shell process in the second terminal
- In the first terminal, run
strace -f -p SHELLPID
- In the second terminal, run screen and watch it fail
- In the first terminal, you now have the strace log you need to find out what's really wrong.
The key addition to the strace
command is the -f
option, which tells it to trace child processes. You need it to trace the screen that will be a child of the shell process you specified with -p
.
I also like to use -ff
and specify an output file with -o
, as in
strace -ff -o /tmp/screentrace -p SHELLPID
which will create a separate output file for each child process. Afterward you read them with less /tmp/screentrace*
and the result is usually cleaner than what you get using a single -f
.
UPDATE
Now that I've seen the strace output, I don't know exactly what went wrong, but this line is the most surprising thing in the trace:
chown("/dev/pts/2", 1002, 5) = -1 EPERM (Operation not permitted)
A few lines earlier, it created a pty, which was revealed by TIOCGPTN
to be number 2.
open("/dev/ptmx", O_RDWR) = 5
...
ioctl(5, TIOCGPTN, [2]) = 0
stat("/dev/pts/2", {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0
But it was unable to chown it. I don't know why that chown would fail, but the chown failure does give a plausible reason why screen gave up. You can get a little more information by adding -v
to the strace options, and looking at the stat
after the TIOCGPTN
to see who owns the /dev/pts/
entry.
Best Answer
Maybe these schema can clarify the situation. This is the usual setting:
And there is no way to plug some new
Process3
like this:What screen (and others) does is allocating some pseudo terminal device (like xterm does) and redirect it to one or more "real" terminals (physical, virtual, or emulated):
Using
screen -x
you can attach one more terminal, xterm, whatever (sayTerminal 3
) to the screen session.So no, you can't communicate directly through stdin/stdout with processes attached to a different terminal. You can only do so through the process that is controlling this terminal if it happens to be a pseudo terminal, and if this process was concieved to do so (like screen is).