| //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]) |
| } |