tests: add basic build progress test
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>pull/1925/head
							parent
							
								
									cf9798cede
								
							
						
					
					
						commit
						b4c0941683
					
				@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					[568].out
 | 
				
			||||||
 | 
					_go*
 | 
				
			||||||
 | 
					_test*
 | 
				
			||||||
 | 
					_obj
 | 
				
			||||||
@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					ARG GOVERSION=1.14
 | 
				
			||||||
 | 
					FROM golang:${GOVERSION}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set base env.
 | 
				
			||||||
 | 
					ARG GOOS=linux
 | 
				
			||||||
 | 
					ARG GOARCH=amd64
 | 
				
			||||||
 | 
					ENV GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Pre compile the stdlib for 386/arm (32bits).
 | 
				
			||||||
 | 
					RUN go build -a std
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add the code to the image.
 | 
				
			||||||
 | 
					WORKDIR pty
 | 
				
			||||||
 | 
					ADD . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build the lib.
 | 
				
			||||||
 | 
					RUN go build
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					# NOTE: Using 1.13 as a base to build the RISCV compiler, the resulting version is based on go1.6.
 | 
				
			||||||
 | 
					FROM golang:1.13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Clone and complie a riscv compatible version of the go compiler.
 | 
				
			||||||
 | 
					RUN git clone https://review.gerrithub.io/riscv/riscv-go /riscv-go
 | 
				
			||||||
 | 
					# riscvdev branch HEAD as of 2019-06-29.
 | 
				
			||||||
 | 
					RUN cd /riscv-go && git checkout 04885fddd096d09d4450726064d06dd107e374bf
 | 
				
			||||||
 | 
					ENV PATH=/riscv-go/misc/riscv:/riscv-go/bin:$PATH
 | 
				
			||||||
 | 
					RUN cd /riscv-go/src && GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash
 | 
				
			||||||
 | 
					ENV GOROOT=/riscv-go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set the base env.
 | 
				
			||||||
 | 
					ENV GOOS=linux GOARCH=riscv CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Pre compile the stdlib.
 | 
				
			||||||
 | 
					RUN go build -a std
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add the code to the image.
 | 
				
			||||||
 | 
					WORKDIR pty
 | 
				
			||||||
 | 
					ADD . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build the lib.
 | 
				
			||||||
 | 
					RUN go build
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					Copyright (c) 2011 Keith Rarick
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person
 | 
				
			||||||
 | 
					obtaining a copy of this software and associated
 | 
				
			||||||
 | 
					documentation files (the "Software"), to deal in the
 | 
				
			||||||
 | 
					Software without restriction, including without limitation
 | 
				
			||||||
 | 
					the rights to use, copy, modify, merge, publish, distribute,
 | 
				
			||||||
 | 
					sublicense, and/or sell copies of the Software, and to
 | 
				
			||||||
 | 
					permit persons to whom the Software is furnished to do so,
 | 
				
			||||||
 | 
					subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall
 | 
				
			||||||
 | 
					be included in all copies or substantial portions of the
 | 
				
			||||||
 | 
					Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
 | 
				
			||||||
 | 
					KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 | 
				
			||||||
 | 
					WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 | 
				
			||||||
 | 
					PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 | 
				
			||||||
 | 
					OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | 
				
			||||||
 | 
					OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 | 
				
			||||||
 | 
					OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 | 
				
			||||||
 | 
					SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					# pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pty is a Go package for using unix pseudo-terminals.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					go get github.com/creack/pty
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that those examples are for demonstration purpose only, to showcase how to use the library. They are not meant to be used in any kind of production environment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/creack/pty"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						c := exec.Command("grep", "--color=auto", "bar")
 | 
				
			||||||
 | 
						f, err := pty.Start(c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							f.Write([]byte("foo\n"))
 | 
				
			||||||
 | 
							f.Write([]byte("bar\n"))
 | 
				
			||||||
 | 
							f.Write([]byte("baz\n"))
 | 
				
			||||||
 | 
							f.Write([]byte{4}) // EOT
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						io.Copy(os.Stdout, f)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```go
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
					        "io"
 | 
				
			||||||
 | 
					        "log"
 | 
				
			||||||
 | 
					        "os"
 | 
				
			||||||
 | 
					        "os/exec"
 | 
				
			||||||
 | 
					        "os/signal"
 | 
				
			||||||
 | 
					        "syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "github.com/creack/pty"
 | 
				
			||||||
 | 
					        "golang.org/x/term"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func test() error {
 | 
				
			||||||
 | 
					        // Create arbitrary command.
 | 
				
			||||||
 | 
					        c := exec.Command("bash")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Start the command with a pty.
 | 
				
			||||||
 | 
					        ptmx, err := pty.Start(c)
 | 
				
			||||||
 | 
					        if err != nil {
 | 
				
			||||||
 | 
					                return err
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Make sure to close the pty at the end.
 | 
				
			||||||
 | 
					        defer func() { _ = ptmx.Close() }() // Best effort.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Handle pty size.
 | 
				
			||||||
 | 
					        ch := make(chan os.Signal, 1)
 | 
				
			||||||
 | 
					        signal.Notify(ch, syscall.SIGWINCH)
 | 
				
			||||||
 | 
					        go func() {
 | 
				
			||||||
 | 
					                for range ch {
 | 
				
			||||||
 | 
					                        if err := pty.InheritSize(os.Stdin, ptmx); err != nil {
 | 
				
			||||||
 | 
					                                log.Printf("error resizing pty: %s", err)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }()
 | 
				
			||||||
 | 
					        ch <- syscall.SIGWINCH // Initial resize.
 | 
				
			||||||
 | 
					        defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set stdin in raw mode.
 | 
				
			||||||
 | 
					        oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
 | 
				
			||||||
 | 
					        if err != nil {
 | 
				
			||||||
 | 
					                panic(err)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Copy stdin to the pty and the pty to stdout.
 | 
				
			||||||
 | 
					        // NOTE: The goroutine will keep reading until the next keystroke before returning.
 | 
				
			||||||
 | 
					        go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
 | 
				
			||||||
 | 
					        _, _ = io.Copy(os.Stdout, ptmx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
					        if err := test(); err != nil {
 | 
				
			||||||
 | 
					                log.Fatal(err)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:build gc
 | 
				
			||||||
 | 
					//+build gc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "textflag.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEXT ·sysvicall6(SB),NOSPLIT,$0-88
 | 
				
			||||||
 | 
						JMP	syscall·sysvicall6(SB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
 | 
				
			||||||
 | 
						JMP	syscall·rawSysvicall6(SB)
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					// Package pty provides functions for working with Unix terminals.
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ErrUnsupported is returned if a function is not
 | 
				
			||||||
 | 
					// available on the current platform.
 | 
				
			||||||
 | 
					var ErrUnsupported = errors.New("unsupported")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Open a pty and its corresponding tty.
 | 
				
			||||||
 | 
					func Open() (pty, tty *os.File, err error) {
 | 
				
			||||||
 | 
						return open()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					//go:build !windows && !solaris && !aix
 | 
				
			||||||
 | 
					// +build !windows,!solaris,!aix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TIOCGWINSZ = syscall.TIOCGWINSZ
 | 
				
			||||||
 | 
						TIOCSWINSZ = syscall.TIOCSWINSZ
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ioctl(fd, cmd, ptr uintptr) error {
 | 
				
			||||||
 | 
						_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
 | 
				
			||||||
 | 
						if e != 0 {
 | 
				
			||||||
 | 
							return e
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 | 
				
			||||||
 | 
					// +build darwin dragonfly freebsd netbsd openbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// from <sys/ioccom.h>
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_IOC_VOID    uintptr = 0x20000000
 | 
				
			||||||
 | 
						_IOC_OUT     uintptr = 0x40000000
 | 
				
			||||||
 | 
						_IOC_IN      uintptr = 0x80000000
 | 
				
			||||||
 | 
						_IOC_IN_OUT  uintptr = _IOC_OUT | _IOC_IN
 | 
				
			||||||
 | 
						_IOC_DIRMASK         = _IOC_VOID | _IOC_OUT | _IOC_IN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_IOC_PARAM_SHIFT = 13
 | 
				
			||||||
 | 
						_IOC_PARAM_MASK  = (1 << _IOC_PARAM_SHIFT) - 1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _IOC_PARM_LEN(ioctl uintptr) uintptr {
 | 
				
			||||||
 | 
						return (ioctl >> 16) & _IOC_PARAM_MASK
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _IOC(inout uintptr, group byte, ioctl_num uintptr, param_len uintptr) uintptr {
 | 
				
			||||||
 | 
						return inout | (param_len&_IOC_PARAM_MASK)<<16 | uintptr(group)<<8 | ioctl_num
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _IO(group byte, ioctl_num uintptr) uintptr {
 | 
				
			||||||
 | 
						return _IOC(_IOC_VOID, group, ioctl_num, 0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _IOR(group byte, ioctl_num uintptr, param_len uintptr) uintptr {
 | 
				
			||||||
 | 
						return _IOC(_IOC_OUT, group, ioctl_num, param_len)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _IOW(group byte, ioctl_num uintptr, param_len uintptr) uintptr {
 | 
				
			||||||
 | 
						return _IOC(_IOC_IN, group, ioctl_num, param_len)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _IOWR(group byte, ioctl_num uintptr, param_len uintptr) uintptr {
 | 
				
			||||||
 | 
						return _IOC(_IOC_IN_OUT, group, ioctl_num, param_len)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					//go:build solaris
 | 
				
			||||||
 | 
					// +build solaris
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
 | 
				
			||||||
 | 
					//go:linkname procioctl libc_ioctl
 | 
				
			||||||
 | 
					var procioctl uintptr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// see /usr/include/sys/stropts.h
 | 
				
			||||||
 | 
						I_PUSH = uintptr((int32('S')<<8 | 002))
 | 
				
			||||||
 | 
						I_STR  = uintptr((int32('S')<<8 | 010))
 | 
				
			||||||
 | 
						I_FIND = uintptr((int32('S')<<8 | 013))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// see /usr/include/sys/ptms.h
 | 
				
			||||||
 | 
						ISPTM   = (int32('P') << 8) | 1
 | 
				
			||||||
 | 
						UNLKPT  = (int32('P') << 8) | 2
 | 
				
			||||||
 | 
						PTSSTTY = (int32('P') << 8) | 3
 | 
				
			||||||
 | 
						ZONEPT  = (int32('P') << 8) | 4
 | 
				
			||||||
 | 
						OWNERPT = (int32('P') << 8) | 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// see /usr/include/sys/termios.h
 | 
				
			||||||
 | 
						TIOCSWINSZ = (uint32('T') << 8) | 103
 | 
				
			||||||
 | 
						TIOCGWINSZ = (uint32('T') << 8) | 104
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type strioctl struct {
 | 
				
			||||||
 | 
						icCmd     int32
 | 
				
			||||||
 | 
						icTimeout int32
 | 
				
			||||||
 | 
						icLen     int32
 | 
				
			||||||
 | 
						icDP      unsafe.Pointer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Defined in asm_solaris_amd64.s.
 | 
				
			||||||
 | 
					func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ioctl(fd, cmd, ptr uintptr) error {
 | 
				
			||||||
 | 
						if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, fd, cmd, ptr, 0, 0, 0); errno != 0 {
 | 
				
			||||||
 | 
							return errno
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					//go:build aix
 | 
				
			||||||
 | 
					// +build aix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TIOCGWINSZ = 0
 | 
				
			||||||
 | 
						TIOCSWINSZ = 0
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ioctl(fd, cmd, ptr uintptr) error {
 | 
				
			||||||
 | 
						return ErrUnsupported
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GOOSARCH="${GOOS}_${GOARCH}"
 | 
				
			||||||
 | 
					case "$GOOSARCH" in
 | 
				
			||||||
 | 
					_* | *_ | _)
 | 
				
			||||||
 | 
						echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GODEFS="go tool cgo -godefs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$GODEFS types.go |gofmt > ztypes_$GOARCH.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case $GOOS in
 | 
				
			||||||
 | 
					freebsd|dragonfly|netbsd|openbsd)
 | 
				
			||||||
 | 
						$GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					//go:build darwin
 | 
				
			||||||
 | 
					// +build darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func open() (pty, tty *os.File, err error) {
 | 
				
			||||||
 | 
						pFD, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p := os.NewFile(uintptr(pFD), "/dev/ptmx")
 | 
				
			||||||
 | 
						// 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := unlockpt(p); err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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) {
 | 
				
			||||||
 | 
						n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0])))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, c := range n {
 | 
				
			||||||
 | 
							if c == 0 {
 | 
				
			||||||
 | 
								return string(n[:i]), nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", errors.New("TIOCPTYGNAME string not NUL-terminated")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func grantpt(f *os.File) error {
 | 
				
			||||||
 | 
						return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unlockpt(f *os.File) error {
 | 
				
			||||||
 | 
						return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					//go:build dragonfly
 | 
				
			||||||
 | 
					// +build dragonfly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// same code as pty_darwin.go
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := unlockpt(p); err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t, err := os.OpenFile(sname, os.O_RDWR, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p, t, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func grantpt(f *os.File) error {
 | 
				
			||||||
 | 
						_, err := isptmaster(f.Fd())
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unlockpt(f *os.File) error {
 | 
				
			||||||
 | 
						_, err := isptmaster(f.Fd())
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isptmaster(fd uintptr) (bool, error) {
 | 
				
			||||||
 | 
						err := ioctl(fd, syscall.TIOCISPTMASTER, 0)
 | 
				
			||||||
 | 
						return err == nil, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						emptyFiodgnameArg fiodgnameArg
 | 
				
			||||||
 | 
						ioctl_FIODNAME    = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg))
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ptsname(f *os.File) (string, error) {
 | 
				
			||||||
 | 
						name := make([]byte, _C_SPECNAMELEN)
 | 
				
			||||||
 | 
						fa := fiodgnameArg{Name: (*byte)(unsafe.Pointer(&name[0])), Len: _C_SPECNAMELEN, Pad_cgo_0: [4]byte{0, 0, 0, 0}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := ioctl(f.Fd(), ioctl_FIODNAME, uintptr(unsafe.Pointer(&fa)))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, c := range name {
 | 
				
			||||||
 | 
							if c == 0 {
 | 
				
			||||||
 | 
								s := "/dev/" + string(name[:i])
 | 
				
			||||||
 | 
								return strings.Replace(s, "ptm", "pts", -1), nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", errors.New("TIOCPTYGNAME string not NUL-terminated")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					//go:build freebsd
 | 
				
			||||||
 | 
					// +build freebsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func posixOpenpt(oflag int) (fd int, err error) {
 | 
				
			||||||
 | 
						r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0)
 | 
				
			||||||
 | 
						fd = int(r0)
 | 
				
			||||||
 | 
						if e1 != 0 {
 | 
				
			||||||
 | 
							err = e1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fd, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func open() (pty, tty *os.File, err error) {
 | 
				
			||||||
 | 
						fd, err := posixOpenpt(syscall.O_RDWR | syscall.O_CLOEXEC)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p := os.NewFile(uintptr(fd), "/dev/pts")
 | 
				
			||||||
 | 
						// In case of error after this point, make sure we close the pts fd.
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								_ = p.Close() // Best effort.
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sname, err := ptsname(p)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p, t, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isptmaster(fd uintptr) (bool, error) {
 | 
				
			||||||
 | 
						err := ioctl(fd, syscall.TIOCPTMASTER, 0)
 | 
				
			||||||
 | 
						return err == nil, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						emptyFiodgnameArg fiodgnameArg
 | 
				
			||||||
 | 
						ioctlFIODGNAME    = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg))
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ptsname(f *os.File) (string, error) {
 | 
				
			||||||
 | 
						master, err := isptmaster(f.Fd())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !master {
 | 
				
			||||||
 | 
							return "", syscall.EINVAL
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const n = _C_SPECNAMELEN + 1
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							buf = make([]byte, n)
 | 
				
			||||||
 | 
							arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))}
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err := ioctl(f.Fd(), ioctlFIODGNAME, uintptr(unsafe.Pointer(&arg))); err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, c := range buf {
 | 
				
			||||||
 | 
							if c == 0 {
 | 
				
			||||||
 | 
								return string(buf[:i]), nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", errors.New("FIODGNAME string not NUL-terminated")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					//go:build linux
 | 
				
			||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"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 := unlockpt(p); err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) //nolint:gosec // Expected Open from a variable.
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p, t, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ptsname(f *os.File) (string, error) {
 | 
				
			||||||
 | 
						var n _C_uint
 | 
				
			||||||
 | 
						err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) //nolint:gosec // Expected unsafe pointer for Syscall call.
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "/dev/pts/" + strconv.Itoa(int(n)), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unlockpt(f *os.File) error {
 | 
				
			||||||
 | 
						var u _C_int
 | 
				
			||||||
 | 
						// use TIOCSPTLCK with a pointer to zero to clear the lock
 | 
				
			||||||
 | 
						return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) //nolint:gosec // Expected unsafe pointer for Syscall call.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					//go:build netbsd
 | 
				
			||||||
 | 
					// +build netbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					//go:build openbsd
 | 
				
			||||||
 | 
					// +build openbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func open() (pty, tty *os.File, err error) {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * from ptm(4):
 | 
				
			||||||
 | 
						 * The PTMGET command allocates a free pseudo terminal, changes its
 | 
				
			||||||
 | 
						 * ownership to the caller, revokes the access privileges for all previous
 | 
				
			||||||
 | 
						 * users, opens the file descriptors for the pty and tty devices and
 | 
				
			||||||
 | 
						 * returns them to the caller in struct ptmget.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p, err := os.OpenFile("/dev/ptm", os.O_RDWR|syscall.O_CLOEXEC, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer p.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var ptm ptmget
 | 
				
			||||||
 | 
						if err := ioctl(p.Fd(), uintptr(ioctl_PTMGET), uintptr(unsafe.Pointer(&ptm))); err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pty = os.NewFile(uintptr(ptm.Cfd), "/dev/ptm")
 | 
				
			||||||
 | 
						tty = os.NewFile(uintptr(ptm.Sfd), "/dev/ptm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pty, tty, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,152 @@
 | 
				
			|||||||
 | 
					//go:build solaris
 | 
				
			||||||
 | 
					// +build solaris
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* based on:
 | 
				
			||||||
 | 
					http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/pt.c
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func open() (pty, tty *os.File, err error) {
 | 
				
			||||||
 | 
						ptmxfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx")
 | 
				
			||||||
 | 
						// 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := unlockpt(p); 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t := os.NewFile(uintptr(ptsfd), sname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// In case of error after this point, make sure we close the pts fd.
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								_ = t.Close() // Best effort.
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pushing terminal driver STREAMS modules as per pts(7)
 | 
				
			||||||
 | 
						for _, mod := range []string{"ptem", "ldterm", "ttcompat"} {
 | 
				
			||||||
 | 
							if err := streamsPush(t, mod); err != nil {
 | 
				
			||||||
 | 
								return nil, nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p, t, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ptsname(f *os.File) (string, error) {
 | 
				
			||||||
 | 
						dev, err := ptsdev(f.Fd())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := syscall.Access(fn, 0); err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fn, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unlockpt(f *os.File) error {
 | 
				
			||||||
 | 
						istr := strioctl{
 | 
				
			||||||
 | 
							icCmd:     UNLKPT,
 | 
				
			||||||
 | 
							icTimeout: 0,
 | 
				
			||||||
 | 
							icLen:     0,
 | 
				
			||||||
 | 
							icDP:      nil,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func minor(x uint64) uint64 { return x & 0377 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ptsdev(fd uintptr) (uint64, error) {
 | 
				
			||||||
 | 
						istr := strioctl{
 | 
				
			||||||
 | 
							icCmd:     ISPTM,
 | 
				
			||||||
 | 
							icTimeout: 0,
 | 
				
			||||||
 | 
							icLen:     0,
 | 
				
			||||||
 | 
							icDP:      nil,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var status syscall.Stat_t
 | 
				
			||||||
 | 
						if err := syscall.Fstat(int(fd), &status); err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return uint64(minor(status.Rdev)), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ptOwn struct {
 | 
				
			||||||
 | 
						rUID int32
 | 
				
			||||||
 | 
						rGID int32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func grantpt(f *os.File) error {
 | 
				
			||||||
 | 
						if _, err := ptsdev(f.Fd()); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pto := ptOwn{
 | 
				
			||||||
 | 
							rUID: int32(os.Getuid()),
 | 
				
			||||||
 | 
							// XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty"
 | 
				
			||||||
 | 
							rGID: int32(os.Getgid()),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						istr := strioctl{
 | 
				
			||||||
 | 
							icCmd:     OWNERPT,
 | 
				
			||||||
 | 
							icTimeout: 0,
 | 
				
			||||||
 | 
							icLen:     int32(unsafe.Sizeof(strioctl{})),
 | 
				
			||||||
 | 
							icDP:      unsafe.Pointer(&pto),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
 | 
				
			||||||
 | 
							return errors.New("access denied")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// streamsPush pushes STREAMS modules if not already done so.
 | 
				
			||||||
 | 
					func streamsPush(f *os.File, mod string) error {
 | 
				
			||||||
 | 
						buf := []byte(mod)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// XXX I_FIND is not returning an error when the module
 | 
				
			||||||
 | 
						// is already pushed even though truss reports a return
 | 
				
			||||||
 | 
						// value of 1. A bug in the Go Solaris syscall interface?
 | 
				
			||||||
 | 
						// XXX without this we are at risk of the issue
 | 
				
			||||||
 | 
						// https://www.illumos.org/issues/9042
 | 
				
			||||||
 | 
						// but since we are not using libc or XPG4.2, we should not be
 | 
				
			||||||
 | 
						// double-pushing modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))); err != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0])))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build !linux && !darwin && !freebsd && !dragonfly && !netbsd && !openbsd && !solaris
 | 
				
			||||||
 | 
					// +build !linux,!darwin,!freebsd,!dragonfly,!netbsd,!openbsd,!solaris
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func open() (pty, tty *os.File, err error) {
 | 
				
			||||||
 | 
						return nil, nil, ErrUnsupported
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
 | 
				
			||||||
 | 
					// and c.Stderr, calls c.Start, and returns the File of the tty's
 | 
				
			||||||
 | 
					// corresponding pty.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Starts the process in a new session and sets the controlling terminal.
 | 
				
			||||||
 | 
					func Start(cmd *exec.Cmd) (*os.File, error) {
 | 
				
			||||||
 | 
						return StartWithSize(cmd, nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartWithAttrs assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
 | 
				
			||||||
 | 
					// and c.Stderr, calls c.Start, and returns the File of the tty's
 | 
				
			||||||
 | 
					// corresponding pty.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This will resize the pty to the specified size before starting the command if a size is provided.
 | 
				
			||||||
 | 
					// The `attrs` parameter overrides the one set in c.SysProcAttr.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This should generally not be needed. Used in some edge cases where it is needed to create a pty
 | 
				
			||||||
 | 
					// without a controlling terminal.
 | 
				
			||||||
 | 
					func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (*os.File, error) {
 | 
				
			||||||
 | 
						pty, tty, err := Open()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() { _ = tty.Close() }() // Best effort.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if sz != nil {
 | 
				
			||||||
 | 
							if err := Setsize(pty, sz); err != nil {
 | 
				
			||||||
 | 
								_ = pty.Close() // Best effort.
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if c.Stdout == nil {
 | 
				
			||||||
 | 
							c.Stdout = tty
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if c.Stderr == nil {
 | 
				
			||||||
 | 
							c.Stderr = tty
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if c.Stdin == nil {
 | 
				
			||||||
 | 
							c.Stdin = tty
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.SysProcAttr = attrs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := c.Start(); err != nil {
 | 
				
			||||||
 | 
							_ = pty.Close() // Best effort.
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pty, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					//go:build !windows
 | 
				
			||||||
 | 
					// +build !windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
 | 
				
			||||||
 | 
					// and c.Stderr, calls c.Start, and returns the File of the tty's
 | 
				
			||||||
 | 
					// corresponding pty.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This will resize the pty to the specified size before starting the command.
 | 
				
			||||||
 | 
					// Starts the process in a new session and sets the controlling terminal.
 | 
				
			||||||
 | 
					func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) {
 | 
				
			||||||
 | 
						if cmd.SysProcAttr == nil {
 | 
				
			||||||
 | 
							cmd.SysProcAttr = &syscall.SysProcAttr{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmd.SysProcAttr.Setsid = true
 | 
				
			||||||
 | 
						cmd.SysProcAttr.Setctty = true
 | 
				
			||||||
 | 
						return StartWithAttrs(cmd, ws, cmd.SysProcAttr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
 | 
				
			||||||
 | 
					// and c.Stderr, calls c.Start, and returns the File of the tty's
 | 
				
			||||||
 | 
					// corresponding pty.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This will resize the pty to the specified size before starting the command.
 | 
				
			||||||
 | 
					// Starts the process in a new session and sets the controlling terminal.
 | 
				
			||||||
 | 
					func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) {
 | 
				
			||||||
 | 
						return nil, ErrUnsupported
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Test script checking that all expected os/arch compile properly.
 | 
				
			||||||
 | 
					# Does not actually test the logic, just the compilation so we make sure we don't break code depending on the lib.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo2() {
 | 
				
			||||||
 | 
					  echo $@ >&2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trap end 0
 | 
				
			||||||
 | 
					end() {
 | 
				
			||||||
 | 
					  [ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cross() {
 | 
				
			||||||
 | 
					  os=$1
 | 
				
			||||||
 | 
					  shift
 | 
				
			||||||
 | 
					  echo2 "Build for $os."
 | 
				
			||||||
 | 
					  for arch in $@; do
 | 
				
			||||||
 | 
					    echo2 "  - $os/$arch"
 | 
				
			||||||
 | 
					    GOOS=$os GOARCH=$arch go build
 | 
				
			||||||
 | 
					  done
 | 
				
			||||||
 | 
					  echo2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cross linux     amd64 386 arm arm64 ppc64 ppc64le s390x mips mipsle mips64 mips64le
 | 
				
			||||||
 | 
					cross darwin    amd64 arm64
 | 
				
			||||||
 | 
					cross freebsd   amd64 386 arm arm64
 | 
				
			||||||
 | 
					cross netbsd    amd64 386 arm arm64
 | 
				
			||||||
 | 
					cross openbsd   amd64 386 arm arm64
 | 
				
			||||||
 | 
					cross dragonfly amd64
 | 
				
			||||||
 | 
					cross solaris   amd64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Not expected to work but should still compile.
 | 
				
			||||||
 | 
					cross windows amd64 386 arm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: Fix compilation error on openbsd/arm.
 | 
				
			||||||
 | 
					# TODO: Merge the solaris PR.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Some os/arch require a different compiler. Run in docker.
 | 
				
			||||||
 | 
					if ! hash docker; then
 | 
				
			||||||
 | 
					  # If docker is not present, stop here.
 | 
				
			||||||
 | 
					  return
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo2 "Build for linux."
 | 
				
			||||||
 | 
					echo2 "  - linux/riscv"
 | 
				
			||||||
 | 
					docker build -t creack-pty-test -f Dockerfile.riscv .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Golang dropped support for darwin 32bits since go1.15. Make sure the lib still compile with go1.14 on those archs.
 | 
				
			||||||
 | 
					echo2 "Build for darwin (32bits)."
 | 
				
			||||||
 | 
					echo2 "  - darwin/386"
 | 
				
			||||||
 | 
					docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=386 .
 | 
				
			||||||
 | 
					echo2 "  - darwin/arm"
 | 
				
			||||||
 | 
					docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=arm .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run a single test for an old go version. Would be best with go1.0, but not available on Dockerhub.
 | 
				
			||||||
 | 
					# Using 1.6 as it is the base version for the RISCV compiler.
 | 
				
			||||||
 | 
					# Would also be better to run all the tests, not just one, need to refactor this file to allow for specifc archs per version.
 | 
				
			||||||
 | 
					echo2 "Build for linux - go1.6."
 | 
				
			||||||
 | 
					echo2 "  - linux/amd64"
 | 
				
			||||||
 | 
					docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.6 --build-arg=GOOS=linux --build-arg=GOARCH=amd64 .
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// InheritSize applies the terminal size of pty to tty. This should be run
 | 
				
			||||||
 | 
					// in a signal handler for syscall.SIGWINCH to automatically resize the tty when
 | 
				
			||||||
 | 
					// the pty receives a window size change notification.
 | 
				
			||||||
 | 
					func InheritSize(pty, tty *os.File) error {
 | 
				
			||||||
 | 
						size, err := GetsizeFull(pty)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := Setsize(tty, size); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Getsize returns the number of rows (lines) and cols (positions
 | 
				
			||||||
 | 
					// in each line) in terminal t.
 | 
				
			||||||
 | 
					func Getsize(t *os.File) (rows, cols int, err error) {
 | 
				
			||||||
 | 
						ws, err := GetsizeFull(t)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return int(ws.Rows), int(ws.Cols), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					//go:build !windows
 | 
				
			||||||
 | 
					// +build !windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Winsize describes the terminal size.
 | 
				
			||||||
 | 
					type Winsize struct {
 | 
				
			||||||
 | 
						Rows uint16 // ws_row: Number of rows (in cells)
 | 
				
			||||||
 | 
						Cols uint16 // ws_col: Number of columns (in cells)
 | 
				
			||||||
 | 
						X    uint16 // ws_xpixel: Width in pixels
 | 
				
			||||||
 | 
						Y    uint16 // ws_ypixel: Height in pixels
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Setsize resizes t to s.
 | 
				
			||||||
 | 
					func Setsize(t *os.File, ws *Winsize) error {
 | 
				
			||||||
 | 
						//nolint:gosec // Expected unsafe pointer for Syscall call.
 | 
				
			||||||
 | 
						return ioctl(t.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(ws)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetsizeFull returns the full terminal size description.
 | 
				
			||||||
 | 
					func GetsizeFull(t *os.File) (size *Winsize, err error) {
 | 
				
			||||||
 | 
						var ws Winsize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//nolint:gosec // Expected unsafe pointer for Syscall call.
 | 
				
			||||||
 | 
						if err := ioctl(t.Fd(), syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &ws, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Winsize is a dummy struct to enable compilation on unsupported platforms.
 | 
				
			||||||
 | 
					type Winsize struct {
 | 
				
			||||||
 | 
						Rows, Cols, X, Y uint16
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Setsize resizes t to s.
 | 
				
			||||||
 | 
					func Setsize(*os.File, *Winsize) error {
 | 
				
			||||||
 | 
						return ErrUnsupported
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetsizeFull returns the full terminal size description.
 | 
				
			||||||
 | 
					func GetsizeFull(*os.File) (*Winsize, error) {
 | 
				
			||||||
 | 
						return nil, ErrUnsupported
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build 386
 | 
				
			||||||
 | 
					// +build 386
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build amd64
 | 
				
			||||||
 | 
					// +build amd64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build arm
 | 
				
			||||||
 | 
					// +build arm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build arm64
 | 
				
			||||||
 | 
					// +build arm64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					//go:build amd64 && dragonfly
 | 
				
			||||||
 | 
					// +build amd64,dragonfly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types_dragonfly.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_C_SPECNAMELEN = 0x3f
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fiodgnameArg struct {
 | 
				
			||||||
 | 
						Name      *byte
 | 
				
			||||||
 | 
						Len       uint32
 | 
				
			||||||
 | 
						Pad_cgo_0 [4]byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					//go:build 386 && freebsd
 | 
				
			||||||
 | 
					// +build 386,freebsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types_freebsd.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_C_SPECNAMELEN = 0x3f
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fiodgnameArg struct {
 | 
				
			||||||
 | 
						Len int32
 | 
				
			||||||
 | 
						Buf *byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					//go:build amd64 && freebsd
 | 
				
			||||||
 | 
					// +build amd64,freebsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types_freebsd.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_C_SPECNAMELEN = 0x3f
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fiodgnameArg struct {
 | 
				
			||||||
 | 
						Len       int32
 | 
				
			||||||
 | 
						Pad_cgo_0 [4]byte
 | 
				
			||||||
 | 
						Buf       *byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					//go:build arm && freebsd
 | 
				
			||||||
 | 
					// +build arm,freebsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types_freebsd.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_C_SPECNAMELEN = 0x3f
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fiodgnameArg struct {
 | 
				
			||||||
 | 
						Len int32
 | 
				
			||||||
 | 
						Buf *byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					//go:build arm64 && freebsd
 | 
				
			||||||
 | 
					// +build arm64,freebsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by cmd/cgo -godefs; DO NOT EDIT.
 | 
				
			||||||
 | 
					// cgo -godefs types_freebsd.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_C_SPECNAMELEN = 0xff
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fiodgnameArg struct {
 | 
				
			||||||
 | 
						Len int32
 | 
				
			||||||
 | 
						Buf *byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types_freebsd.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_C_SPECNAMELEN = 0x3f
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fiodgnameArg struct {
 | 
				
			||||||
 | 
						Len       int32
 | 
				
			||||||
 | 
						Pad_cgo_0 [4]byte
 | 
				
			||||||
 | 
						Buf       *byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build loong64
 | 
				
			||||||
 | 
					// +build loong64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					//go:build (mips || mipsle || mips64 || mips64le) && linux
 | 
				
			||||||
 | 
					// +build mips mipsle mips64 mips64le
 | 
				
			||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					//go:build (386 || amd64 || arm || arm64) && netbsd
 | 
				
			||||||
 | 
					// +build 386 amd64 arm arm64
 | 
				
			||||||
 | 
					// +build netbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ptmget struct {
 | 
				
			||||||
 | 
						Cfd int32
 | 
				
			||||||
 | 
						Sfd int32
 | 
				
			||||||
 | 
						Cn  [1024]int8
 | 
				
			||||||
 | 
						Sn  [1024]int8
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ioctl_TIOCPTSNAME = 0x48087448
 | 
				
			||||||
 | 
						ioctl_TIOCGRANTPT = 0x20007447
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					//go:build (386 || amd64 || arm || arm64 || mips64) && openbsd
 | 
				
			||||||
 | 
					// +build 386 amd64 arm arm64 mips64
 | 
				
			||||||
 | 
					// +build openbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ptmget struct {
 | 
				
			||||||
 | 
						Cfd int32
 | 
				
			||||||
 | 
						Sfd int32
 | 
				
			||||||
 | 
						Cn  [16]int8
 | 
				
			||||||
 | 
						Sn  [16]int8
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ioctl_PTMGET = 0x40287401
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build ppc64
 | 
				
			||||||
 | 
					// +build ppc64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build ppc64le
 | 
				
			||||||
 | 
					// +build ppc64le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build riscv || riscv64
 | 
				
			||||||
 | 
					// +build riscv riscv64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by cmd/cgo -godefs; DO NOT EDIT.
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					//go:build s390x
 | 
				
			||||||
 | 
					// +build s390x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Created by cgo -godefs - DO NOT EDIT
 | 
				
			||||||
 | 
					// cgo -godefs types.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						_C_int  int32
 | 
				
			||||||
 | 
						_C_uint uint32
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
					Loading…
					
					
				
		Reference in New Issue