turbo-editors/turbo-corepublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

🛟 Updated. 28d5985 · on main · k33g · 4h ago
pty_linux.go · 60 lines · 1.9 KBGo Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//go:build linux

package terminal

import (
	"fmt"
	"os"
	"syscall"

	"golang.org/x/sys/unix"
)

// openPTY allocates a pseudo-terminal and returns both of its ends.
//
// Linux hands out the slave by number: unlock the pair, ask which number it
// got, and the device is /dev/pts/<number>.
func openPTY() (master, slave *os.File, err error) {
	master, err = os.OpenFile("/dev/ptmx", os.O_RDWR|unix.O_NOCTTY, 0)
	if err != nil {
		return nil, nil, fmt.Errorf("terminal: opening /dev/ptmx: %w", err)
	}

	// A pair starts locked so that nothing can open the slave between its
	// creation and the master being ready for it.
	if err := unix.IoctlSetPointerInt(int(master.Fd()), unix.TIOCSPTLCK, 0); err != nil {
		master.Close()
		return nil, nil, fmt.Errorf("terminal: unlocking the pseudo-terminal: %w", err)
	}

	number, err := unix.IoctlGetInt(int(master.Fd()), unix.TIOCGPTN)
	if err != nil {
		master.Close()
		return nil, nil, fmt.Errorf("terminal: naming the pseudo-terminal: %w", err)
	}

	slave, err = os.OpenFile(fmt.Sprintf("/dev/pts/%d", number), os.O_RDWR|unix.O_NOCTTY, 0)
	if err != nil {
		master.Close()
		return nil, nil, fmt.Errorf("terminal: opening the slave side: %w", err)
	}
	return master, slave, nil
}

// setWinsize tells the pseudo-terminal how big it is, which the kernel passes
// on to the shell as SIGWINCH.
func setWinsize(master *os.File, width, height int) error {
	return unix.IoctlSetWinsize(int(master.Fd()), unix.TIOCSWINSZ, &unix.Winsize{
		Row: uint16(height),
		Col: uint16(width),
	})
}

// childAttributes put the shell in a session of its own with the slave as its
// controlling terminal.
//
// Without this the shell has no controlling terminal, and job control — Ctrl-C,
// Ctrl-Z, running something in the background — does not work at all.
func childAttributes() *syscall.SysProcAttr {
	return &syscall.SysProcAttr{Setsid: true, Setctty: true}
}