From e9fe4226256da367a1a627f1788a6530ab3109b4 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 16 May 2021 18:17:26 +0200 Subject: [PATCH] Add support for NetBSD 386/amd64/arm (#117) --- mktypes.bash | 2 +- pty_netbsd.go | 66 ++++++++++++++++++++++++++++++++++++++ pty_unsupported.go | 2 +- types_netbsd.go | 15 +++++++++ ztypes_netbsd_32bit_int.go | 14 ++++++++ 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 pty_netbsd.go create mode 100644 types_netbsd.go create mode 100644 ztypes_netbsd_32bit_int.go diff --git a/mktypes.bash b/mktypes.bash index 82ee167..7f71bda 100755 --- a/mktypes.bash +++ b/mktypes.bash @@ -13,7 +13,7 @@ GODEFS="go tool cgo -godefs" $GODEFS types.go |gofmt > ztypes_$GOARCH.go case $GOOS in -freebsd|dragonfly|openbsd) +freebsd|dragonfly|netbsd|openbsd) $GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go ;; esac diff --git a/pty_netbsd.go b/pty_netbsd.go new file mode 100644 index 0000000..20f9125 --- /dev/null +++ b/pty_netbsd.go @@ -0,0 +1,66 @@ +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := grantpt(p); err != nil { + return nil, nil, err + } + + // In NetBSD unlockpt() does nothing, so it isn't called here. + + t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + /* + * from ptsname(3): The ptsname() function is equivalent to: + * struct ptmget pm; + * ioctl(fd, TIOCPTSNAME, &pm) == -1 ? NULL : pm.sn; + */ + var ptm ptmget + if err := ioctl(f.Fd(), uintptr(ioctl_TIOCPTSNAME), uintptr(unsafe.Pointer(&ptm))); err != nil { + return "", err + } + name := make([]byte, len(ptm.Sn)) + for i, c := range ptm.Sn { + name[i] = byte(c) + if c == 0 { + return string(name[:i]), nil + } + } + return "", errors.New("TIOCPTSNAME string not NUL-terminated") +} + +func grantpt(f *os.File) error { + /* + * from grantpt(3): Calling grantpt() is equivalent to: + * ioctl(fd, TIOCGRANTPT, 0); + */ + return ioctl(f.Fd(), uintptr(ioctl_TIOCGRANTPT), 0) +} diff --git a/pty_unsupported.go b/pty_unsupported.go index ceb425b..6cd757b 100644 --- a/pty_unsupported.go +++ b/pty_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin,!freebsd,!dragonfly,!openbsd,!solaris +// +build !linux,!darwin,!freebsd,!dragonfly,!netbsd,!openbsd,!solaris package pty diff --git a/types_netbsd.go b/types_netbsd.go new file mode 100644 index 0000000..52ebea7 --- /dev/null +++ b/types_netbsd.go @@ -0,0 +1,15 @@ +// +build ignore + +package pty + +/* +#include +#include +#include +*/ +import "C" + +type ptmget C.struct_ptmget + +var ioctl_TIOCPTSNAME = C.TIOCPTSNAME +var ioctl_TIOCGRANTPT = C.TIOCGRANTPT diff --git a/ztypes_netbsd_32bit_int.go b/ztypes_netbsd_32bit_int.go new file mode 100644 index 0000000..f40a5a6 --- /dev/null +++ b/ztypes_netbsd_32bit_int.go @@ -0,0 +1,14 @@ +// +build netbsd +// +build 386 amd64 arm arm64 + +package pty + +type ptmget struct { + Cfd int32 + Sfd int32 + Cn [1024]int8 + Sn [1024]int8 +} + +var ioctl_TIOCPTSNAME = 0x48087448 +var ioctl_TIOCGRANTPT = 0x20007447