mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00
142 lines
2.8 KiB
Go
142 lines
2.8 KiB
Go
//go:build zos
|
|
// +build zos
|
|
|
|
package pty
|
|
|
|
import (
|
|
"os"
|
|
"runtime"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
SYS_UNLOCKPT = 0x37B
|
|
SYS_GRANTPT = 0x37A
|
|
SYS_POSIX_OPENPT = 0xC66
|
|
SYS_FCNTL = 0x18C
|
|
SYS___PTSNAME_A = 0x718
|
|
|
|
SETCVTON = 1
|
|
|
|
O_NONBLOCK = 0x04
|
|
|
|
F_SETFL = 4
|
|
F_CONTROL_CVT = 13
|
|
)
|
|
|
|
type f_cnvrt struct {
|
|
Cvtcmd int32
|
|
Pccsid int16
|
|
Fccsid int16
|
|
}
|
|
|
|
func open() (pty, tty *os.File, err error) {
|
|
ptmxfd, err := openpt(os.O_RDWR | syscall.O_NOCTTY)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// Needed for z/OS so that the characters are not garbled if ptyp* is untagged
|
|
cvtreq := f_cnvrt{Cvtcmd: SETCVTON, Pccsid: 0, Fccsid: 1047}
|
|
if _, err = fcntl(uintptr(ptmxfd), F_CONTROL_CVT, uintptr(unsafe.Pointer(&cvtreq))); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx")
|
|
if p == 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(ptmxfd)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
_, err = grantpt(ptmxfd)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if _, err = unlockpt(ptmxfd); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
ptsfd, err := syscall.Open(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if _, err = fcntl(uintptr(ptsfd), F_CONTROL_CVT, uintptr(unsafe.Pointer(&cvtreq))); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
t := os.NewFile(uintptr(ptsfd), sname)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return p, t, nil
|
|
}
|
|
|
|
func openpt(oflag int) (fd int, err error) {
|
|
r0, _, e1 := runtime.CallLeFuncWithErr(runtime.GetZosLibVec()+SYS_POSIX_OPENPT<<4, uintptr(oflag))
|
|
fd = int(r0)
|
|
if e1 != 0 {
|
|
err = syscall.Errno(e1)
|
|
}
|
|
return
|
|
}
|
|
|
|
func fcntl(fd uintptr, cmd int, arg uintptr) (val int, err error) {
|
|
r0, _, e1 := runtime.CallLeFuncWithErr(runtime.GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg)
|
|
val = int(r0)
|
|
if e1 != 0 {
|
|
err = syscall.Errno(e1)
|
|
}
|
|
return
|
|
}
|
|
|
|
func ptsname(fd int) (name string, err error) {
|
|
r0, _, e1 := runtime.CallLeFuncWithPtrReturn(runtime.GetZosLibVec()+SYS___PTSNAME_A<<4, uintptr(fd))
|
|
name = u2s(unsafe.Pointer(r0))
|
|
if e1 != 0 {
|
|
err = syscall.Errno(e1)
|
|
}
|
|
return
|
|
}
|
|
|
|
func grantpt(fildes int) (rc int, err error) {
|
|
r0, _, e1 := runtime.CallLeFuncWithErr(runtime.GetZosLibVec()+SYS_GRANTPT<<4, uintptr(fildes))
|
|
rc = int(r0)
|
|
if e1 != 0 {
|
|
err = syscall.Errno(e1)
|
|
}
|
|
return
|
|
}
|
|
|
|
func unlockpt(fildes int) (rc int, err error) {
|
|
r0, _, e1 := runtime.CallLeFuncWithErr(runtime.GetZosLibVec()+SYS_UNLOCKPT<<4, uintptr(fildes))
|
|
rc = int(r0)
|
|
if e1 != 0 {
|
|
err = syscall.Errno(e1)
|
|
}
|
|
return
|
|
}
|
|
|
|
func u2s(cstr unsafe.Pointer) string {
|
|
str := (*[1024]uint8)(cstr)
|
|
i := 0
|
|
for str[i] != 0 {
|
|
i++
|
|
}
|
|
return string(str[:i])
|
|
}
|