1

So, I came across the ttyname function (unistd.h) and had to test it out.

#include <unistd.h>
#include <stdio.h>

int main(void) {
  printf("%s\n", ttyname(0));
  return 0;
}

On my machine, it echos out /dev/ttys011. I discovered it's a device!

echo "Hello" > /dev/ttys011

Woah, running that from another terminal produced Hello in the original terminal I ran my ttyname program in.

So what happens when I cat /dev/ttys011? Well, I get every other character typed. Oh yeah; it breaks the original TTY session, too.

So I try the following:

cat /dev/ttys011 | tee /dev/ttys011

Well, everything shows up in the original terminal, but my "tap" terminal (the one the above command is being run in) is still only getting every other character.

Oh yeah, my original terminal is still broken (the characters show up, but only every other character actually reaches my shell).

For instance, typing ls yields ls in the terminal, l in the "tap" terminal, and running it gives me 'l' is not a command.

What is going on here? I would expect weird behavior, but why is every other character being captured?

4

Your shell, or whatever process was in the foreground, was already reading the terminal to which is was attached, which was /dev/ttys011. Then you started another process, a cat also reading the same terminal at the same time.

Now there are two processes competing for the same input from the terminal. Each time you type a key in the terminal, it is delivered to one of the waiting processes. The other process is interested in reading too, but when it becomes its turn to read there's nothing left to read. Even though you seemed to observe a regular alternation of which characters go to which process, it's actually unpredictable which parts of the input will go to which process: it could be all input to one, all input to the other, or anything in between.

If you want your cat process to receive all of the input, you need to arrange for nothing else to be reading from the same device at the same time. One easy way you could do that is to run something like sleep 999 in the terminal. sleep waits for the delay to expire, but while it's waiting it shouldn't be attempting to read anything.

The command:

cat /dev/ttys011 | tee /dev/ttys011

does not restore any input captured by cat to its original location. That is, tee does not deliver it to whatever process was originally interested in reading it (such as your shell), it just sends it to the terminal's output, which causes it to be displayed.

By the way: you don't need a C program and the ttyname() function to get your terminal's name; all you have to do is type tty and press enter at the shell prompt.

  • Heh, this makes a lot of sense. So TTY's are simply the input sessions? That would make sense, seeing as how cat is almost becoming the "shell" of sorts (even though it's not doing anything with the input). – Qix Jan 20 '15 at 6:29
  • No, ttys are not just input sessions, they do input and output, as you saw when you did echo "Hello" > /dev/ttys011. When the tty is a serial port for example the input is connected to the receive line of the serial port and the output is connected to the transmit line. For pseudo-terminals like the one you're talking about, both input and output are connected to a piece of software, like a terminal emulator. Yes, cat is becoming the "shell" in the sense that it is taking input from a terminal like shells do. It's no different than what happens when you simply run cat at the prompt. – Celada Jan 20 '15 at 7:37
  • Actually, now that I'm re-reading this; I don't think it's random or unpredictable; read() is usually a blocking call. One blocks, and when a character is read it processes and the second program blocks with a call to read(), and back and forth. Still a great answer. – Qix Jul 23 '15 at 17:40
  • @Qix it really is unpredictable. In your example, nothing guarantees that the other thread will get scheduled and call read() before the first thread calls read() again. And while both threads are blocked on read(), the kernel does not make any promises about which one it will wake up. – Celada Jul 23 '15 at 17:53
  • Ah true, didn't think about that. – Qix Jul 23 '15 at 17:54

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.