Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
••••••••••••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Pipes Won't Let Me Go

Some time ago when I was working on codecrafters shell challenge I hit a problem. The problem was that behaviour of my shell if use it via terminal was…

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!

Some time ago when I was working on codecrafters shell challenge I hit a problem.

The problem was that behaviour of my shell if use it via terminal was different from when use it in test environment.

When use it via terminal emulator the prompt was shown, however in tests it wasn't there. It appeared that readline works a bit different if communicating with it throug Stdin Stdout programatically.

I managed to overcome the problem, i wrote about it in one of my previous posts, but i think it is quite interesting and important to understand how this 2 ways work.



What is tty?



In unix system everything is a file including any device, tty is not an exception. It is a special character device. It means that it is a device that it streaming data as it receives it in real time byte by byte.



As it is a file it can be open for read or read with cat, or it can be written to with echo >. There is something confusing though. Suppose we use /dev/ttyp0 we want to write some data to it so it would be picked up somwhere, also we want to receive feedback from the device. But there seems to be a problem, if it is a file, how what is written on our hand is not mixing up with what is sent from the other hand?



At this point I found that instead of saying "in unix everything is a file" it would be better to say: "in unix everything looks like a file". What it means that file and tty device have same interface: read, write, close, but for diferent things it behaves differently differently. You see file descriptor no only a pointer to a file, it includes some additional info, and among other things it includes info on what drivers to use. For File read and write will use same destination, for tty read and write would use different buffers.



The Two-Way Pipe



TTY it is a 2 way-pipe (full-duplex). When any tty device would be represented by master end and slave end - two different entries at /dev/ptmx and /dev/pts/4.




  • Master end is held by usef facing app, when app receives typed charecters it writes them to master.

  • Slave end is held by a shell application and used slave as a stdin, and stdout.



When something is written to master, it appears on slave reader, and directed to a shell app stdin. When a shell app writes something to its stdout, whidh is slaves write, it is transfered to masters read.



TTY vs PTY




  • TTY is actual hardware(e.g /dev/ttys0), so the other end of the pipe is actual device

  • PTY is a pseudo-terminal, it is pair of files used to build TTY like interaction between software apps.



There is also such thing as line discipline, this is a kernel layer that echoes typed characters back to master, buffers input until Enter is hit. It also intercepts special symbols and key sequences like ^c or ^z and act on them accordingly. While this is an important piece, I will not focus on it at this post.



how to find out if app interacts with tty?



it can be easialy done with IsTerminal(fd int) from "golang.org/x/term", but how does it work under the hood?




// x/term/term.go
func IsTerminal(fd int) bool {
return isTerminal(fd)
}

// x/term/unix_term.go
func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil
}

// x/term/term_unix_bsd.go
const ioctlReadTermios = unix.TIOCGETA
// x/sys/unix/ioctl_unsigned.go

func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err
}







ioctlPtr makes a syscall with a file descriptor and unix.TIOCGETA request, and writes result to value, it errors if file under fd is not tty. Presnse of error in the upstream code is interpreted as current file descriptor does not point to a tty device.



unix.TIOCGETA is read:

TIO - terminal Input/Output

C - control

GET - read/retrieve operation

A - attributes



Actual unix.TIOGETA value of course is not an arbitrary integer. But as I think it would be to deep in the rabbit hole for now, and I'll get to it somewhere in the future.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Pipes Won't Let Me Go

Thematisch verwandte Begriffe: Pipes, Wont · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag