mirror of
https://github.com/creack/pty.git
synced 2026-03-31 02:27:08 +09:00
initial
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[568].out
|
||||
_go*
|
||||
_test*
|
||||
_obj
|
||||
9
Makefile
Normal file
9
Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
GOROOT ?= $(shell printf 't:;@echo $$(GOROOT)\n' | gomake -f -)
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=github.com/kr/pty
|
||||
GOFILES=\
|
||||
pty_$(GOOS).go\
|
||||
run.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
40
README.md
Normal file
40
README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# pty
|
||||
|
||||
Pty is a Go package for using unix pseudo-terminals.
|
||||
|
||||
## Install
|
||||
|
||||
goinstall github.com/kr/pty
|
||||
|
||||
## Example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kr/pty"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
||||
func main() {
|
||||
c, err := pty.Run(
|
||||
"/bin/grep",
|
||||
[]string{"grep", "--color=auto", "bar"},
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
fmt.Fprintln(c.Stdin, "foo")
|
||||
fmt.Fprintln(c.Stdin, "bar")
|
||||
fmt.Fprintln(c.Stdin, "baz")
|
||||
c.Stdin.Close()
|
||||
}()
|
||||
io.Copy(os.Stdout, c.Stdout)
|
||||
c.Wait(0)
|
||||
}
|
||||
89
pty_darwin.go
Normal file
89
pty_darwin.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
sys_TIOCGPTN = 0x80045430
|
||||
sys_TIOCSPTLCK = 0x40045431
|
||||
)
|
||||
|
||||
|
||||
// Opens a pty and its corresponding tty.
|
||||
func Open() (pty, tty *os.File, err os.Error) {
|
||||
p, err := os.Open("/dev/ptmx", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sname, err := ptsname(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = grantpt(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
t, err := os.Open(sname, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return p, t, nil
|
||||
}
|
||||
|
||||
const (
|
||||
ptdev1 = "pqrsPQRS"
|
||||
ptdev2 = "0123456789abcdefghijklmnopqrstuv"
|
||||
)
|
||||
|
||||
func ptsname(f *os.File) (string, os.Error) {
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "/dev/tty" + string([]byte{
|
||||
ptdev1[minor(fi.Rdev)/32],
|
||||
ptdev2[minor(fi.Rdev)%32],
|
||||
}), nil
|
||||
}
|
||||
|
||||
|
||||
func grantpt(f *os.File) os.Error {
|
||||
p, err := os.StartProcess("/bin/ptchown", []string{"/bin/ptchown"},
|
||||
nil, "", []*os.File{f})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := p.Wait(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if w.Exited() && w.ExitStatus() == 0 {
|
||||
return nil
|
||||
}
|
||||
return os.EACCES
|
||||
}
|
||||
|
||||
|
||||
func ioctl(fd int, cmd uint, data *int) os.Error {
|
||||
_, _, e := syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
uintptr(fd),
|
||||
uintptr(cmd),
|
||||
uintptr(unsafe.Pointer(data)),
|
||||
)
|
||||
if e != 0 {
|
||||
return os.ENOTTY
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func minor(d uint64) int {
|
||||
return int(d & 0xffffffff)
|
||||
}
|
||||
68
pty_linux.go
Normal file
68
pty_linux.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
sys_TIOCGPTN = 0x80045430
|
||||
sys_TIOCSPTLCK = 0x40045431
|
||||
)
|
||||
|
||||
|
||||
// Opens a pty and its corresponding tty.
|
||||
func Open() (pty, tty *os.File, err os.Error) {
|
||||
p, err := os.Open("/dev/ptmx", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sname, err := ptsname(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = unlockpt(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
t, err := os.Open(sname, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return p, t, nil
|
||||
}
|
||||
|
||||
|
||||
func ptsname(f *os.File) (string, os.Error) {
|
||||
var n int
|
||||
err := ioctl(f.Fd(), sys_TIOCGPTN, &n)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "/dev/pts/" + strconv.Itoa(n), nil
|
||||
}
|
||||
|
||||
|
||||
func unlockpt(f *os.File) os.Error {
|
||||
var u int
|
||||
return ioctl(f.Fd(), sys_TIOCSPTLCK, &u)
|
||||
}
|
||||
|
||||
|
||||
func ioctl(fd int, cmd uint, data *int) os.Error {
|
||||
_, _, e := syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
uintptr(fd),
|
||||
uintptr(cmd),
|
||||
uintptr(unsafe.Pointer(data)),
|
||||
)
|
||||
if e != 0 {
|
||||
return os.ENOTTY
|
||||
}
|
||||
return nil
|
||||
}
|
||||
33
run.go
Normal file
33
run.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package pty
|
||||
|
||||
import (
|
||||
"exec"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
||||
// Run starts a process with its stdin, stdout, and stderr
|
||||
// connected to a pseudo-terminal tty;
|
||||
// Stdin and Stdout of the returned exec.Cmd
|
||||
// are the corresponding pty (Stderr is always nil).
|
||||
// Arguments name, argv, envv, and dir are passed
|
||||
// to os.StartProcess unchanged.
|
||||
func Run(name string, argv, envv []string, dir string) (c *exec.Cmd, err os.Error) {
|
||||
c = new(exec.Cmd)
|
||||
var fd [3]*os.File
|
||||
|
||||
c.Stdin, fd[0], err = Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fd[1] = fd[0]
|
||||
fd[2] = fd[0]
|
||||
c.Stdout = c.Stdin
|
||||
c.Process, err = os.StartProcess(name, argv, envv, dir, fd[:])
|
||||
fd[0].Close()
|
||||
if err != nil {
|
||||
c.Stdin.Close()
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
Reference in New Issue
Block a user