From 785ac2b60e64f00131c01acdad09cbb9ed0bb505 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Wed, 27 Jun 2018 17:29:16 +0100 Subject: [PATCH] Initial commit --- README.md | 7 +++++ gui/gui.go | 3 ++ main.go | 21 +++++++++++++ pty/pty.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 README.md create mode 100644 gui/gui.go create mode 100644 main.go create mode 100644 pty/pty.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..a67d1f5 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Terminal + +## Platform Support + +| Linux | Yes +| MacOSX | Not yet... +| Windows | Not yet... diff --git a/gui/gui.go b/gui/gui.go new file mode 100644 index 0000000..ee99ddd --- /dev/null +++ b/gui/gui.go @@ -0,0 +1,3 @@ +package gui + + diff --git a/main.go b/main.go new file mode 100644 index 0000000..842d68c --- /dev/null +++ b/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "io" + "os" + + "gitlab.com/liamg/terminal/pty" +) + +func main() { + + pty, err := pty.NewPtyWithShell() + if err != nil { + panic(err) + } + + go io.Copy(pty, os.Stdin) + io.Copy(os.Stdout, pty) + + // return pty, err +} diff --git a/pty/pty.go b/pty/pty.go new file mode 100644 index 0000000..f68a04b --- /dev/null +++ b/pty/pty.go @@ -0,0 +1,89 @@ +package pty + +import ( + "fmt" + "os" + "os/exec" + "syscall" + "unsafe" +) + +func NewPtyWithShell() (*os.File, error) { + pty, tty, err := open() + if err != nil { + return nil, err + } + defer tty.Close() + shell := exec.Command("/bin/bash") + shell.Stdout = tty + shell.Stdin = tty + shell.Stderr = tty + shell.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} + if err := shell.Start(); err != nil { + pty.Close() + return nil, err + } + return pty, nil +} + +// todo: port these for darwin/windows: +func open() (*os.File, *os.File, error) { + + pty, err := getpt() + if err != nil { + panic(err) + } + + ptsName, err := ptsname(pty) + if err != nil { + panic(err) + } + + // err = grantpt(pty) + // if err != nil { + // return nil, nil, err + // } + + err = unlockpt(pty) + if err != nil { + return nil, nil, err + } + + tty, err := os.OpenFile(ptsName, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return pty, tty, nil + +} + +func getpt() (file *os.File, err error) { + return os.OpenFile("/dev/ptmx", os.O_RDWR, 0) +} + +func ptsname(file *os.File) (name string, err error) { + n, err := ioctl(file, syscall.TIOCGPTN, 0) + return fmt.Sprintf("/dev/pts/%d", n), err +} + +func ioctl(file *os.File, command uint, arg int) (int, error) { + _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(file.Fd()), + uintptr(command), uintptr(unsafe.Pointer(&arg))) + if err != 0 { + return 0, fmt.Errorf("Error no %d", err) + } + return arg, nil +} + +/* +func grantpt(f *os.File) error { + _, err := ioctl(f, syscall.TIOCPTYGRANT, 0) + syscall.SYS + return err +} +*/ + +func unlockpt(f *os.File) error { + _, err := ioctl(f, syscall.TIOCSPTLCK, 0) + return err +}