Add support for detaching shortcut in client mode

When joining a session from command line, the user can exit now by
pressing a predefined key sequence that can be specified from command
line.
pull/25/head
Vasile Popescu 4 years ago committed by Elis Popescu
parent 6c0171e9d9
commit 14266a7f24

@ -6,34 +6,55 @@ import (
"net/http"
"net/url"
"os"
"fmt"
ttyServer "github.com/elisescu/tty-share/server"
"github.com/gorilla/websocket"
"github.com/moby/term"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal"
)
type ttyShareClient struct {
url string
connection *websocket.Conn
url string
connection *websocket.Conn
detachKeys string
}
func newTtyShareClient(url string) *ttyShareClient {
func newTtyShareClient(url string, detachKeys string) *ttyShareClient {
return &ttyShareClient{
url: url,
connection: nil,
url: url,
connection: nil,
detachKeys: detachKeys,
}
}
func clearScreen() {
fmt.Fprintf(os.Stdout, "\033[H\033[2J")
}
type wsTextWriter struct {
conn *websocket.Conn
}
func (w *wsTextWriter) Write(data []byte) (n int, err error) {
err = w.conn.WriteMessage(websocket.TextMessage, data)
return len(data), err
}
type keyListener struct {
wrappedReader io.Reader
}
func (kl *keyListener) Read(data []byte) (n int, err error) {
n, err = kl.wrappedReader.Read(data)
if _, ok := err.(term.EscapeError); ok {
log.Debug("Escape code detected.")
}
return
}
func (c *ttyShareClient) Run() (err error) {
log.Debugf("Connecting as a client to %s ..", c.url)
@ -64,16 +85,25 @@ func (c *ttyShareClient) Run() (err error) {
return
}
detachBytes, err := term.ToBytes(c.detachKeys)
if err != nil {
log.Errorf("Invalid dettaching keys: %s", c.detachKeys)
return
}
state, err := terminal.MakeRaw(0)
defer terminal.Restore(0, state)
c.connection = conn
// Clear the screen before processing any incoming data
clearScreen()
readLoop := func() {
for {
var msg ttyServer.MsgAll
_, r, err := conn.NextReader()
if err != nil {
log.Debugf("Connection closed\n")
log.Debugf("Connection closed")
return
}
err = json.NewDecoder(r).Decode(&msg)
@ -107,15 +137,20 @@ func (c *ttyShareClient) Run() (err error) {
ww := &wsTextWriter{
conn: conn,
}
_, err := io.Copy(ttyServer.NewTTYProtocolWriter(ww), os.Stdin)
kl := &keyListener{
wrappedReader: term.NewEscapeProxy(os.Stdin, detachBytes),
}
_, err := io.Copy(ttyServer.NewTTYProtocolWriter(ww), kl)
if err != nil {
log.Debugf("Connection closed.\n")
log.Debugf("Connection closed")
c.Stop()
return
}
}
go writeLoop()
readLoop()
clearScreen()
return
}

@ -11,8 +11,8 @@ require (
github.com/jroimartin/gocui v0.4.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 // indirect
github.com/sirupsen/logrus v1.4.2
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7 // indirect
)

@ -1,3 +1,6 @@
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elisescu/pty v1.0.2 h1:I/wkN5bnPyh00j/bnNAy8wll8yvd8wRLUjPnmcmYI+Q=
@ -5,6 +8,8 @@ github.com/elisescu/pty v1.0.2/go.mod h1:tzLUboZf84k7sFZdd2cOvhr/fSxMABV0UTMxnF2
github.com/go-bindata/go-bindata v1.0.0 h1:DZ34txDXWn1DyWa+vQf7V9ANc2ILTtrEjtlsdJRF26M=
github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE=
github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
@ -18,22 +23,34 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2 h1:SPoLlS9qUUnXcIY4pvA4CTwYjk0Is5f4UPEkeESr53k=
github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ=
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 h1:lh3PyZvY+B9nFliSGTn5uFuqQQJGuNrD0MLCokv09ag=
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7 h1:/W9OPMnnpmFXHYkcp2rQsbFUbRlRzfECQjmAFiOyHE8=
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a h1:i47hUS795cOydZI4AwJQCKXOr4BvxzvikwDoDtHhP2Y=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=

@ -40,17 +40,21 @@ func main() {
Usage:
tty-share creates a session to a terminal application with remote participants. The session can be joined either from the browser, or by tty-share command itself.
tty-share [flags] ; share the terminal and get a session URL, as a server
tty-share <session URL> ; connect to an existing session, as a client
tty-share [[--args <"args">] --command <executable>] # share the terminal and get a session URL, as a server
[--logfile <file name>] [--listen <[ip]:port>]
[--frontend-path <path>] [--tty-proxy <host:port>]
[--readonly] [--public] [no-tls] [--verbose] [--version]
tty-share [--verbose] [--logfile <file name>]
[--detach-keys] <session URL> # connect to an existing session, as a client
Examples:
Start bash and create a public sharing session, so it's accessible outside the local network, and make the session read only:
tty-share --public --readonly --command bash
tty-share --public --readonly --command bash
Join a remote session by providing the URL created another tty-share command:
tty-share http://localhost:8000/s/local/
tty-share http://localhost:8000/s/local/
Flags:
`
@ -67,6 +71,7 @@ Flags:
readOnly := flag.Bool("readonly", false, "Start a read only session")
publicSession := flag.Bool("public", false, "Create a public session")
noTLS := flag.Bool("no-tls", false, "Don't use TLS to connect to the tty-proxy server. Useful for local debugging")
detachKeys := flag.String("detach-keys", "ctrl-o,ctrl-c", "Sequence of keys to press for closing the connection. Supported: https://godoc.org/github.com/moby/term#pkg-variables.")
verbose := flag.Bool("verbose", false, "Verbose logging")
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "%s", usageString)
@ -101,12 +106,13 @@ Flags:
args := flag.Args()
if len(args) == 1 {
connectURL := args[0]
client := newTtyShareClient(connectURL)
client := newTtyShareClient(connectURL, *detachKeys)
err := client.Run()
if err != nil {
log.Errorf("Cannot connect to the remote session. Make sure the URL points to a valid tty-share session.", err.Error())
fmt.Printf("Cannot connect to the remote session. Make sure the URL points to a valid tty-share session.\n")
}
fmt.Printf("\ntty-share disconnected\n\n")
return
}

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Microsoft Corporation
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,12 @@
# go-ansiterm
This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent.
For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position.
The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go).
See parser_test.go for examples exercising the state machine and generating appropriate function calls.
-----
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

@ -0,0 +1,188 @@
package ansiterm
const LogEnv = "DEBUG_TERMINAL"
// ANSI constants
// References:
// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm
// -- http://man7.org/linux/man-pages/man4/console_codes.4.html
// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html
// -- http://en.wikipedia.org/wiki/ANSI_escape_code
// -- http://vt100.net/emu/dec_ansi_parser
// -- http://vt100.net/emu/vt500_parser.svg
// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
// -- http://www.inwap.com/pdp10/ansicode.txt
const (
// ECMA-48 Set Graphics Rendition
// Note:
// -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved
// -- Fonts could possibly be supported via SetCurrentConsoleFontEx
// -- Windows does not expose the per-window cursor (i.e., caret) blink times
ANSI_SGR_RESET = 0
ANSI_SGR_BOLD = 1
ANSI_SGR_DIM = 2
_ANSI_SGR_ITALIC = 3
ANSI_SGR_UNDERLINE = 4
_ANSI_SGR_BLINKSLOW = 5
_ANSI_SGR_BLINKFAST = 6
ANSI_SGR_REVERSE = 7
_ANSI_SGR_INVISIBLE = 8
_ANSI_SGR_LINETHROUGH = 9
_ANSI_SGR_FONT_00 = 10
_ANSI_SGR_FONT_01 = 11
_ANSI_SGR_FONT_02 = 12
_ANSI_SGR_FONT_03 = 13
_ANSI_SGR_FONT_04 = 14
_ANSI_SGR_FONT_05 = 15
_ANSI_SGR_FONT_06 = 16
_ANSI_SGR_FONT_07 = 17
_ANSI_SGR_FONT_08 = 18
_ANSI_SGR_FONT_09 = 19
_ANSI_SGR_FONT_10 = 20
_ANSI_SGR_DOUBLEUNDERLINE = 21
ANSI_SGR_BOLD_DIM_OFF = 22
_ANSI_SGR_ITALIC_OFF = 23
ANSI_SGR_UNDERLINE_OFF = 24
_ANSI_SGR_BLINK_OFF = 25
_ANSI_SGR_RESERVED_00 = 26
ANSI_SGR_REVERSE_OFF = 27
_ANSI_SGR_INVISIBLE_OFF = 28
_ANSI_SGR_LINETHROUGH_OFF = 29
ANSI_SGR_FOREGROUND_BLACK = 30
ANSI_SGR_FOREGROUND_RED = 31
ANSI_SGR_FOREGROUND_GREEN = 32
ANSI_SGR_FOREGROUND_YELLOW = 33
ANSI_SGR_FOREGROUND_BLUE = 34
ANSI_SGR_FOREGROUND_MAGENTA = 35
ANSI_SGR_FOREGROUND_CYAN = 36
ANSI_SGR_FOREGROUND_WHITE = 37
_ANSI_SGR_RESERVED_01 = 38
ANSI_SGR_FOREGROUND_DEFAULT = 39
ANSI_SGR_BACKGROUND_BLACK = 40
ANSI_SGR_BACKGROUND_RED = 41
ANSI_SGR_BACKGROUND_GREEN = 42
ANSI_SGR_BACKGROUND_YELLOW = 43
ANSI_SGR_BACKGROUND_BLUE = 44
ANSI_SGR_BACKGROUND_MAGENTA = 45
ANSI_SGR_BACKGROUND_CYAN = 46
ANSI_SGR_BACKGROUND_WHITE = 47
_ANSI_SGR_RESERVED_02 = 48
ANSI_SGR_BACKGROUND_DEFAULT = 49
// 50 - 65: Unsupported
ANSI_MAX_CMD_LENGTH = 4096
MAX_INPUT_EVENTS = 128
DEFAULT_WIDTH = 80
DEFAULT_HEIGHT = 24
ANSI_BEL = 0x07
ANSI_BACKSPACE = 0x08
ANSI_TAB = 0x09
ANSI_LINE_FEED = 0x0A
ANSI_VERTICAL_TAB = 0x0B
ANSI_FORM_FEED = 0x0C
ANSI_CARRIAGE_RETURN = 0x0D
ANSI_ESCAPE_PRIMARY = 0x1B
ANSI_ESCAPE_SECONDARY = 0x5B
ANSI_OSC_STRING_ENTRY = 0x5D
ANSI_COMMAND_FIRST = 0x40
ANSI_COMMAND_LAST = 0x7E
DCS_ENTRY = 0x90
CSI_ENTRY = 0x9B
OSC_STRING = 0x9D
ANSI_PARAMETER_SEP = ";"
ANSI_CMD_G0 = '('
ANSI_CMD_G1 = ')'
ANSI_CMD_G2 = '*'
ANSI_CMD_G3 = '+'
ANSI_CMD_DECPNM = '>'
ANSI_CMD_DECPAM = '='
ANSI_CMD_OSC = ']'
ANSI_CMD_STR_TERM = '\\'
KEY_CONTROL_PARAM_2 = ";2"
KEY_CONTROL_PARAM_3 = ";3"
KEY_CONTROL_PARAM_4 = ";4"
KEY_CONTROL_PARAM_5 = ";5"
KEY_CONTROL_PARAM_6 = ";6"
KEY_CONTROL_PARAM_7 = ";7"
KEY_CONTROL_PARAM_8 = ";8"
KEY_ESC_CSI = "\x1B["
KEY_ESC_N = "\x1BN"
KEY_ESC_O = "\x1BO"
FILL_CHARACTER = ' '
)
func getByteRange(start byte, end byte) []byte {
bytes := make([]byte, 0, 32)
for i := start; i <= end; i++ {
bytes = append(bytes, byte(i))
}
return bytes
}
var toGroundBytes = getToGroundBytes()
var executors = getExecuteBytes()
// SPACE 20+A0 hex Always and everywhere a blank space
// Intermediate 20-2F hex !"#$%&'()*+,-./
var intermeds = getByteRange(0x20, 0x2F)
// Parameters 30-3F hex 0123456789:;<=>?
// CSI Parameters 30-39, 3B hex 0123456789;
var csiParams = getByteRange(0x30, 0x3F)
var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...)
// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
var upperCase = getByteRange(0x40, 0x5F)
// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~
var lowerCase = getByteRange(0x60, 0x7E)
// Alphabetics 40-7E hex (all of upper and lower case)
var alphabetics = append(upperCase, lowerCase...)
var printables = getByteRange(0x20, 0x7F)
var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E)
var escapeToGroundBytes = getEscapeToGroundBytes()
// See http://www.vt100.net/emu/vt500_parser.png for description of the complex
// byte ranges below
func getEscapeToGroundBytes() []byte {
escapeToGroundBytes := getByteRange(0x30, 0x4F)
escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...)
escapeToGroundBytes = append(escapeToGroundBytes, 0x59)
escapeToGroundBytes = append(escapeToGroundBytes, 0x5A)
escapeToGroundBytes = append(escapeToGroundBytes, 0x5C)
escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...)
return escapeToGroundBytes
}
func getExecuteBytes() []byte {
executeBytes := getByteRange(0x00, 0x17)
executeBytes = append(executeBytes, 0x19)
executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...)
return executeBytes
}
func getToGroundBytes() []byte {
groundBytes := []byte{0x18}
groundBytes = append(groundBytes, 0x1A)
groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...)
groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...)
groundBytes = append(groundBytes, 0x99)
groundBytes = append(groundBytes, 0x9A)
groundBytes = append(groundBytes, 0x9C)
return groundBytes
}
// Delete 7F hex Always and everywhere ignored
// C1 Control 80-9F hex 32 additional control characters
// G1 Displayable A1-FE hex 94 additional displayable characters
// Special A0+FF hex Same as SPACE and DELETE

@ -0,0 +1,7 @@
package ansiterm
type ansiContext struct {
currentChar byte
paramBuffer []byte
interBuffer []byte
}

@ -0,0 +1,49 @@
package ansiterm
type csiEntryState struct {
baseState
}
func (csiState csiEntryState) Handle(b byte) (s state, e error) {
csiState.parser.logf("CsiEntry::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(alphabetics, b):
return csiState.parser.ground, nil
case sliceContains(csiCollectables, b):
return csiState.parser.csiParam, nil
case sliceContains(executors, b):
return csiState, csiState.parser.execute()
}
return csiState, nil
}
func (csiState csiEntryState) Transition(s state) error {
csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s)
switch s {
case csiState.parser.ground:
return csiState.parser.csiDispatch()
case csiState.parser.csiParam:
switch {
case sliceContains(csiParams, csiState.parser.context.currentChar):
csiState.parser.collectParam()
case sliceContains(intermeds, csiState.parser.context.currentChar):
csiState.parser.collectInter()
}
}
return nil
}
func (csiState csiEntryState) Enter() error {
csiState.parser.clear()
return nil
}

@ -0,0 +1,38 @@
package ansiterm
type csiParamState struct {
baseState
}
func (csiState csiParamState) Handle(b byte) (s state, e error) {
csiState.parser.logf("CsiParam::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(alphabetics, b):
return csiState.parser.ground, nil
case sliceContains(csiCollectables, b):
csiState.parser.collectParam()
return csiState, nil
case sliceContains(executors, b):
return csiState, csiState.parser.execute()
}
return csiState, nil
}
func (csiState csiParamState) Transition(s state) error {
csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s)
switch s {
case csiState.parser.ground:
return csiState.parser.csiDispatch()
}
return nil
}

@ -0,0 +1,36 @@
package ansiterm
type escapeIntermediateState struct {
baseState
}
func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
escState.parser.logf("escapeIntermediateState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(intermeds, b):
return escState, escState.parser.collectInter()
case sliceContains(executors, b):
return escState, escState.parser.execute()
case sliceContains(escapeIntermediateToGroundBytes, b):
return escState.parser.ground, nil
}
return escState, nil
}
func (escState escapeIntermediateState) Transition(s state) error {
escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s)
switch s {
case escState.parser.ground:
return escState.parser.escDispatch()
}
return nil
}

@ -0,0 +1,47 @@
package ansiterm
type escapeState struct {
baseState
}
func (escState escapeState) Handle(b byte) (s state, e error) {
escState.parser.logf("escapeState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case b == ANSI_ESCAPE_SECONDARY:
return escState.parser.csiEntry, nil
case b == ANSI_OSC_STRING_ENTRY:
return escState.parser.oscString, nil
case sliceContains(executors, b):
return escState, escState.parser.execute()
case sliceContains(escapeToGroundBytes, b):
return escState.parser.ground, nil
case sliceContains(intermeds, b):
return escState.parser.escapeIntermediate, nil
}
return escState, nil
}
func (escState escapeState) Transition(s state) error {
escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s)
switch s {
case escState.parser.ground:
return escState.parser.escDispatch()
case escState.parser.escapeIntermediate:
return escState.parser.collectInter()
}
return nil
}
func (escState escapeState) Enter() error {
escState.parser.clear()
return nil
}

@ -0,0 +1,90 @@
package ansiterm
type AnsiEventHandler interface {
// Print
Print(b byte) error
// Execute C0 commands
Execute(b byte) error
// CUrsor Up
CUU(int) error
// CUrsor Down
CUD(int) error
// CUrsor Forward
CUF(int) error
// CUrsor Backward
CUB(int) error
// Cursor to Next Line
CNL(int) error
// Cursor to Previous Line
CPL(int) error
// Cursor Horizontal position Absolute
CHA(int) error
// Vertical line Position Absolute
VPA(int) error
// CUrsor Position
CUP(int, int) error
// Horizontal and Vertical Position (depends on PUM)
HVP(int, int) error
// Text Cursor Enable Mode
DECTCEM(bool) error
// Origin Mode
DECOM(bool) error
// 132 Column Mode
DECCOLM(bool) error
// Erase in Display
ED(int) error
// Erase in Line
EL(int) error
// Insert Line
IL(int) error
// Delete Line
DL(int) error
// Insert Character
ICH(int) error
// Delete Character
DCH(int) error
// Set Graphics Rendition
SGR([]int) error
// Pan Down
SU(int) error
// Pan Up
SD(int) error
// Device Attributes
DA([]string) error
// Set Top and Bottom Margins
DECSTBM(int, int) error
// Index
IND() error
// Reverse Index
RI() error
// Flush updates from previous commands
Flush() error
}

@ -0,0 +1,24 @@
package ansiterm
type groundState struct {
baseState
}
func (gs groundState) Handle(b byte) (s state, e error) {
gs.parser.context.currentChar = b
nextState, err := gs.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(printables, b):
return gs, gs.parser.print()
case sliceContains(executors, b):
return gs, gs.parser.execute()
}
return gs, nil
}

@ -0,0 +1,31 @@
package ansiterm
type oscStringState struct {
baseState
}
func (oscState oscStringState) Handle(b byte) (s state, e error) {
oscState.parser.logf("OscString::Handle %#x", b)
nextState, err := oscState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case isOscStringTerminator(b):
return oscState.parser.ground, nil
}
return oscState, nil
}
// See below for OSC string terminators for linux
// http://man7.org/linux/man-pages/man4/console_codes.4.html
func isOscStringTerminator(b byte) bool {
if b == ANSI_BEL || b == 0x5C {
return true
}
return false
}

@ -0,0 +1,151 @@
package ansiterm
import (
"errors"
"log"
"os"
)
type AnsiParser struct {
currState state
eventHandler AnsiEventHandler
context *ansiContext
csiEntry state
csiParam state
dcsEntry state
escape state
escapeIntermediate state
error state
ground state
oscString state
stateMap []state
logf func(string, ...interface{})
}
type Option func(*AnsiParser)
func WithLogf(f func(string, ...interface{})) Option {
return func(ap *AnsiParser) {
ap.logf = f
}
}
func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser {
ap := &AnsiParser{
eventHandler: evtHandler,
context: &ansiContext{},
}
for _, o := range opts {
o(ap)
}
if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
logFile, _ := os.Create("ansiParser.log")
logger := log.New(logFile, "", log.LstdFlags)
if ap.logf != nil {
l := ap.logf
ap.logf = func(s string, v ...interface{}) {
l(s, v...)
logger.Printf(s, v...)
}
} else {
ap.logf = logger.Printf
}
}
if ap.logf == nil {
ap.logf = func(string, ...interface{}) {}
}
ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}}
ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}}
ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}}
ap.escape = escapeState{baseState{name: "Escape", parser: ap}}
ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}}
ap.error = errorState{baseState{name: "Error", parser: ap}}
ap.ground = groundState{baseState{name: "Ground", parser: ap}}
ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}}
ap.stateMap = []state{
ap.csiEntry,
ap.csiParam,
ap.dcsEntry,
ap.escape,
ap.escapeIntermediate,
ap.error,
ap.ground,
ap.oscString,
}
ap.currState = getState(initialState, ap.stateMap)
ap.logf("CreateParser: parser %p", ap)
return ap
}
func getState(name string, states []state) state {
for _, el := range states {
if el.Name() == name {
return el
}
}
return nil
}
func (ap *AnsiParser) Parse(bytes []byte) (int, error) {
for i, b := range bytes {
if err := ap.handle(b); err != nil {
return i, err
}
}
return len(bytes), ap.eventHandler.Flush()
}
func (ap *AnsiParser) handle(b byte) error {
ap.context.currentChar = b
newState, err := ap.currState.Handle(b)
if err != nil {
return err
}
if newState == nil {
ap.logf("WARNING: newState is nil")
return errors.New("New state of 'nil' is invalid.")
}
if newState != ap.currState {
if err := ap.changeState(newState); err != nil {
return err
}
}
return nil
}
func (ap *AnsiParser) changeState(newState state) error {
ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
// Exit old state
if err := ap.currState.Exit(); err != nil {
ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
return err
}
// Perform transition action
if err := ap.currState.Transition(newState); err != nil {
ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
return err
}
// Enter new state
if err := newState.Enter(); err != nil {
ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err)
return err
}
ap.currState = newState
return nil
}

@ -0,0 +1,99 @@
package ansiterm
import (
"strconv"
)
func parseParams(bytes []byte) ([]string, error) {
paramBuff := make([]byte, 0, 0)
params := []string{}
for _, v := range bytes {
if v == ';' {
if len(paramBuff) > 0 {
// Completed parameter, append it to the list
s := string(paramBuff)
params = append(params, s)
paramBuff = make([]byte, 0, 0)
}
} else {
paramBuff = append(paramBuff, v)
}
}
// Last parameter may not be terminated with ';'
if len(paramBuff) > 0 {
s := string(paramBuff)
params = append(params, s)
}
return params, nil
}
func parseCmd(context ansiContext) (string, error) {
return string(context.currentChar), nil
}
func getInt(params []string, dflt int) int {
i := getInts(params, 1, dflt)[0]
return i
}
func getInts(params []string, minCount int, dflt int) []int {
ints := []int{}
for _, v := range params {
i, _ := strconv.Atoi(v)
// Zero is mapped to the default value in VT100.
if i == 0 {
i = dflt
}
ints = append(ints, i)
}
if len(ints) < minCount {
remaining := minCount - len(ints)
for i := 0; i < remaining; i++ {
ints = append(ints, dflt)
}
}
return ints
}
func (ap *AnsiParser) modeDispatch(param string, set bool) error {
switch param {
case "?3":
return ap.eventHandler.DECCOLM(set)
case "?6":
return ap.eventHandler.DECOM(set)
case "?25":
return ap.eventHandler.DECTCEM(set)
}
return nil
}
func (ap *AnsiParser) hDispatch(params []string) error {
if len(params) == 1 {
return ap.modeDispatch(params[0], true)
}
return nil
}
func (ap *AnsiParser) lDispatch(params []string) error {
if len(params) == 1 {
return ap.modeDispatch(params[0], false)
}
return nil
}
func getEraseParam(params []string) int {
param := getInt(params, 0)
if param < 0 || 3 < param {
param = 0
}
return param
}

@ -0,0 +1,119 @@
package ansiterm
func (ap *AnsiParser) collectParam() error {
currChar := ap.context.currentChar
ap.logf("collectParam %#x", currChar)
ap.context.paramBuffer = append(ap.context.paramBuffer, currChar)
return nil
}
func (ap *AnsiParser) collectInter() error {
currChar := ap.context.currentChar
ap.logf("collectInter %#x", currChar)
ap.context.paramBuffer = append(ap.context.interBuffer, currChar)
return nil
}
func (ap *AnsiParser) escDispatch() error {
cmd, _ := parseCmd(*ap.context)
intermeds := ap.context.interBuffer
ap.logf("escDispatch currentChar: %#x", ap.context.currentChar)
ap.logf("escDispatch: %v(%v)", cmd, intermeds)
switch cmd {
case "D": // IND
return ap.eventHandler.IND()
case "E": // NEL, equivalent to CRLF
err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN)
if err == nil {
err = ap.eventHandler.Execute(ANSI_LINE_FEED)
}
return err
case "M": // RI
return ap.eventHandler.RI()
}
return nil
}
func (ap *AnsiParser) csiDispatch() error {
cmd, _ := parseCmd(*ap.context)
params, _ := parseParams(ap.context.paramBuffer)
ap.logf("Parsed params: %v with length: %d", params, len(params))
ap.logf("csiDispatch: %v(%v)", cmd, params)
switch cmd {
case "@":
return ap.eventHandler.ICH(getInt(params, 1))
case "A":
return ap.eventHandler.CUU(getInt(params, 1))
case "B":
return ap.eventHandler.CUD(getInt(params, 1))
case "C":
return ap.eventHandler.CUF(getInt(params, 1))
case "D":
return ap.eventHandler.CUB(getInt(params, 1))
case "E":
return ap.eventHandler.CNL(getInt(params, 1))
case "F":
return ap.eventHandler.CPL(getInt(params, 1))
case "G":
return ap.eventHandler.CHA(getInt(params, 1))
case "H":
ints := getInts(params, 2, 1)
x, y := ints[0], ints[1]
return ap.eventHandler.CUP(x, y)
case "J":
param := getEraseParam(params)
return ap.eventHandler.ED(param)
case "K":
param := getEraseParam(params)
return ap.eventHandler.EL(param)
case "L":
return ap.eventHandler.IL(getInt(params, 1))
case "M":
return ap.eventHandler.DL(getInt(params, 1))
case "P":
return ap.eventHandler.DCH(getInt(params, 1))
case "S":
return ap.eventHandler.SU(getInt(params, 1))
case "T":
return ap.eventHandler.SD(getInt(params, 1))
case "c":
return ap.eventHandler.DA(params)
case "d":
return ap.eventHandler.VPA(getInt(params, 1))
case "f":
ints := getInts(params, 2, 1)
x, y := ints[0], ints[1]
return ap.eventHandler.HVP(x, y)
case "h":
return ap.hDispatch(params)
case "l":
return ap.lDispatch(params)
case "m":
return ap.eventHandler.SGR(getInts(params, 1, 0))
case "r":
ints := getInts(params, 2, 1)
top, bottom := ints[0], ints[1]
return ap.eventHandler.DECSTBM(top, bottom)
default:
ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context)
return nil
}
}
func (ap *AnsiParser) print() error {
return ap.eventHandler.Print(ap.context.currentChar)
}
func (ap *AnsiParser) clear() error {
ap.context = &ansiContext{}
return nil
}
func (ap *AnsiParser) execute() error {
return ap.eventHandler.Execute(ap.context.currentChar)
}

@ -0,0 +1,71 @@
package ansiterm
type stateID int
type state interface {
Enter() error
Exit() error
Handle(byte) (state, error)
Name() string
Transition(state) error
}
type baseState struct {
name string
parser *AnsiParser
}
func (base baseState) Enter() error {
return nil
}
func (base baseState) Exit() error {
return nil
}
func (base baseState) Handle(b byte) (s state, e error) {
switch {
case b == CSI_ENTRY:
return base.parser.csiEntry, nil
case b == DCS_ENTRY:
return base.parser.dcsEntry, nil
case b == ANSI_ESCAPE_PRIMARY:
return base.parser.escape, nil
case b == OSC_STRING:
return base.parser.oscString, nil
case sliceContains(toGroundBytes, b):
return base.parser.ground, nil
}
return nil, nil
}
func (base baseState) Name() string {
return base.name
}
func (base baseState) Transition(s state) error {
if s == base.parser.ground {
execBytes := []byte{0x18}
execBytes = append(execBytes, 0x1A)
execBytes = append(execBytes, getByteRange(0x80, 0x8F)...)
execBytes = append(execBytes, getByteRange(0x91, 0x97)...)
execBytes = append(execBytes, 0x99)
execBytes = append(execBytes, 0x9A)
if sliceContains(execBytes, base.parser.context.currentChar) {
return base.parser.execute()
}
}
return nil
}
type dcsEntryState struct {
baseState
}
type errorState struct {
baseState
}

@ -0,0 +1,21 @@
package ansiterm
import (
"strconv"
)
func sliceContains(bytes []byte, b byte) bool {
for _, v := range bytes {
if v == b {
return true
}
}
return false
}
func convertBytesToInteger(bytes []byte) int {
s := string(bytes)
i, _ := strconv.Atoi(s)
return i
}

@ -0,0 +1,182 @@
// +build windows
package winterm
import (
"fmt"
"os"
"strconv"
"strings"
"syscall"
"github.com/Azure/go-ansiterm"
)
// Windows keyboard constants
// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx.
const (
VK_PRIOR = 0x21 // PAGE UP key
VK_NEXT = 0x22 // PAGE DOWN key
VK_END = 0x23 // END key
VK_HOME = 0x24 // HOME key
VK_LEFT = 0x25 // LEFT ARROW key
VK_UP = 0x26 // UP ARROW key
VK_RIGHT = 0x27 // RIGHT ARROW key
VK_DOWN = 0x28 // DOWN ARROW key
VK_SELECT = 0x29 // SELECT key
VK_PRINT = 0x2A // PRINT key
VK_EXECUTE = 0x2B // EXECUTE key
VK_SNAPSHOT = 0x2C // PRINT SCREEN key
VK_INSERT = 0x2D // INS key
VK_DELETE = 0x2E // DEL key
VK_HELP = 0x2F // HELP key
VK_F1 = 0x70 // F1 key
VK_F2 = 0x71 // F2 key
VK_F3 = 0x72 // F3 key
VK_F4 = 0x73 // F4 key
VK_F5 = 0x74 // F5 key
VK_F6 = 0x75 // F6 key
VK_F7 = 0x76 // F7 key
VK_F8 = 0x77 // F8 key
VK_F9 = 0x78 // F9 key
VK_F10 = 0x79 // F10 key
VK_F11 = 0x7A // F11 key
VK_F12 = 0x7B // F12 key
RIGHT_ALT_PRESSED = 0x0001
LEFT_ALT_PRESSED = 0x0002
RIGHT_CTRL_PRESSED = 0x0004
LEFT_CTRL_PRESSED = 0x0008
SHIFT_PRESSED = 0x0010
NUMLOCK_ON = 0x0020
SCROLLLOCK_ON = 0x0040
CAPSLOCK_ON = 0x0080
ENHANCED_KEY = 0x0100
)
type ansiCommand struct {
CommandBytes []byte
Command string
Parameters []string
IsSpecial bool
}
func newAnsiCommand(command []byte) *ansiCommand {
if isCharacterSelectionCmdChar(command[1]) {
// Is Character Set Selection commands
return &ansiCommand{
CommandBytes: command,
Command: string(command),
IsSpecial: true,
}
}
// last char is command character
lastCharIndex := len(command) - 1
ac := &ansiCommand{
CommandBytes: command,
Command: string(command[lastCharIndex]),
IsSpecial: false,
}
// more than a single escape
if lastCharIndex != 0 {
start := 1
// skip if double char escape sequence
if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY {
start++
}
// convert this to GetNextParam method
ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP)
}
return ac
}
func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 {
if index < 0 || index >= len(ac.Parameters) {
return defaultValue
}
param, err := strconv.ParseInt(ac.Parameters[index], 10, 16)
if err != nil {
return defaultValue
}
return int16(param)
}
func (ac *ansiCommand) String() string {
return fmt.Sprintf("0x%v \"%v\" (\"%v\")",
bytesToHex(ac.CommandBytes),
ac.Command,
strings.Join(ac.Parameters, "\",\""))
}
// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands.
// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html.
func isAnsiCommandChar(b byte) bool {
switch {
case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY:
return true
case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM:
// non-CSI escape sequence terminator
return true
case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL:
// String escape sequence terminator
return true
}
return false
}
func isXtermOscSequence(command []byte, current byte) bool {
return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL)
}
func isCharacterSelectionCmdChar(b byte) bool {
return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3)
}
// bytesToHex converts a slice of bytes to a human-readable string.
func bytesToHex(b []byte) string {
hex := make([]string, len(b))
for i, ch := range b {
hex[i] = fmt.Sprintf("%X", ch)
}
return strings.Join(hex, "")
}
// ensureInRange adjusts the passed value, if necessary, to ensure it is within
// the passed min / max range.
func ensureInRange(n int16, min int16, max int16) int16 {
if n < min {
return min
} else if n > max {
return max
} else {
return n
}
}
func GetStdFile(nFile int) (*os.File, uintptr) {
var file *os.File
switch nFile {
case syscall.STD_INPUT_HANDLE:
file = os.Stdin
case syscall.STD_OUTPUT_HANDLE:
file = os.Stdout
case syscall.STD_ERROR_HANDLE:
file = os.Stderr
default:
panic(fmt.Errorf("Invalid standard handle identifier: %v", nFile))
}
fd, err := syscall.GetStdHandle(nFile)
if err != nil {
panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err))
}
return file, uintptr(fd)
}

@ -0,0 +1,327 @@
// +build windows
package winterm
import (
"fmt"
"syscall"
"unsafe"
)
//===========================================================================================================
// IMPORTANT NOTE:
//
// The methods below make extensive use of the "unsafe" package to obtain the required pointers.
// Beginning in Go 1.3, the garbage collector may release local variables (e.g., incoming arguments, stack
// variables) the pointers reference *before* the API completes.
//
// As a result, in those cases, the code must hint that the variables remain in active by invoking the
// dummy method "use" (see below). Newer versions of Go are planned to change the mechanism to no longer
// require unsafe pointers.
//
// If you add or modify methods, ENSURE protection of local variables through the "use" builtin to inform
// the garbage collector the variables remain in use if:
//
// -- The value is not a pointer (e.g., int32, struct)
// -- The value is not referenced by the method after passing the pointer to Windows
//
// See http://golang.org/doc/go1.3.
//===========================================================================================================
var (
kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo")
setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo")
setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition")
setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize")
scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA")
setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo")
writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW")
readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW")
waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject")
)
// Windows Console constants
const (
// Console modes
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010
ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080
ENABLE_AUTO_POSITION = 0x0100
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
DISABLE_NEWLINE_AUTO_RETURN = 0x0008
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
// Character attributes
// Note:
// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
// Clearing all foreground or background colors results in black; setting all creates white.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
FOREGROUND_BLUE uint16 = 0x0001
FOREGROUND_GREEN uint16 = 0x0002
FOREGROUND_RED uint16 = 0x0004
FOREGROUND_INTENSITY uint16 = 0x0008
FOREGROUND_MASK uint16 = 0x000F
BACKGROUND_BLUE uint16 = 0x0010
BACKGROUND_GREEN uint16 = 0x0020
BACKGROUND_RED uint16 = 0x0040
BACKGROUND_INTENSITY uint16 = 0x0080
BACKGROUND_MASK uint16 = 0x00F0
COMMON_LVB_MASK uint16 = 0xFF00
COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000
COMMON_LVB_UNDERSCORE uint16 = 0x8000
// Input event types
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
KEY_EVENT = 0x0001
MOUSE_EVENT = 0x0002
WINDOW_BUFFER_SIZE_EVENT = 0x0004
MENU_EVENT = 0x0008
FOCUS_EVENT = 0x0010
// WaitForSingleObject return codes
WAIT_ABANDONED = 0x00000080
WAIT_FAILED = 0xFFFFFFFF
WAIT_SIGNALED = 0x0000000
WAIT_TIMEOUT = 0x00000102
// WaitForSingleObject wait duration
WAIT_INFINITE = 0xFFFFFFFF
WAIT_ONE_SECOND = 1000
WAIT_HALF_SECOND = 500
WAIT_QUARTER_SECOND = 250
)
// Windows API Console types
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682101(v=vs.85).aspx for Console specific types (e.g., COORD)
// -- See https://msdn.microsoft.com/en-us/library/aa296569(v=vs.60).aspx for comments on alignment
type (
CHAR_INFO struct {
UnicodeChar uint16
Attributes uint16
}
CONSOLE_CURSOR_INFO struct {
Size uint32
Visible int32
}
CONSOLE_SCREEN_BUFFER_INFO struct {
Size COORD
CursorPosition COORD
Attributes uint16
Window SMALL_RECT
MaximumWindowSize COORD
}
COORD struct {
X int16
Y int16
}
SMALL_RECT struct {
Left int16
Top int16
Right int16
Bottom int16
}
// INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
INPUT_RECORD struct {
EventType uint16
KeyEvent KEY_EVENT_RECORD
}
KEY_EVENT_RECORD struct {
KeyDown int32
RepeatCount uint16
VirtualKeyCode uint16
VirtualScanCode uint16
UnicodeChar uint16
ControlKeyState uint32
}
WINDOW_BUFFER_SIZE struct {
Size COORD
}
)
// boolToBOOL converts a Go bool into a Windows int32.
func boolToBOOL(f bool) int32 {
if f {
return int32(1)
} else {
return int32(0)
}
}
// GetConsoleCursorInfo retrieves information about the size and visiblity of the console cursor.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683163(v=vs.85).aspx.
func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error {
r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)
return checkError(r1, r2, err)
}
// SetConsoleCursorInfo sets the size and visiblity of the console cursor.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx.
func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error {
r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)
return checkError(r1, r2, err)
}
// SetConsoleCursorPosition location of the console cursor.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx.
func SetConsoleCursorPosition(handle uintptr, coord COORD) error {
r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord))
use(coord)
return checkError(r1, r2, err)
}
// GetConsoleMode gets the console mode for given file descriptor
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx.
func GetConsoleMode(handle uintptr) (mode uint32, err error) {
err = syscall.GetConsoleMode(syscall.Handle(handle), &mode)
return mode, err
}
// SetConsoleMode sets the console mode for given file descriptor
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
func SetConsoleMode(handle uintptr, mode uint32) error {
r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0)
use(mode)
return checkError(r1, r2, err)
}
// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx.
func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
info := CONSOLE_SCREEN_BUFFER_INFO{}
err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0))
if err != nil {
return nil, err
}
return &info, nil
}
func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error {
r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char)))
use(scrollRect)
use(clipRect)
use(destOrigin)
use(char)
return checkError(r1, r2, err)
}
// SetConsoleScreenBufferSize sets the size of the console screen buffer.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx.
func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error {
r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord))
use(coord)
return checkError(r1, r2, err)
}
// SetConsoleTextAttribute sets the attributes of characters written to the
// console screen buffer by the WriteFile or WriteConsole function.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
func SetConsoleTextAttribute(handle uintptr, attribute uint16) error {
r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
use(attribute)
return checkError(r1, r2, err)
}
// SetConsoleWindowInfo sets the size and position of the console screen buffer's window.
// Note that the size and location must be within and no larger than the backing console screen buffer.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx.
func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error {
r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect)))
use(isAbsolute)
use(rect)
return checkError(r1, r2, err)
}
// WriteConsoleOutput writes the CHAR_INFOs from the provided buffer to the active console buffer.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx.
func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error {
r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion)))
use(buffer)
use(bufferSize)
use(bufferCoord)
return checkError(r1, r2, err)
}
// ReadConsoleInput reads (and removes) data from the console input buffer.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx.
func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error {
r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count)))
use(buffer)
return checkError(r1, r2, err)
}
// WaitForSingleObject waits for the passed handle to be signaled.
// It returns true if the handle was signaled; false otherwise.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx.
func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) {
r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait)))
switch r1 {
case WAIT_ABANDONED, WAIT_TIMEOUT:
return false, nil
case WAIT_SIGNALED:
return true, nil
}
use(msWait)
return false, err
}
// String helpers
func (info CONSOLE_SCREEN_BUFFER_INFO) String() string {
return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize)
}
func (coord COORD) String() string {
return fmt.Sprintf("%v,%v", coord.X, coord.Y)
}
func (rect SMALL_RECT) String() string {
return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom)
}
// checkError evaluates the results of a Windows API call and returns the error if it failed.
func checkError(r1, r2 uintptr, err error) error {
// Windows APIs return non-zero to indicate success
if r1 != 0 {
return nil
}
// Return the error if provided, otherwise default to EINVAL
if err != nil {
return err
}
return syscall.EINVAL
}
// coordToPointer converts a COORD into a uintptr (by fooling the type system).
func coordToPointer(c COORD) uintptr {
// Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass.
return uintptr(*((*uint32)(unsafe.Pointer(&c))))
}
// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
func use(p interface{}) {}

@ -0,0 +1,100 @@
// +build windows
package winterm
import "github.com/Azure/go-ansiterm"
const (
FOREGROUND_COLOR_MASK = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
BACKGROUND_COLOR_MASK = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
)
// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the
// request represented by the passed ANSI mode.
func collectAnsiIntoWindowsAttributes(windowsMode uint16, inverted bool, baseMode uint16, ansiMode int16) (uint16, bool) {
switch ansiMode {
// Mode styles
case ansiterm.ANSI_SGR_BOLD:
windowsMode = windowsMode | FOREGROUND_INTENSITY
case ansiterm.ANSI_SGR_DIM, ansiterm.ANSI_SGR_BOLD_DIM_OFF:
windowsMode &^= FOREGROUND_INTENSITY
case ansiterm.ANSI_SGR_UNDERLINE:
windowsMode = windowsMode | COMMON_LVB_UNDERSCORE
case ansiterm.ANSI_SGR_REVERSE:
inverted = true
case ansiterm.ANSI_SGR_REVERSE_OFF:
inverted = false
case ansiterm.ANSI_SGR_UNDERLINE_OFF:
windowsMode &^= COMMON_LVB_UNDERSCORE
// Foreground colors
case ansiterm.ANSI_SGR_FOREGROUND_DEFAULT:
windowsMode = (windowsMode &^ FOREGROUND_MASK) | (baseMode & FOREGROUND_MASK)
case ansiterm.ANSI_SGR_FOREGROUND_BLACK:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK)
case ansiterm.ANSI_SGR_FOREGROUND_RED:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED
case ansiterm.ANSI_SGR_FOREGROUND_GREEN:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN
case ansiterm.ANSI_SGR_FOREGROUND_YELLOW:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN
case ansiterm.ANSI_SGR_FOREGROUND_BLUE:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_BLUE
case ansiterm.ANSI_SGR_FOREGROUND_MAGENTA:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_BLUE
case ansiterm.ANSI_SGR_FOREGROUND_CYAN:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE
case ansiterm.ANSI_SGR_FOREGROUND_WHITE:
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
// Background colors
case ansiterm.ANSI_SGR_BACKGROUND_DEFAULT:
// Black with no intensity
windowsMode = (windowsMode &^ BACKGROUND_MASK) | (baseMode & BACKGROUND_MASK)
case ansiterm.ANSI_SGR_BACKGROUND_BLACK:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK)
case ansiterm.ANSI_SGR_BACKGROUND_RED:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED
case ansiterm.ANSI_SGR_BACKGROUND_GREEN:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN
case ansiterm.ANSI_SGR_BACKGROUND_YELLOW:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN
case ansiterm.ANSI_SGR_BACKGROUND_BLUE:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_BLUE
case ansiterm.ANSI_SGR_BACKGROUND_MAGENTA:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_BLUE
case ansiterm.ANSI_SGR_BACKGROUND_CYAN:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE
case ansiterm.ANSI_SGR_BACKGROUND_WHITE:
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
}
return windowsMode, inverted
}
// invertAttributes inverts the foreground and background colors of a Windows attributes value
func invertAttributes(windowsMode uint16) uint16 {
return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4)
}

@ -0,0 +1,101 @@
// +build windows
package winterm
const (
horizontal = iota
vertical
)
func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT {
if h.originMode {
sr := h.effectiveSr(info.Window)
return SMALL_RECT{
Top: sr.top,
Bottom: sr.bottom,
Left: 0,
Right: info.Size.X - 1,
}
} else {
return SMALL_RECT{
Top: info.Window.Top,
Bottom: info.Window.Bottom,
Left: 0,
Right: info.Size.X - 1,
}
}
}
// setCursorPosition sets the cursor to the specified position, bounded to the screen size
func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error {
position.X = ensureInRange(position.X, window.Left, window.Right)
position.Y = ensureInRange(position.Y, window.Top, window.Bottom)
err := SetConsoleCursorPosition(h.fd, position)
if err != nil {
return err
}
h.logf("Cursor position set: (%d, %d)", position.X, position.Y)
return err
}
func (h *windowsAnsiEventHandler) moveCursorVertical(param int) error {
return h.moveCursor(vertical, param)
}
func (h *windowsAnsiEventHandler) moveCursorHorizontal(param int) error {
return h.moveCursor(horizontal, param)
}
func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
position := info.CursorPosition
switch moveMode {
case horizontal:
position.X += int16(param)
case vertical:
position.Y += int16(param)
}
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) moveCursorLine(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
position := info.CursorPosition
position.X = 0
position.Y += int16(param)
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
position := info.CursorPosition
position.X = int16(param) - 1
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
return err
}
return nil
}

@ -0,0 +1,84 @@
// +build windows
package winterm
import "github.com/Azure/go-ansiterm"
func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD, toCoord COORD) error {
// Ignore an invalid (negative area) request
if toCoord.Y < fromCoord.Y {
return nil
}
var err error
var coordStart = COORD{}
var coordEnd = COORD{}
xCurrent, yCurrent := fromCoord.X, fromCoord.Y
xEnd, yEnd := toCoord.X, toCoord.Y
// Clear any partial initial line
if xCurrent > 0 {
coordStart.X, coordStart.Y = xCurrent, yCurrent
coordEnd.X, coordEnd.Y = xEnd, yCurrent
err = h.clearRect(attributes, coordStart, coordEnd)
if err != nil {
return err
}
xCurrent = 0
yCurrent += 1
}
// Clear intervening rectangular section
if yCurrent < yEnd {
coordStart.X, coordStart.Y = xCurrent, yCurrent
coordEnd.X, coordEnd.Y = xEnd, yEnd-1
err = h.clearRect(attributes, coordStart, coordEnd)
if err != nil {
return err
}
xCurrent = 0
yCurrent = yEnd
}
// Clear remaining partial ending line
coordStart.X, coordStart.Y = xCurrent, yCurrent
coordEnd.X, coordEnd.Y = xEnd, yEnd
err = h.clearRect(attributes, coordStart, coordEnd)
if err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error {
region := SMALL_RECT{Top: fromCoord.Y, Left: fromCoord.X, Bottom: toCoord.Y, Right: toCoord.X}
width := toCoord.X - fromCoord.X + 1
height := toCoord.Y - fromCoord.Y + 1
size := uint32(width) * uint32(height)
if size <= 0 {
return nil
}
buffer := make([]CHAR_INFO, size)
char := CHAR_INFO{ansiterm.FILL_CHARACTER, attributes}
for i := 0; i < int(size); i++ {
buffer[i] = char
}
err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region)
if err != nil {
return err
}
return nil
}

@ -0,0 +1,118 @@
// +build windows
package winterm
// effectiveSr gets the current effective scroll region in buffer coordinates
func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion {
top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom)
bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom)
if top >= bottom {
top = window.Top
bottom = window.Bottom
}
return scrollRegion{top: top, bottom: bottom}
}
func (h *windowsAnsiEventHandler) scrollUp(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
sr := h.effectiveSr(info.Window)
return h.scroll(param, sr, info)
}
func (h *windowsAnsiEventHandler) scrollDown(param int) error {
return h.scrollUp(-param)
}
func (h *windowsAnsiEventHandler) deleteLines(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
start := info.CursorPosition.Y
sr := h.effectiveSr(info.Window)
// Lines cannot be inserted or deleted outside the scrolling region.
if start >= sr.top && start <= sr.bottom {
sr.top = start
return h.scroll(param, sr, info)
} else {
return nil
}
}
func (h *windowsAnsiEventHandler) insertLines(param int) error {
return h.deleteLines(-param)
}
// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates.
func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error {
h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom)
h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom)
// Copy from and clip to the scroll region (full buffer width)
scrollRect := SMALL_RECT{
Top: sr.top,
Bottom: sr.bottom,
Left: 0,
Right: info.Size.X - 1,
}
// Origin to which area should be copied
destOrigin := COORD{
X: 0,
Y: sr.top - int16(param),
}
char := CHAR_INFO{
UnicodeChar: ' ',
Attributes: h.attributes,
}
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) deleteCharacters(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
return h.scrollLine(param, info.CursorPosition, info)
}
func (h *windowsAnsiEventHandler) insertCharacters(param int) error {
return h.deleteCharacters(-param)
}
// scrollLine scrolls a line horizontally starting at the provided position by a number of columns.
func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error {
// Copy from and clip to the scroll region (full buffer width)
scrollRect := SMALL_RECT{
Top: position.Y,
Bottom: position.Y,
Left: position.X,
Right: info.Size.X - 1,
}
// Origin to which area should be copied
destOrigin := COORD{
X: position.X - int16(columns),
Y: position.Y,
}
char := CHAR_INFO{
UnicodeChar: ' ',
Attributes: h.attributes,
}
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
return err
}
return nil
}

@ -0,0 +1,9 @@
// +build windows
package winterm
// AddInRange increments a value by the passed quantity while ensuring the values
// always remain within the supplied min / max range.
func addInRange(n int16, increment int16, min int16, max int16) int16 {
return ensureInRange(n+increment, min, max)
}

@ -0,0 +1,743 @@
// +build windows
package winterm
import (
"bytes"
"log"
"os"
"strconv"
"github.com/Azure/go-ansiterm"
)
type windowsAnsiEventHandler struct {
fd uintptr
file *os.File
infoReset *CONSOLE_SCREEN_BUFFER_INFO
sr scrollRegion
buffer bytes.Buffer
attributes uint16
inverted bool
wrapNext bool
drewMarginByte bool
originMode bool
marginByte byte
curInfo *CONSOLE_SCREEN_BUFFER_INFO
curPos COORD
logf func(string, ...interface{})
}
type Option func(*windowsAnsiEventHandler)
func WithLogf(f func(string, ...interface{})) Option {
return func(w *windowsAnsiEventHandler) {
w.logf = f
}
}
func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler {
infoReset, err := GetConsoleScreenBufferInfo(fd)
if err != nil {
return nil
}
h := &windowsAnsiEventHandler{
fd: fd,
file: file,
infoReset: infoReset,
attributes: infoReset.Attributes,
}
for _, o := range opts {
o(h)
}
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
logFile, _ := os.Create("winEventHandler.log")
logger := log.New(logFile, "", log.LstdFlags)
if h.logf != nil {
l := h.logf
h.logf = func(s string, v ...interface{}) {
l(s, v...)
logger.Printf(s, v...)
}
} else {
h.logf = logger.Printf
}
}
if h.logf == nil {
h.logf = func(string, ...interface{}) {}
}
return h
}
type scrollRegion struct {
top int16
bottom int16
}
// simulateLF simulates a LF or CR+LF by scrolling if necessary to handle the
// current cursor position and scroll region settings, in which case it returns
// true. If no special handling is necessary, then it does nothing and returns
// false.
//
// In the false case, the caller should ensure that a carriage return
// and line feed are inserted or that the text is otherwise wrapped.
func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) {
if h.wrapNext {
if err := h.Flush(); err != nil {
return false, err
}
h.clearWrap()
}
pos, info, err := h.getCurrentInfo()
if err != nil {
return false, err
}
sr := h.effectiveSr(info.Window)
if pos.Y == sr.bottom {
// Scrolling is necessary. Let Windows automatically scroll if the scrolling region
// is the full window.
if sr.top == info.Window.Top && sr.bottom == info.Window.Bottom {
if includeCR {
pos.X = 0
h.updatePos(pos)
}
return false, nil
}
// A custom scroll region is active. Scroll the window manually to simulate
// the LF.
if err := h.Flush(); err != nil {
return false, err
}
h.logf("Simulating LF inside scroll region")
if err := h.scrollUp(1); err != nil {
return false, err
}
if includeCR {
pos.X = 0
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return false, err
}
}
return true, nil
} else if pos.Y < info.Window.Bottom {
// Let Windows handle the LF.
pos.Y++
if includeCR {
pos.X = 0
}
h.updatePos(pos)
return false, nil
} else {
// The cursor is at the bottom of the screen but outside the scroll
// region. Skip the LF.
h.logf("Simulating LF outside scroll region")
if includeCR {
if err := h.Flush(); err != nil {
return false, err
}
pos.X = 0
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return false, err
}
}
return true, nil
}
}
// executeLF executes a LF without a CR.
func (h *windowsAnsiEventHandler) executeLF() error {
handled, err := h.simulateLF(false)
if err != nil {
return err
}
if !handled {
// Windows LF will reset the cursor column position. Write the LF
// and restore the cursor position.
pos, _, err := h.getCurrentInfo()
if err != nil {
return err
}
h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED)
if pos.X != 0 {
if err := h.Flush(); err != nil {
return err
}
h.logf("Resetting cursor position for LF without CR")
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err
}
}
}
return nil
}
func (h *windowsAnsiEventHandler) Print(b byte) error {
if h.wrapNext {
h.buffer.WriteByte(h.marginByte)
h.clearWrap()
if _, err := h.simulateLF(true); err != nil {
return err
}
}
pos, info, err := h.getCurrentInfo()
if err != nil {
return err
}
if pos.X == info.Size.X-1 {
h.wrapNext = true
h.marginByte = b
} else {
pos.X++
h.updatePos(pos)
h.buffer.WriteByte(b)
}
return nil
}
func (h *windowsAnsiEventHandler) Execute(b byte) error {
switch b {
case ansiterm.ANSI_TAB:
h.logf("Execute(TAB)")
// Move to the next tab stop, but preserve auto-wrap if already set.
if !h.wrapNext {
pos, info, err := h.getCurrentInfo()
if err != nil {
return err
}
pos.X = (pos.X + 8) - pos.X%8
if pos.X >= info.Size.X {
pos.X = info.Size.X - 1
}
if err := h.Flush(); err != nil {
return err
}
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err
}
}
return nil
case ansiterm.ANSI_BEL:
h.buffer.WriteByte(ansiterm.ANSI_BEL)
return nil
case ansiterm.ANSI_BACKSPACE:
if h.wrapNext {
if err := h.Flush(); err != nil {
return err
}
h.clearWrap()
}
pos, _, err := h.getCurrentInfo()
if err != nil {
return err
}
if pos.X > 0 {
pos.X--
h.updatePos(pos)
h.buffer.WriteByte(ansiterm.ANSI_BACKSPACE)
}
return nil
case ansiterm.ANSI_VERTICAL_TAB, ansiterm.ANSI_FORM_FEED:
// Treat as true LF.
return h.executeLF()
case ansiterm.ANSI_LINE_FEED:
// Simulate a CR and LF for now since there is no way in go-ansiterm
// to tell if the LF should include CR (and more things break when it's
// missing than when it's incorrectly added).
handled, err := h.simulateLF(true)
if handled || err != nil {
return err
}
return h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED)
case ansiterm.ANSI_CARRIAGE_RETURN:
if h.wrapNext {
if err := h.Flush(); err != nil {
return err
}
h.clearWrap()
}
pos, _, err := h.getCurrentInfo()
if err != nil {
return err
}
if pos.X != 0 {
pos.X = 0
h.updatePos(pos)
h.buffer.WriteByte(ansiterm.ANSI_CARRIAGE_RETURN)
}
return nil
default:
return nil
}
}
func (h *windowsAnsiEventHandler) CUU(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CUU: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorVertical(-param)
}
func (h *windowsAnsiEventHandler) CUD(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CUD: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorVertical(param)
}
func (h *windowsAnsiEventHandler) CUF(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CUF: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorHorizontal(param)
}
func (h *windowsAnsiEventHandler) CUB(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CUB: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorHorizontal(-param)
}
func (h *windowsAnsiEventHandler) CNL(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CNL: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorLine(param)
}
func (h *windowsAnsiEventHandler) CPL(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CPL: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorLine(-param)
}
func (h *windowsAnsiEventHandler) CHA(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CHA: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.moveCursorColumn(param)
}
func (h *windowsAnsiEventHandler) VPA(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("VPA: [[%d]]", param)
h.clearWrap()
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
window := h.getCursorWindow(info)
position := info.CursorPosition
position.Y = window.Top + int16(param) - 1
return h.setCursorPosition(position, window)
}
func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("CUP: [[%d %d]]", row, col)
h.clearWrap()
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
window := h.getCursorWindow(info)
position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1}
return h.setCursorPosition(position, window)
}
func (h *windowsAnsiEventHandler) HVP(row int, col int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("HVP: [[%d %d]]", row, col)
h.clearWrap()
return h.CUP(row, col)
}
func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)})
h.clearWrap()
return nil
}
func (h *windowsAnsiEventHandler) DECOM(enable bool) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)})
h.clearWrap()
h.originMode = enable
return h.CUP(1, 1)
}
func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)})
h.clearWrap()
if err := h.ED(2); err != nil {
return err
}
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
targetWidth := int16(80)
if use132 {
targetWidth = 132
}
if info.Size.X < targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
h.logf("set buffer failed: %v", err)
return err
}
}
window := info.Window
window.Left = 0
window.Right = targetWidth - 1
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
h.logf("set window failed: %v", err)
return err
}
if info.Size.X > targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
h.logf("set buffer failed: %v", err)
return err
}
}
return SetConsoleCursorPosition(h.fd, COORD{0, 0})
}
func (h *windowsAnsiEventHandler) ED(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("ED: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
// [J -- Erases from the cursor to the end of the screen, including the cursor position.
// [1J -- Erases from the beginning of the screen to the cursor, including the cursor position.
// [2J -- Erases the complete display. The cursor does not move.
// Notes:
// -- Clearing the entire buffer, versus just the Window, works best for Windows Consoles
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
var start COORD
var end COORD
switch param {
case 0:
start = info.CursorPosition
end = COORD{info.Size.X - 1, info.Size.Y - 1}
case 1:
start = COORD{0, 0}
end = info.CursorPosition
case 2:
start = COORD{0, 0}
end = COORD{info.Size.X - 1, info.Size.Y - 1}
}
err = h.clearRange(h.attributes, start, end)
if err != nil {
return err
}
// If the whole buffer was cleared, move the window to the top while preserving
// the window-relative cursor position.
if param == 2 {
pos := info.CursorPosition
window := info.Window
pos.Y -= window.Top
window.Bottom -= window.Top
window.Top = 0
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err
}
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
return err
}
}
return nil
}
func (h *windowsAnsiEventHandler) EL(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("EL: [%v]", strconv.Itoa(param))
h.clearWrap()
// [K -- Erases from the cursor to the end of the line, including the cursor position.
// [1K -- Erases from the beginning of the line to the cursor, including the cursor position.
// [2K -- Erases the complete line.
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
var start COORD
var end COORD
switch param {
case 0:
start = info.CursorPosition
end = COORD{info.Size.X, info.CursorPosition.Y}
case 1:
start = COORD{0, info.CursorPosition.Y}
end = info.CursorPosition
case 2:
start = COORD{0, info.CursorPosition.Y}
end = COORD{info.Size.X, info.CursorPosition.Y}
}
err = h.clearRange(h.attributes, start, end)
if err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) IL(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("IL: [%v]", strconv.Itoa(param))
h.clearWrap()
return h.insertLines(param)
}
func (h *windowsAnsiEventHandler) DL(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("DL: [%v]", strconv.Itoa(param))
h.clearWrap()
return h.deleteLines(param)
}
func (h *windowsAnsiEventHandler) ICH(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("ICH: [%v]", strconv.Itoa(param))
h.clearWrap()
return h.insertCharacters(param)
}
func (h *windowsAnsiEventHandler) DCH(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("DCH: [%v]", strconv.Itoa(param))
h.clearWrap()
return h.deleteCharacters(param)
}
func (h *windowsAnsiEventHandler) SGR(params []int) error {
if err := h.Flush(); err != nil {
return err
}
strings := []string{}
for _, v := range params {
strings = append(strings, strconv.Itoa(v))
}
h.logf("SGR: [%v]", strings)
if len(params) <= 0 {
h.attributes = h.infoReset.Attributes
h.inverted = false
} else {
for _, attr := range params {
if attr == ansiterm.ANSI_SGR_RESET {
h.attributes = h.infoReset.Attributes
h.inverted = false
continue
}
h.attributes, h.inverted = collectAnsiIntoWindowsAttributes(h.attributes, h.inverted, h.infoReset.Attributes, int16(attr))
}
}
attributes := h.attributes
if h.inverted {
attributes = invertAttributes(attributes)
}
err := SetConsoleTextAttribute(h.fd, attributes)
if err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) SU(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("SU: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.scrollUp(param)
}
func (h *windowsAnsiEventHandler) SD(param int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("SD: [%v]", []string{strconv.Itoa(param)})
h.clearWrap()
return h.scrollDown(param)
}
func (h *windowsAnsiEventHandler) DA(params []string) error {
h.logf("DA: [%v]", params)
// DA cannot be implemented because it must send data on the VT100 input stream,
// which is not available to go-ansiterm.
return nil
}
func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error {
if err := h.Flush(); err != nil {
return err
}
h.logf("DECSTBM: [%d, %d]", top, bottom)
// Windows is 0 indexed, Linux is 1 indexed
h.sr.top = int16(top - 1)
h.sr.bottom = int16(bottom - 1)
// This command also moves the cursor to the origin.
h.clearWrap()
return h.CUP(1, 1)
}
func (h *windowsAnsiEventHandler) RI() error {
if err := h.Flush(); err != nil {
return err
}
h.logf("RI: []")
h.clearWrap()
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
sr := h.effectiveSr(info.Window)
if info.CursorPosition.Y == sr.top {
return h.scrollDown(1)
}
return h.moveCursorVertical(-1)
}
func (h *windowsAnsiEventHandler) IND() error {
h.logf("IND: []")
return h.executeLF()
}
func (h *windowsAnsiEventHandler) Flush() error {
h.curInfo = nil
if h.buffer.Len() > 0 {
h.logf("Flush: [%s]", h.buffer.Bytes())
if _, err := h.buffer.WriteTo(h.file); err != nil {
return err
}
}
if h.wrapNext && !h.drewMarginByte {
h.logf("Flush: drawing margin byte '%c'", h.marginByte)
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return err
}
charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}}
size := COORD{1, 1}
position := COORD{0, 0}
region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y}
if err := WriteConsoleOutput(h.fd, charInfo, size, position, &region); err != nil {
return err
}
h.drewMarginByte = true
}
return nil
}
// cacheConsoleInfo ensures that the current console screen information has been queried
// since the last call to Flush(). It must be called before accessing h.curInfo or h.curPos.
func (h *windowsAnsiEventHandler) getCurrentInfo() (COORD, *CONSOLE_SCREEN_BUFFER_INFO, error) {
if h.curInfo == nil {
info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil {
return COORD{}, nil, err
}
h.curInfo = info
h.curPos = info.CursorPosition
}
return h.curPos, h.curInfo, nil
}
func (h *windowsAnsiEventHandler) updatePos(pos COORD) {
if h.curInfo == nil {
panic("failed to call getCurrentInfo before calling updatePos")
}
h.curPos = pos
}
// clearWrap clears the state where the cursor is in the margin
// waiting for the next character before wrapping the line. This must
// be done before most operations that act on the cursor.
func (h *windowsAnsiEventHandler) clearWrap() {
h.wrapNext = false
h.drewMarginByte = false
}

@ -0,0 +1,8 @@
# if you want to ignore files created by your editor/tools, consider using a
# global .gitignore or .git/info/exclude see https://help.github.com/articles/ignoring-files
.*
!.github
!.gitignore
profile.out
# support running go modules in vendor mode for local development
vendor/

191
vendor/github.com/moby/term/LICENSE generated vendored

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2013-2018 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -0,0 +1,36 @@
# term - utilities for dealing with terminals
![Test](https://github.com/moby/term/workflows/Test/badge.svg) [![GoDoc](https://godoc.org/github.com/moby/term?status.svg)](https://godoc.org/github.com/moby/term) [![Go Report Card](https://goreportcard.com/badge/github.com/moby/term)](https://goreportcard.com/report/github.com/moby/term)
term provides structures and helper functions to work with terminal (state, sizes).
#### Using term
```go
package main
import (
"log"
"os"
"github.com/moby/term"
)
func main() {
fd := os.Stdin.Fd()
if term.IsTerminal(fd) {
ws, err := term.GetWinsize(fd)
if err != nil {
log.Fatalf("term.GetWinsize: %s", err)
}
log.Printf("%d:%d\n", ws.Height, ws.Width)
}
}
```
## Contributing
Want to hack on term? [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) apply.
## Copyright and license
Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons.

@ -0,0 +1,66 @@
package term
import (
"fmt"
"strings"
)
// ASCII list the possible supported ASCII key sequence
var ASCII = []string{
"ctrl-@",
"ctrl-a",
"ctrl-b",
"ctrl-c",
"ctrl-d",
"ctrl-e",
"ctrl-f",
"ctrl-g",
"ctrl-h",
"ctrl-i",
"ctrl-j",
"ctrl-k",
"ctrl-l",
"ctrl-m",
"ctrl-n",
"ctrl-o",
"ctrl-p",
"ctrl-q",
"ctrl-r",
"ctrl-s",
"ctrl-t",
"ctrl-u",
"ctrl-v",
"ctrl-w",
"ctrl-x",
"ctrl-y",
"ctrl-z",
"ctrl-[",
"ctrl-\\",
"ctrl-]",
"ctrl-^",
"ctrl-_",
}
// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code.
func ToBytes(keys string) ([]byte, error) {
codes := []byte{}
next:
for _, key := range strings.Split(keys, ",") {
if len(key) != 1 {
for code, ctrl := range ASCII {
if ctrl == key {
codes = append(codes, byte(code))
continue next
}
}
if key == "DEL" {
codes = append(codes, 127)
} else {
return nil, fmt.Errorf("Unknown character: '%s'", key)
}
} else {
codes = append(codes, key[0])
}
}
return codes, nil
}

@ -0,0 +1,12 @@
module github.com/moby/term
go 1.13
require (
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78
github.com/creack/pty v1.1.9
github.com/google/go-cmp v0.4.0
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a
gotest.tools/v3 v3.0.2
)

@ -0,0 +1,23 @@
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a h1:i47hUS795cOydZI4AwJQCKXOr4BvxzvikwDoDtHhP2Y=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=

@ -0,0 +1,88 @@
package term
import (
"io"
)
// EscapeError is special error which returned by a TTY proxy reader's Read()
// method in case its detach escape sequence is read.
type EscapeError struct{}
func (EscapeError) Error() string {
return "read escape sequence"
}
// escapeProxy is used only for attaches with a TTY. It is used to proxy
// stdin keypresses from the underlying reader and look for the passed in
// escape key sequence to signal a detach.
type escapeProxy struct {
escapeKeys []byte
escapeKeyPos int
r io.Reader
buf []byte
}
// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader
// and detects when the specified escape keys are read, in which case the Read
// method will return an error of type EscapeError.
func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader {
return &escapeProxy{
escapeKeys: escapeKeys,
r: r,
}
}
func (r *escapeProxy) Read(buf []byte) (n int, err error) {
if len(r.escapeKeys) > 0 && r.escapeKeyPos == len(r.escapeKeys) {
return 0, EscapeError{}
}
if len(r.buf) > 0 {
n = copy(buf, r.buf)
r.buf = r.buf[n:]
}
nr, err := r.r.Read(buf[n:])
n += nr
if len(r.escapeKeys) == 0 {
return n, err
}
for i := 0; i < n; i++ {
if buf[i] == r.escapeKeys[r.escapeKeyPos] {
r.escapeKeyPos++
// Check if the full escape sequence is matched.
if r.escapeKeyPos == len(r.escapeKeys) {
n = i + 1 - r.escapeKeyPos
if n < 0 {
n = 0
}
return n, EscapeError{}
}
continue
}
// If we need to prepend a partial escape sequence from the previous
// read, make sure the new buffer size doesn't exceed len(buf).
// Otherwise, preserve any extra data in a buffer for the next read.
if i < r.escapeKeyPos {
preserve := make([]byte, 0, r.escapeKeyPos+n)
preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...)
preserve = append(preserve, buf[:n]...)
n = copy(buf, preserve)
i += r.escapeKeyPos
r.buf = append(r.buf, preserve[n:]...)
}
r.escapeKeyPos = 0
}
// If we're in the middle of reading an escape sequence, make sure we don't
// let the caller read it. If later on we find that this is not the escape
// sequence, we'll prepend it back to buf.
n -= r.escapeKeyPos
if n < 0 {
n = 0
}
return n, err
}

19
vendor/github.com/moby/term/tc.go generated vendored

@ -0,0 +1,19 @@
// +build !windows
package term
import (
"golang.org/x/sys/unix"
)
func tcget(fd uintptr) (*Termios, error) {
p, err := unix.IoctlGetTermios(int(fd), getTermios)
if err != nil {
return nil, err
}
return p, nil
}
func tcset(fd uintptr, p *Termios) error {
return unix.IoctlSetTermios(int(fd), setTermios, p)
}

120
vendor/github.com/moby/term/term.go generated vendored

@ -0,0 +1,120 @@
// +build !windows
// Package term provides structures and helper functions to work with
// terminal (state, sizes).
package term
import (
"errors"
"fmt"
"io"
"os"
"os/signal"
"golang.org/x/sys/unix"
)
var (
// ErrInvalidState is returned if the state of the terminal is invalid.
ErrInvalidState = errors.New("Invalid terminal state")
)
// State represents the state of the terminal.
type State struct {
termios Termios
}
// Winsize represents the size of the terminal window.
type Winsize struct {
Height uint16
Width uint16
x uint16
y uint16
}
// StdStreams returns the standard streams (stdin, stdout, stderr).
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
return os.Stdin, os.Stdout, os.Stderr
}
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
func GetFdInfo(in interface{}) (uintptr, bool) {
var inFd uintptr
var isTerminalIn bool
if file, ok := in.(*os.File); ok {
inFd = file.Fd()
isTerminalIn = IsTerminal(inFd)
}
return inFd, isTerminalIn
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
_, err := tcget(fd)
return err == nil
}
// RestoreTerminal restores the terminal connected to the given file descriptor
// to a previous state.
func RestoreTerminal(fd uintptr, state *State) error {
if state == nil {
return ErrInvalidState
}
return tcset(fd, &state.termios)
}
// SaveState saves the state of the terminal connected to the given file descriptor.
func SaveState(fd uintptr) (*State, error) {
termios, err := tcget(fd)
if err != nil {
return nil, err
}
return &State{termios: *termios}, nil
}
// DisableEcho applies the specified state to the terminal connected to the file
// descriptor, with echo disabled.
func DisableEcho(fd uintptr, state *State) error {
newState := state.termios
newState.Lflag &^= unix.ECHO
if err := tcset(fd, &newState); err != nil {
return err
}
handleInterrupt(fd, state)
return nil
}
// SetRawTerminal puts the terminal connected to the given file descriptor into
// raw mode and returns the previous state. On UNIX, this puts both the input
// and output into raw mode. On Windows, it only puts the input into raw mode.
func SetRawTerminal(fd uintptr) (*State, error) {
oldState, err := MakeRaw(fd)
if err != nil {
return nil, err
}
handleInterrupt(fd, oldState)
return oldState, err
}
// SetRawTerminalOutput puts the output of terminal connected to the given file
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
// state. On Windows, it disables LF -> CRLF translation.
func SetRawTerminalOutput(fd uintptr) (*State, error) {
return nil, nil
}
func handleInterrupt(fd uintptr, state *State) {
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
go func() {
for range sigchan {
// quit cleanly and the new terminal item is on a new line
fmt.Println()
signal.Stop(sigchan)
close(sigchan)
RestoreTerminal(fd, state)
os.Exit(1)
}
}()
}

@ -0,0 +1,228 @@
package term
import (
"io"
"os"
"os/signal"
windowsconsole "github.com/moby/term/windows"
"golang.org/x/sys/windows"
)
// State holds the console mode for the terminal.
type State struct {
mode uint32
}
// Winsize is used for window size.
type Winsize struct {
Height uint16
Width uint16
}
// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console
var vtInputSupported bool
// StdStreams returns the standard streams (stdin, stdout, stderr).
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
// Turn on VT handling on all std handles, if possible. This might
// fail, in which case we will fall back to terminal emulation.
var (
emulateStdin, emulateStdout, emulateStderr bool
mode uint32
)
fd := windows.Handle(os.Stdin.Fd())
if err := windows.GetConsoleMode(fd, &mode); err == nil {
// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
emulateStdin = true
} else {
vtInputSupported = true
}
// Unconditionally set the console mode back even on failure because SetConsoleMode
// remembers invalid bits on input handles.
_ = windows.SetConsoleMode(fd, mode)
}
fd = windows.Handle(os.Stdout.Fd())
if err := windows.GetConsoleMode(fd, &mode); err == nil {
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
emulateStdout = true
} else {
_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
}
}
fd = windows.Handle(os.Stderr.Fd())
if err := windows.GetConsoleMode(fd, &mode); err == nil {
// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it.
if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
emulateStderr = true
} else {
_ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
}
}
// Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and
// STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as
// go-ansiterm hasn't switch to x/sys/windows.
// TODO: switch back to x/sys/windows once go-ansiterm has switched
if emulateStdin {
stdIn = windowsconsole.NewAnsiReader(windows.STD_INPUT_HANDLE)
} else {
stdIn = os.Stdin
}
if emulateStdout {
stdOut = windowsconsole.NewAnsiWriter(windows.STD_OUTPUT_HANDLE)
} else {
stdOut = os.Stdout
}
if emulateStderr {
stdErr = windowsconsole.NewAnsiWriter(windows.STD_ERROR_HANDLE)
} else {
stdErr = os.Stderr
}
return
}
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
func GetFdInfo(in interface{}) (uintptr, bool) {
return windowsconsole.GetHandleInfo(in)
}
// GetWinsize returns the window size based on the specified file descriptor.
func GetWinsize(fd uintptr) (*Winsize, error) {
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
return nil, err
}
winsize := &Winsize{
Width: uint16(info.Window.Right - info.Window.Left + 1),
Height: uint16(info.Window.Bottom - info.Window.Top + 1),
}
return winsize, nil
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
var mode uint32
err := windows.GetConsoleMode(windows.Handle(fd), &mode)
return err == nil
}
// RestoreTerminal restores the terminal connected to the given file descriptor
// to a previous state.
func RestoreTerminal(fd uintptr, state *State) error {
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}
// SaveState saves the state of the terminal connected to the given file descriptor.
func SaveState(fd uintptr) (*State, error) {
var mode uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil {
return nil, err
}
return &State{mode: mode}, nil
}
// DisableEcho disables echo for the terminal connected to the given file descriptor.
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
func DisableEcho(fd uintptr, state *State) error {
mode := state.mode
mode &^= windows.ENABLE_ECHO_INPUT
mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT
err := windows.SetConsoleMode(windows.Handle(fd), mode)
if err != nil {
return err
}
// Register an interrupt handler to catch and restore prior state
restoreAtInterrupt(fd, state)
return nil
}
// SetRawTerminal puts the terminal connected to the given file descriptor into
// raw mode and returns the previous state. On UNIX, this puts both the input
// and output into raw mode. On Windows, it only puts the input into raw mode.
func SetRawTerminal(fd uintptr) (*State, error) {
state, err := MakeRaw(fd)
if err != nil {
return nil, err
}
// Register an interrupt handler to catch and restore prior state
restoreAtInterrupt(fd, state)
return state, err
}
// SetRawTerminalOutput puts the output of terminal connected to the given file
// descriptor into raw mode. On UNIX, this does nothing and returns nil for the
// state. On Windows, it disables LF -> CRLF translation.
func SetRawTerminalOutput(fd uintptr) (*State, error) {
state, err := SaveState(fd)
if err != nil {
return nil, err
}
// Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this
// version of Windows.
_ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
return state, err
}
// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be restored.
func MakeRaw(fd uintptr) (*State, error) {
state, err := SaveState(fd)
if err != nil {
return nil, err
}
mode := state.mode
// See
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
// Disable these modes
mode &^= windows.ENABLE_ECHO_INPUT
mode &^= windows.ENABLE_LINE_INPUT
mode &^= windows.ENABLE_MOUSE_INPUT
mode &^= windows.ENABLE_WINDOW_INPUT
mode &^= windows.ENABLE_PROCESSED_INPUT
// Enable these modes
mode |= windows.ENABLE_EXTENDED_FLAGS
mode |= windows.ENABLE_INSERT_MODE
mode |= windows.ENABLE_QUICK_EDIT_MODE
if vtInputSupported {
mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
}
err = windows.SetConsoleMode(windows.Handle(fd), mode)
if err != nil {
return nil, err
}
return state, nil
}
func restoreAtInterrupt(fd uintptr, state *State) {
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
go func() {
_ = <-sigchan
_ = RestoreTerminal(fd, state)
os.Exit(0)
}()
}

@ -0,0 +1,35 @@
// +build !windows
package term
import (
"golang.org/x/sys/unix"
)
// Termios is the Unix API for terminal I/O.
type Termios = unix.Termios
// MakeRaw puts the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd uintptr) (*State, error) {
termios, err := tcget(fd)
if err != nil {
return nil, err
}
oldState := State{termios: *termios}
termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
termios.Oflag &^= unix.OPOST
termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
termios.Cflag &^= (unix.CSIZE | unix.PARENB)
termios.Cflag |= unix.CS8
termios.Cc[unix.VMIN] = 1
termios.Cc[unix.VTIME] = 0
if err := tcset(fd, termios); err != nil {
return nil, err
}
return &oldState, nil
}

@ -0,0 +1,12 @@
// +build darwin freebsd openbsd netbsd
package term
import (
"golang.org/x/sys/unix"
)
const (
getTermios = unix.TIOCGETA
setTermios = unix.TIOCSETA
)

@ -0,0 +1,12 @@
//+build !darwin,!freebsd,!netbsd,!openbsd,!windows
package term
import (
"golang.org/x/sys/unix"
)
const (
getTermios = unix.TCGETS
setTermios = unix.TCSETS
)

@ -0,0 +1,252 @@
// +build windows
package windowsconsole
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"strings"
"unsafe"
ansiterm "github.com/Azure/go-ansiterm"
"github.com/Azure/go-ansiterm/winterm"
)
const (
escapeSequence = ansiterm.KEY_ESC_CSI
)
// ansiReader wraps a standard input file (e.g., os.Stdin) providing ANSI sequence translation.
type ansiReader struct {
file *os.File
fd uintptr
buffer []byte
cbBuffer int
command []byte
}
// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a
// Windows console input handle.
func NewAnsiReader(nFile int) io.ReadCloser {
file, fd := winterm.GetStdFile(nFile)
return &ansiReader{
file: file,
fd: fd,
command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH),
buffer: make([]byte, 0),
}
}
// Close closes the wrapped file.
func (ar *ansiReader) Close() (err error) {
return ar.file.Close()
}
// Fd returns the file descriptor of the wrapped file.
func (ar *ansiReader) Fd() uintptr {
return ar.fd
}
// Read reads up to len(p) bytes of translated input events into p.
func (ar *ansiReader) Read(p []byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
// Previously read bytes exist, read as much as we can and return
if len(ar.buffer) > 0 {
originalLength := len(ar.buffer)
copiedLength := copy(p, ar.buffer)
if copiedLength == originalLength {
ar.buffer = make([]byte, 0, len(p))
} else {
ar.buffer = ar.buffer[copiedLength:]
}
return copiedLength, nil
}
// Read and translate key events
events, err := readInputEvents(ar, len(p))
if err != nil {
return 0, err
} else if len(events) == 0 {
return 0, nil
}
keyBytes := translateKeyEvents(events, []byte(escapeSequence))
// Save excess bytes and right-size keyBytes
if len(keyBytes) > len(p) {
ar.buffer = keyBytes[len(p):]
keyBytes = keyBytes[:len(p)]
} else if len(keyBytes) == 0 {
return 0, nil
}
copiedLength := copy(p, keyBytes)
if copiedLength != len(keyBytes) {
return 0, errors.New("unexpected copy length encountered")
}
return copiedLength, nil
}
// readInputEvents polls until at least one event is available.
func readInputEvents(ar *ansiReader, maxBytes int) ([]winterm.INPUT_RECORD, error) {
// Determine the maximum number of records to retrieve
// -- Cast around the type system to obtain the size of a single INPUT_RECORD.
// unsafe.Sizeof requires an expression vs. a type-reference; the casting
// tricks the type system into believing it has such an expression.
recordSize := int(unsafe.Sizeof(*((*winterm.INPUT_RECORD)(unsafe.Pointer(&maxBytes)))))
countRecords := maxBytes / recordSize
if countRecords > ansiterm.MAX_INPUT_EVENTS {
countRecords = ansiterm.MAX_INPUT_EVENTS
} else if countRecords == 0 {
countRecords = 1
}
// Wait for and read input events
events := make([]winterm.INPUT_RECORD, countRecords)
nEvents := uint32(0)
eventsExist, err := winterm.WaitForSingleObject(ar.fd, winterm.WAIT_INFINITE)
if err != nil {
return nil, err
}
if eventsExist {
err = winterm.ReadConsoleInput(ar.fd, events, &nEvents)
if err != nil {
return nil, err
}
}
// Return a slice restricted to the number of returned records
return events[:nEvents], nil
}
// KeyEvent Translation Helpers
var arrowKeyMapPrefix = map[uint16]string{
winterm.VK_UP: "%s%sA",
winterm.VK_DOWN: "%s%sB",
winterm.VK_RIGHT: "%s%sC",
winterm.VK_LEFT: "%s%sD",
}
var keyMapPrefix = map[uint16]string{
winterm.VK_UP: "\x1B[%sA",
winterm.VK_DOWN: "\x1B[%sB",
winterm.VK_RIGHT: "\x1B[%sC",
winterm.VK_LEFT: "\x1B[%sD",
winterm.VK_HOME: "\x1B[1%s~", // showkey shows ^[[1
winterm.VK_END: "\x1B[4%s~", // showkey shows ^[[4
winterm.VK_INSERT: "\x1B[2%s~",
winterm.VK_DELETE: "\x1B[3%s~",
winterm.VK_PRIOR: "\x1B[5%s~",
winterm.VK_NEXT: "\x1B[6%s~",
winterm.VK_F1: "",
winterm.VK_F2: "",
winterm.VK_F3: "\x1B[13%s~",
winterm.VK_F4: "\x1B[14%s~",
winterm.VK_F5: "\x1B[15%s~",
winterm.VK_F6: "\x1B[17%s~",
winterm.VK_F7: "\x1B[18%s~",
winterm.VK_F8: "\x1B[19%s~",
winterm.VK_F9: "\x1B[20%s~",
winterm.VK_F10: "\x1B[21%s~",
winterm.VK_F11: "\x1B[23%s~",
winterm.VK_F12: "\x1B[24%s~",
}
// translateKeyEvents converts the input events into the appropriate ANSI string.
func translateKeyEvents(events []winterm.INPUT_RECORD, escapeSequence []byte) []byte {
var buffer bytes.Buffer
for _, event := range events {
if event.EventType == winterm.KEY_EVENT && event.KeyEvent.KeyDown != 0 {
buffer.WriteString(keyToString(&event.KeyEvent, escapeSequence))
}
}
return buffer.Bytes()
}
// keyToString maps the given input event record to the corresponding string.
func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) string {
if keyEvent.UnicodeChar == 0 {
return formatVirtualKey(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence)
}
_, alt, control := getControlKeys(keyEvent.ControlKeyState)
if control {
// TODO(azlinux): Implement following control sequences
// <Ctrl>-D Signals the end of input from the keyboard; also exits current shell.
// <Ctrl>-H Deletes the first character to the left of the cursor. Also called the ERASE key.
// <Ctrl>-Q Restarts printing after it has been stopped with <Ctrl>-s.
// <Ctrl>-S Suspends printing on the screen (does not stop the program).
// <Ctrl>-U Deletes all characters on the current line. Also called the KILL key.
// <Ctrl>-E Quits current command and creates a core
}
// <Alt>+Key generates ESC N Key
if !control && alt {
return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar))
}
return string(keyEvent.UnicodeChar)
}
// formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string.
func formatVirtualKey(key uint16, controlState uint32, escapeSequence []byte) string {
shift, alt, control := getControlKeys(controlState)
modifier := getControlKeysModifier(shift, alt, control)
if format, ok := arrowKeyMapPrefix[key]; ok {
return fmt.Sprintf(format, escapeSequence, modifier)
}
if format, ok := keyMapPrefix[key]; ok {
return fmt.Sprintf(format, modifier)
}
return ""
}
// getControlKeys extracts the shift, alt, and ctrl key states.
func getControlKeys(controlState uint32) (shift, alt, control bool) {
shift = 0 != (controlState & winterm.SHIFT_PRESSED)
alt = 0 != (controlState & (winterm.LEFT_ALT_PRESSED | winterm.RIGHT_ALT_PRESSED))
control = 0 != (controlState & (winterm.LEFT_CTRL_PRESSED | winterm.RIGHT_CTRL_PRESSED))
return shift, alt, control
}
// getControlKeysModifier returns the ANSI modifier for the given combination of control keys.
func getControlKeysModifier(shift, alt, control bool) string {
if shift && alt && control {
return ansiterm.KEY_CONTROL_PARAM_8
}
if alt && control {
return ansiterm.KEY_CONTROL_PARAM_7
}
if shift && control {
return ansiterm.KEY_CONTROL_PARAM_6
}
if control {
return ansiterm.KEY_CONTROL_PARAM_5
}
if shift && alt {
return ansiterm.KEY_CONTROL_PARAM_4
}
if alt {
return ansiterm.KEY_CONTROL_PARAM_3
}
if shift {
return ansiterm.KEY_CONTROL_PARAM_2
}
return ""
}

@ -0,0 +1,56 @@
// +build windows
package windowsconsole
import (
"io"
"os"
ansiterm "github.com/Azure/go-ansiterm"
"github.com/Azure/go-ansiterm/winterm"
)
// ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation.
type ansiWriter struct {
file *os.File
fd uintptr
infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO
command []byte
escapeSequence []byte
inAnsiSequence bool
parser *ansiterm.AnsiParser
}
// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
// Windows console output handle.
func NewAnsiWriter(nFile int) io.Writer {
file, fd := winterm.GetStdFile(nFile)
info, err := winterm.GetConsoleScreenBufferInfo(fd)
if err != nil {
return nil
}
parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file))
return &ansiWriter{
file: file,
fd: fd,
infoReset: info,
command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH),
escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
parser: parser,
}
}
func (aw *ansiWriter) Fd() uintptr {
return aw.fd
}
// Write writes len(p) bytes from p to the underlying data stream.
func (aw *ansiWriter) Write(p []byte) (total int, err error) {
if len(p) == 0 {
return 0, nil
}
return aw.parser.Parse(p)
}

@ -0,0 +1,39 @@
// +build windows
package windowsconsole
import (
"os"
"golang.org/x/sys/windows"
)
// GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
func GetHandleInfo(in interface{}) (uintptr, bool) {
switch t := in.(type) {
case *ansiReader:
return t.Fd(), true
case *ansiWriter:
return t.Fd(), true
}
var inFd uintptr
var isTerminal bool
if file, ok := in.(*os.File); ok {
inFd = file.Fd()
isTerminal = isConsole(inFd)
}
return inFd, isTerminal
}
// IsConsole returns true if the given file descriptor is a Windows Console.
// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
// Deprecated: use golang.org/x/sys/windows.GetConsoleMode() or golang.org/x/crypto/ssh/terminal.IsTerminal()
var IsConsole = isConsole
func isConsole(fd uintptr) bool {
var mode uint32
err := windows.GetConsoleMode(windows.Handle(fd), &mode)
return err == nil
}

@ -0,0 +1,5 @@
// These files implement ANSI-aware input and output streams for use by the Docker Windows client.
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.
package windowsconsole

@ -0,0 +1,20 @@
// +build !windows
package term
import (
"golang.org/x/sys/unix"
)
// GetWinsize returns the window size based on the specified file descriptor.
func GetWinsize(fd uintptr) (*Winsize, error) {
uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel}
return ws, err
}
// SetWinsize tries to set the specified window size for the specified file descriptor.
func SetWinsize(fd uintptr, ws *Winsize) error {
uws := &unix.Winsize{Row: ws.Height, Col: ws.Width, Xpixel: ws.x, Ypixel: ws.y}
return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, uws)
}

@ -0,0 +1,30 @@
// Copyright 2020 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.
// Package unsafeheader contains header declarations for the Go runtime's
// slice and string implementations.
//
// This package allows x/sys to use types equivalent to
// reflect.SliceHeader and reflect.StringHeader without introducing
// a dependency on the (relatively heavy) "reflect" package.
package unsafeheader
import (
"unsafe"
)
// Slice is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may change in a later release.
type Slice struct {
Data unsafe.Pointer
Len int
Cap int
}
// String is the runtime representation of a string.
// It cannot be used safely or portably and its representation may change in a later release.
type String struct {
Data unsafe.Pointer
Len int
}

@ -89,7 +89,7 @@ constants.
Adding new syscall numbers is mostly done by running the build on a sufficiently
new installation of the target OS (or updating the source checkouts for the
new build system). However, depending on the OS, you make need to update the
new build system). However, depending on the OS, you may need to update the
parsing in mksysnum.
### mksyscall.go
@ -149,10 +149,21 @@ To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants.
### mkmerge.go
This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these
into a common file for each OS.
The merge is performed in the following steps:
1. Construct the set of common code that is idential in all architecture-specific files.
2. Write this common code to the merged file.
3. Remove the common code from all architecture-specific files.
## Generated files
### `zerror_${GOOS}_${GOARCH}.go`
### `zerrors_${GOOS}_${GOARCH}.go`
A file containing all of the system's generated error numbers, error strings,
signal numbers, and constants. Generated by `mkerrors.sh` (see above).

@ -23,10 +23,6 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV $0, A3
MOV $0, A4
MOV $0, A5
MOV $0, A6
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP) // r1
@ -44,9 +40,6 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV ZERO, A3
MOV ZERO, A4
MOV ZERO, A5
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP)

@ -0,0 +1,29 @@
// Copyright 2019 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.
// +build !gccgo
#include "textflag.h"
//
// System call support for mips64, OpenBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)

@ -8,6 +8,7 @@
package unix
const (
DLT_HHDLC = 0x79
IFF_SMART = 0x20
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
@ -210,13 +211,18 @@ const (
IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_FAITH = 0x16
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
SIOCADDRT = 0x8030720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8030720b

@ -8,6 +8,7 @@
package unix
const (
DLT_HHDLC = 0x79
IFF_SMART = 0x20
IFT_1822 = 0x2
IFT_A12MPPSWITCH = 0x82
@ -210,13 +211,18 @@ const (
IFT_XETHER = 0x1a
IPPROTO_MAXID = 0x34
IPV6_FAITH = 0x1d
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_FAITH = 0x16
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
MAP_NORESERVE = 0x40
MAP_RENAME = 0x20
NET_RT_MAXID = 0x6
RTF_PRCLONING = 0x10000
RTM_OLDADD = 0x9
RTM_OLDDEL = 0xa
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
SIOCADDRT = 0x8040720a
SIOCALIFADDR = 0x8118691b
SIOCDELRT = 0x8040720b

@ -0,0 +1,17 @@
// Copyright 2020 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.
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
// them here for backwards compatibility.
package unix
const (
DLT_HHDLC = 0x79
IPV6_MIN_MEMBERSHIPS = 0x1f
IP_MAX_SOURCE_FILTER = 0x400
IP_MIN_MEMBERSHIPS = 0x1f
RT_CACHING_CONTEXT = 0x1
RT_NORTREF = 0x2
)

@ -20,6 +20,15 @@ func IoctlSetInt(fd int, req uint, value int) error {
return ioctl(fd, req, uintptr(value))
}
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
v := int32(value)
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
//
// To change fd's window size, the req argument should be TIOCSWINSZ.

@ -73,26 +73,22 @@ aix_ppc64)
darwin_386)
mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
darwin_amd64)
mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
darwin_arm)
mkerrors="$mkerrors"
mksyscall="go run mksyscall.go -l32"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
darwin_arm64)
mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
@ -124,7 +120,7 @@ freebsd_arm)
freebsd_arm64)
mkerrors="$mkerrors -m64"
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
netbsd_386)
mkerrors="$mkerrors -m32"
@ -184,12 +180,27 @@ openbsd_arm64)
# API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
openbsd_mips64)
mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -openbsd"
mksysctl="go run mksysctl_openbsd.go"
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
# Let the type of C char be signed for making the bare syscall
# API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;;
solaris_amd64)
mksyscall="go run mksyscall_solaris.go"
mkerrors="$mkerrors -m64"
mksysnum=
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
illumos_amd64)
mksyscall="go run mksyscall_solaris.go"
mkerrors=
mksysnum=
mktypes=
;;
*)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1
@ -211,12 +222,15 @@ esac
# aix/ppc64 script generates files instead of writing to stdin.
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
elif [ "$GOOS" == "darwin" ]; then
# pre-1.12, direct syscalls
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
# 1.12 and later, syscalls via libSystem
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
# 1.13 and later, syscalls via libSystem (including syscallPtr)
echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
elif [ "$GOOS" == "illumos" ]; then
# illumos code generation requires a --illumos switch
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
# illumos implies solaris, so solaris code generation is also required
echo "$mksyscall -tags solaris,$GOARCH syscall_solaris.go syscall_solaris_$GOARCH.go |gofmt >zsyscall_solaris_$GOARCH.go";
else
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
fi

@ -105,7 +105,9 @@ includes_FreeBSD='
#include <sys/capsicum.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/disk.h>
#include <sys/event.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@ -186,19 +188,24 @@ struct ltchars {
#include <sys/select.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/timerfd.h>
#include <sys/uio.h>
#include <sys/xattr.h>
#include <linux/bpf.h>
#include <linux/can.h>
#include <linux/can/error.h>
#include <linux/can/raw.h>
#include <linux/capability.h>
#include <linux/cryptouser.h>
#include <linux/devlink.h>
#include <linux/dm-ioctl.h>
#include <linux/errqueue.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/fscrypt.h>
#include <linux/fsverity.h>
#include <linux/genetlink.h>
#include <linux/hdreg.h>
#include <linux/icmpv6.h>
@ -280,6 +287,11 @@ struct ltchars {
// for the tipc_subscr timeout __u32 field.
#undef TIPC_WAIT_FOREVER
#define TIPC_WAIT_FOREVER 0xffffffff
// Copied from linux/l2tp.h
// Including linux/l2tp.h here causes conflicts between linux/in.h
// and netinet/in.h included via net/route.h above.
#define IPPROTO_L2TP 115
'
includes_NetBSD='
@ -289,6 +301,7 @@ includes_NetBSD='
#include <sys/extattr.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@ -317,6 +330,7 @@ includes_OpenBSD='
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/select.h>
#include <sys/sched.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
@ -473,12 +487,13 @@ ccflags="$@"
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
$2 ~ /^KEXEC_/ ||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
$2 ~ /^MODULE_INIT_/ ||
$2 !~ "NLA_TYPE_MASK" &&
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
$2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ ||
@ -486,8 +501,9 @@ ccflags="$@"
$2 ~ /^TCSET/ ||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
$2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ ||
$2 ~ /^DIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
@ -497,10 +513,14 @@ ccflags="$@"
$2 ~ /^(CLOCK|TIMER)_/ ||
$2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ ||
$2 ~ /^CP_/ ||
$2 ~ /^CPUSTATES$/ ||
$2 ~ /^ALG_/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
$2 ~ /^FS_IOC_.*ENCRYPTION/ ||
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
$2 ~ /^FS_VERITY_/ ||
$2 ~ /^FSCRYPT_/ ||
$2 ~ /^DM_/ ||
$2 ~ /^GRND_/ ||
$2 ~ /^RND/ ||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||

@ -510,6 +510,40 @@ func SysctlRaw(name string, args ...int) ([]byte, error) {
return buf[:n], nil
}
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
func SysctlTimeval(name string) (*Timeval, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
var tv Timeval
n := uintptr(unsafe.Sizeof(tv))
if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil {
return nil, err
}
if n != unsafe.Sizeof(tv) {
return nil, EIO
}
return &tv, nil
}
//sys utimes(path string, timeval *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error {

@ -10,6 +10,8 @@ import (
"unsafe"
)
const _SYS_GETDIRENTRIES64 = 344
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// To implement this using libSystem we'd need syscall_syscallPtr for
// fdopendir. However, syscallPtr was only added in Go 1.13, so we fall
@ -20,7 +22,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
} else {
p = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
r0, _, e1 := Syscall6(_SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
n = int(r0)
if e1 != 0 {
return n, errnoErr(e1)

@ -6,7 +6,11 @@
package unix
import "unsafe"
import (
"unsafe"
"golang.org/x/sys/internal/unsafeheader"
)
//sys closedir(dir uintptr) (err error)
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
@ -71,6 +75,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
cnt++
continue
}
reclen := int(entry.Reclen)
if reclen > len(buf) {
// Not enough room. Return for now.
@ -79,13 +84,15 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// restarting is O(n^2) in the length of the directory. Oh well.
break
}
// Copy entry into return buffer.
s := struct {
ptr unsafe.Pointer
siz int
cap int
}{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen}
copy(buf, *(*[]byte)(unsafe.Pointer(&s)))
var s []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
hdr.Data = unsafe.Pointer(&entry)
hdr.Cap = reclen
hdr.Len = reclen
copy(buf, s)
buf = buf[reclen:]
n += reclen
cnt++

@ -49,6 +49,11 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink
}
// Some external packages rely on SYS___SYSCTL being defined to implement their
// own sysctl wrappers. Provide it here, even though direct syscalls are no
// longer supported on darwin.
const SYS___SYSCTL = 202
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, err error) {
const siz = unsafe.Sizeof(mib[0])
@ -155,23 +160,6 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
//sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
//sysnb pipe() (r int, w int, err error)
func Pipe(p []int) (err error) {
@ -440,6 +428,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
//sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Getsid(pid int) (sid int, err error)
//sysnb Gettimeofday(tp *Timeval) (err error)
//sysnb Getuid() (uid int)
//sysnb Issetugid() (tainted bool)
//sys Kqueue() (fd int, err error)

@ -1,9 +0,0 @@
// Copyright 2019 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.
// +build darwin,386,!go1.12
package unix
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64

@ -20,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec)
tv.Usec = int32(usec)
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
@ -55,10 +44,6 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/386 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64

@ -1,9 +0,0 @@
// Copyright 2019 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.
// +build darwin,amd64,!go1.12
package unix
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64

@ -20,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = sec
tv.Usec = usec
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
@ -55,10 +44,6 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/amd64 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64

@ -1,11 +0,0 @@
// Copyright 2019 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.
// +build darwin,arm,!go1.12
package unix
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return 0, ENOSYS
}

@ -20,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec)
tv.Usec = int32(usec)
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
@ -55,10 +44,6 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/arm the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error)

@ -1,11 +0,0 @@
// Copyright 2019 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.
// +build darwin,arm64,!go1.12
package unix
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return 0, ENOSYS
}

@ -22,17 +22,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = sec
tv.Usec = usec
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
@ -57,10 +46,6 @@ func (cmsg *Cmsghdr) SetLen(length int) {
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of darwin/arm64 the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error)

@ -521,20 +521,10 @@ func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) {
return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
}
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
}
func PtraceGetRegs(pid int, regsout *Reg) (err error) {
return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
}
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}
func PtraceLwpEvents(pid int, enable int) (err error) {
return ptrace(PTRACE_LWPEVENTS, pid, 0, enable)
}

@ -54,3 +54,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
}
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

@ -54,3 +54,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
}
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

@ -54,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

@ -54,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

@ -0,0 +1,57 @@
// Copyright 2009 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.
// illumos system calls not present on Solaris.
// +build amd64,illumos
package unix
import "unsafe"
func bytes2iovec(bs [][]byte) []Iovec {
iovecs := make([]Iovec, len(bs))
for i, b := range bs {
iovecs[i].SetLen(len(b))
if len(b) > 0 {
// somehow Iovec.Base on illumos is (*int8), not (*byte)
iovecs[i].Base = (*int8)(unsafe.Pointer(&b[0]))
} else {
iovecs[i].Base = (*int8)(unsafe.Pointer(&_zero))
}
}
return iovecs
}
//sys readv(fd int, iovs []Iovec) (n int, err error)
func Readv(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = readv(fd, iovecs)
return n, err
}
//sys preadv(fd int, iovs []Iovec, off int64) (n int, err error)
func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = preadv(fd, iovecs, off)
return n, err
}
//sys writev(fd int, iovs []Iovec) (n int, err error)
func Writev(fd int, iovs [][]byte) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = writev(fd, iovecs)
return n, err
}
//sys pwritev(fd int, iovs []Iovec, off int64) (n int, err error)
func Pwritev(fd int, iovs [][]byte, off int64) (n int, err error) {
iovecs := bytes2iovec(iovs)
n, err = pwritev(fd, iovecs, off)
return n, err
}

@ -82,21 +82,18 @@ func IoctlRetInt(fd int, req uint) (int, error) {
return int(ret), nil
}
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
v := int32(value)
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
}
func IoctlSetRTCTime(fd int, value *RTCTime) error {
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value)
return err
}
func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value)
return err
}
func IoctlGetUint32(fd int, req uint) (uint32, error) {
var value uint32
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
@ -109,6 +106,12 @@ func IoctlGetRTCTime(fd int) (*RTCTime, error) {
return &value, err
}
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
var value RTCWkAlrm
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
return &value, err
}
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
func Link(oldpath string, newpath string) (err error) {
@ -839,6 +842,69 @@ func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil
}
// SockaddrL2TPIP implements the Sockaddr interface for IPPROTO_L2TP/AF_INET sockets.
type SockaddrL2TPIP struct {
Addr [4]byte
ConnId uint32
raw RawSockaddrL2TPIP
}
func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET
sa.raw.Conn_id = sa.ConnId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil
}
// SockaddrL2TPIP6 implements the Sockaddr interface for IPPROTO_L2TP/AF_INET6 sockets.
type SockaddrL2TPIP6 struct {
Addr [16]byte
ZoneId uint32
ConnId uint32
raw RawSockaddrL2TPIP6
}
func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET6
sa.raw.Conn_id = sa.ConnId
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil
}
// SockaddrIUCV implements the Sockaddr interface for AF_IUCV sockets.
type SockaddrIUCV struct {
UserID string
Name string
raw RawSockaddrIUCV
}
func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_IUCV
// These are EBCDIC encoded by the kernel, but we still need to pad them
// with blanks. Initializing with blanks allows the caller to feed in either
// a padded or an unpadded string.
for i := 0; i < 8; i++ {
sa.raw.Nodeid[i] = ' '
sa.raw.User_id[i] = ' '
sa.raw.Name[i] = ' '
}
if len(sa.UserID) > 8 || len(sa.Name) > 8 {
return nil, 0, EINVAL
}
for i, b := range []byte(sa.UserID[:]) {
sa.raw.User_id[i] = int8(b)
}
for i, b := range []byte(sa.Name[:]) {
sa.raw.Name[i] = int8(b)
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil
}
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_NETLINK:
@ -889,25 +955,58 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return sa, nil
case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
if err != nil {
return nil, err
}
switch proto {
case IPPROTO_L2TP:
pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa))
sa := new(SockaddrL2TPIP)
sa.ConnId = pp.Conn_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
default:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
}
return sa, nil
case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
if err != nil {
return nil, err
}
switch proto {
case IPPROTO_L2TP:
pp := (*RawSockaddrL2TPIP6)(unsafe.Pointer(rsa))
sa := new(SockaddrL2TPIP6)
sa.ConnId = pp.Conn_id
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
default:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
}
return sa, nil
case AF_VSOCK:
pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
@ -986,6 +1085,38 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
}
return sa, nil
case AF_IUCV:
pp := (*RawSockaddrIUCV)(unsafe.Pointer(rsa))
var user [8]byte
var name [8]byte
for i := 0; i < 8; i++ {
user[i] = byte(pp.User_id[i])
name[i] = byte(pp.Name[i])
}
sa := &SockaddrIUCV{
UserID: string(user[:]),
Name: string(name[:]),
}
return sa, nil
case AF_CAN:
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
sa := &SockaddrCAN{
Ifindex: int(pp.Ifindex),
}
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
for i := 0; i < 4; i++ {
rx[i] = pp.Addr[i]
}
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
for i := 0; i < 4; i++ {
tx[i] = pp.Addr[i+4]
}
return sa, nil
}
return nil, EAFNOSUPPORT
}
@ -1555,8 +1686,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Acct(path string) (err error)
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
//sys Adjtimex(buf *Timex) (state int, err error)
//sys Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Chdir(path string) (err error)
//sys Chroot(path string) (err error)
//sys ClockGetres(clockid int32, res *Timespec) (err error)
@ -1566,6 +1697,15 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys DeleteModule(name string, flags int) (err error)
//sys Dup(oldfd int) (fd int, err error)
func Dup2(oldfd, newfd int) error {
// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
return Dup3(oldfd, newfd, 0)
}
return dup2(oldfd, newfd)
}
//sys Dup3(oldfd int, newfd int, flags int) (err error)
//sysnb EpollCreate1(flag int) (fd int, err error)
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
@ -1654,6 +1794,30 @@ func Setgid(uid int) (err error) {
return EOPNOTSUPP
}
// SetfsgidRetGid sets fsgid for current thread and returns previous fsgid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability.
// If the call fails due to other reasons, current fsgid will be returned.
func SetfsgidRetGid(gid int) (int, error) {
return setfsgid(gid)
}
// SetfsuidRetUid sets fsuid for current thread and returns previous fsuid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability
// If the call fails due to other reasons, current fsuid will be returned.
func SetfsuidRetUid(uid int) (int, error) {
return setfsuid(uid)
}
func Setfsgid(gid int) error {
_, err := setfsgid(gid)
return err
}
func Setfsuid(uid int) error {
_, err := setfsuid(uid)
return err
}
func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
return signalfd(fd, sigmask, _C__NSIG/8, flags)
}
@ -1666,6 +1830,9 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
//sys Syncfs(fd int) (err error)
//sysnb Sysinfo(info *Sysinfo_t) (err error)
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
//sysnb TimerfdCreate(clockid int, flags int) (fd int, err error)
//sysnb TimerfdGettime(fd int, currValue *ItimerSpec) (err error)
//sysnb TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error)
//sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error)
//sysnb Times(tms *Tms) (ticks uintptr, err error)
//sysnb Umask(mask int) (oldmask int)
@ -1835,11 +2002,30 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
return int(n), nil
}
func isGroupMember(gid int) bool {
groups, err := Getgroups()
if err != nil {
return false
}
for _, g := range groups {
if g == gid {
return true
}
}
return false
}
//sys faccessat(dirfd int, path string, mode uint32) (err error)
//sys Faccessat2(dirfd int, path string, mode uint32, flags int) (err error)
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
return EINVAL
if flags == 0 {
return faccessat(dirfd, path, mode)
}
if err := Faccessat2(dirfd, path, mode, flags); err != ENOSYS && err != EPERM {
return err
}
// The Linux kernel faccessat system call does not take any flags.
@ -1848,8 +2034,8 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
// Because people naturally expect syscall.Faccessat to act
// like C faccessat, we do the same.
if flags == 0 {
return faccessat(dirfd, path, mode)
if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
return EINVAL
}
var st Stat_t
@ -1892,7 +2078,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
gid = Getgid()
}
if uint32(gid) == st.Gid {
if uint32(gid) == st.Gid || isGroupMember(gid) {
fmode = (st.Mode >> 3) & 7
} else {
fmode = st.Mode & 7
@ -1993,6 +2179,18 @@ func Klogset(typ int, arg int) (err error) {
return nil
}
// RemoteIovec is Iovec with the pointer replaced with an integer.
// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
// refers to a location in a different process' address space, which
// would confuse the Go garbage collector.
type RemoteIovec struct {
Base uintptr
Len int
}
//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
/*
* Unimplemented
*/
@ -2087,7 +2285,6 @@ func Klogset(typ int, arg int) (err error) {
// TimerGetoverrun
// TimerGettime
// TimerSettime
// Timerfd
// Tkill (obsolete)
// Tuxcall
// Umount2

@ -49,7 +49,7 @@ func Pipe2(p []int, flags int) (err error) {
// 64-bit file system and 32-bit uid calls
// (386 default is 32-bit file system and 16-bit uid).
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
@ -70,8 +70,8 @@ func Pipe2(p []int, flags int) (err error) {
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32
//sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32
//sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32

@ -6,7 +6,7 @@
package unix
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -55,8 +55,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

@ -7,7 +7,6 @@
package unix
import (
"syscall"
"unsafe"
)
@ -49,10 +48,6 @@ func Pipe2(p []int, flags int) (err error) {
return
}
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno)
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, errno := seek(fd, offset, whence)
if errno != 0 {
@ -80,7 +75,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
// 64-bit file system and 32-bit uid calls
// (16-bit uid calls are not always supported in newer kernels)
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
@ -98,8 +93,8 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32
//sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32
//sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32

@ -25,7 +25,7 @@ func EpollCreate(size int) (fd int, err error) {
//sysnb Getegid() (egid int)
//sysnb Geteuid() (euid int)
//sysnb Getgid() (gid int)
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sys Listen(s int, n int) (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
@ -42,12 +42,12 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Setreuid(ruid int, euid int) (err error)
//sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
@ -168,6 +168,24 @@ func Pipe2(p []int, flags int) (err error) {
return
}
// Getrlimit prefers the prlimit64 system call. See issue 38604.
func Getrlimit(resource int, rlim *Rlimit) error {
err := prlimit(0, resource, nil, rlim)
if err != ENOSYS {
return err
}
return getrlimit(resource, rlim)
}
// Setrlimit prefers the prlimit64 system call. See issue 38604.
func Setrlimit(resource int, rlim *Rlimit) error {
err := prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
return setrlimit(resource, rlim)
}
func (r *PtraceRegs) PC() uint64 { return r.Pc }
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
@ -192,9 +210,9 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
func Dup2(oldfd int, newfd int) (err error) {
return Dup3(oldfd, newfd, 0)
}
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error
func Pause() error {
_, err := ppoll(nil, 0, nil, nil)

@ -0,0 +1,13 @@
// Copyright 2009 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.
// +build arm,!gccgo,linux
package unix
import "syscall"
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno)

@ -7,7 +7,7 @@
package unix
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -36,8 +36,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -216,6 +216,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

@ -14,7 +14,7 @@ import (
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -31,8 +31,8 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

@ -7,7 +7,7 @@
package unix
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -34,8 +34,8 @@ package unix
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

@ -41,8 +41,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -191,10 +191,6 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
func Dup2(oldfd int, newfd int) (err error) {
return Dup3(oldfd, newfd, 0)
}
func Pause() error {
_, err := ppoll(nil, 0, nil, nil)
return err
@ -228,3 +224,7 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
}
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
}
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error

@ -10,7 +10,7 @@ import (
"unsafe"
)
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
@ -34,8 +34,8 @@ import (
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

@ -8,7 +8,7 @@ package unix
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
@ -30,8 +30,8 @@ package unix
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

@ -106,23 +106,6 @@ func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
//sysnb pipe() (fd1 int, fd2 int, err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {

@ -55,23 +55,6 @@ func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
func SysctlClockinfo(name string) (*Clockinfo, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
n := uintptr(SizeofClockinfo)
var ci Clockinfo
if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofClockinfo {
return nil, EIO
}
return &ci, nil
}
func SysctlUvmexp(name string) (*Uvmexp, error) {
mib, err := sysctlmib(name)
if err != nil {
@ -89,16 +72,20 @@ func SysctlUvmexp(name string) (*Uvmexp, error) {
return &u, nil
}
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
return Pipe2(p, 0)
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) error {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
return err
}
//sys Getdents(fd int, buf []byte) (n int, err error)

@ -0,0 +1,35 @@
// Copyright 2019 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.
package unix
func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: sec, Nsec: nsec}
}
func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: usec}
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
// of OpenBSD the syscall is called sysctl instead of __sysctl.
const SYS___SYSCTL = SYS_SYSCTL

@ -12,6 +12,8 @@ import (
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/internal/unsafeheader"
)
var (
@ -76,7 +78,7 @@ func SignalName(s syscall.Signal) string {
// The signal name should start with "SIG".
func SignalNum(s string) syscall.Signal {
signalNameMapOnce.Do(func() {
signalNameMap = make(map[string]syscall.Signal)
signalNameMap = make(map[string]syscall.Signal, len(signalList))
for _, signal := range signalList {
signalNameMap[signal.name] = signal.num
}
@ -113,15 +115,12 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
return nil, errno
}
// Slice memory layout
var sl = struct {
addr uintptr
len int
cap int
}{addr, length, length}
// Use unsafe to turn sl into a []byte.
b := *(*[]byte)(unsafe.Pointer(&sl))
// Use unsafe to convert addr into a []byte.
var b []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
hdr.Data = unsafe.Pointer(addr)
hdr.Cap = length
hdr.Len = length
// Register mapping in m and return it.
p := &b[cap(b)-1]

@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
@ -355,6 +361,22 @@ const (
CTL_KERN = 0x1
CTL_MAXNAME = 0x18
CTL_NET = 0x4
DIOCGATTR = 0xc144648e
DIOCGDELETE = 0x80106488
DIOCGFLUSH = 0x20006487
DIOCGFRONTSTUFF = 0x40086486
DIOCGFWHEADS = 0x40046483
DIOCGFWSECTORS = 0x40046482
DIOCGIDENT = 0x41006489
DIOCGMEDIASIZE = 0x40086481
DIOCGPHYSPATH = 0x4400648d
DIOCGPROVIDERNAME = 0x4400648a
DIOCGSECTORSIZE = 0x40046480
DIOCGSTRIPEOFFSET = 0x4008648c
DIOCGSTRIPESIZE = 0x4008648b
DIOCSKERNELDUMP = 0x804c6490
DIOCSKERNELDUMP_FREEBSD11 = 0x80046485
DIOCZONECMD = 0xc06c648f
DLT_A429 = 0xb8
DLT_A653_ICM = 0xb9
DLT_AIRONET_HEADER = 0x78
@ -379,11 +401,14 @@ const (
DLT_CHAOS = 0x5
DLT_CHDLC = 0x68
DLT_CISCO_IOS = 0x76
DLT_CLASS_NETBSD_RAWAF = 0x2240000
DLT_C_HDLC = 0x68
DLT_C_HDLC_WITH_DIR = 0xcd
DLT_DBUS = 0xe7
DLT_DECT = 0xdd
DLT_DISPLAYPORT_AUX = 0x113
DLT_DOCSIS = 0x8f
DLT_DOCSIS31_XRA31 = 0x111
DLT_DVB_CI = 0xeb
DLT_ECONET = 0x73
DLT_EN10MB = 0x1
@ -393,6 +418,7 @@ const (
DLT_ERF = 0xc5
DLT_ERF_ETH = 0xaf
DLT_ERF_POS = 0xb0
DLT_ETHERNET_MPACKET = 0x112
DLT_FC_2 = 0xe0
DLT_FC_2_WITH_FRAME_DELIMS = 0xe1
DLT_FDDI = 0xa
@ -406,7 +432,6 @@ const (
DLT_GPRS_LLC = 0xa9
DLT_GSMTAP_ABIS = 0xda
DLT_GSMTAP_UM = 0xd9
DLT_HHDLC = 0x79
DLT_IBM_SN = 0x92
DLT_IBM_SP = 0x91
DLT_IEEE802 = 0x6
@ -429,6 +454,7 @@ const (
DLT_IPV4 = 0xe4
DLT_IPV6 = 0xe5
DLT_IP_OVER_FC = 0x7a
DLT_ISO_14443 = 0x108
DLT_JUNIPER_ATM1 = 0x89
DLT_JUNIPER_ATM2 = 0x87
DLT_JUNIPER_ATM_CEMIC = 0xee
@ -461,8 +487,9 @@ const (
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
DLT_LINUX_SLL = 0x71
DLT_LOOP = 0x6c
DLT_LORATAP = 0x10e
DLT_LTALK = 0x72
DLT_MATCHING_MAX = 0x104
DLT_MATCHING_MAX = 0x113
DLT_MATCHING_MIN = 0x68
DLT_MFR = 0xb6
DLT_MOST = 0xd3
@ -478,14 +505,16 @@ const (
DLT_NFC_LLCP = 0xf5
DLT_NFLOG = 0xef
DLT_NG40 = 0xf4
DLT_NORDIC_BLE = 0x110
DLT_NULL = 0x0
DLT_OPENFLOW = 0x10b
DLT_PCI_EXP = 0x7d
DLT_PFLOG = 0x75
DLT_PFSYNC = 0x79
DLT_PKTAP = 0x102
DLT_PPI = 0xc0
DLT_PPP = 0x9
DLT_PPP_BSDOS = 0x10
DLT_PPP_BSDOS = 0xe
DLT_PPP_ETHER = 0x33
DLT_PPP_PPPD = 0xa6
DLT_PPP_SERIAL = 0x32
@ -496,19 +525,25 @@ const (
DLT_PRONET = 0x4
DLT_RAIF1 = 0xc6
DLT_RAW = 0xc
DLT_RDS = 0x109
DLT_REDBACK_SMARTEDGE = 0x20
DLT_RIO = 0x7c
DLT_RTAC_SERIAL = 0xfa
DLT_SCCP = 0x8e
DLT_SCTP = 0xf8
DLT_SDLC = 0x10c
DLT_SITA = 0xc4
DLT_SLIP = 0x8
DLT_SLIP_BSDOS = 0xf
DLT_SLIP_BSDOS = 0xd
DLT_STANAG_5066_D_PDU = 0xed
DLT_SUNATM = 0x7b
DLT_SYMANTEC_FIREWALL = 0x63
DLT_TI_LLN_SNIFFER = 0x10d
DLT_TZSP = 0x80
DLT_USB = 0xba
DLT_USBPCAP = 0xf9
DLT_USB_DARWIN = 0x10a
DLT_USB_FREEBSD = 0xba
DLT_USB_LINUX = 0xbd
DLT_USB_LINUX_MMAPPED = 0xdc
DLT_USER0 = 0x93
@ -527,10 +562,14 @@ const (
DLT_USER7 = 0x9a
DLT_USER8 = 0x9b
DLT_USER9 = 0x9c
DLT_VSOCK = 0x10f
DLT_WATTSTOPPER_DLM = 0x107
DLT_WIHART = 0xdf
DLT_WIRESHARK_UPPER_PDU = 0xfc
DLT_X2E_SERIAL = 0xd5
DLT_X2E_XORAYA = 0xd6
DLT_ZWAVE_R1_R2 = 0x105
DLT_ZWAVE_R3 = 0x106
DT_BLK = 0x6
DT_CHR = 0x2
DT_DIR = 0x4
@ -548,6 +587,7 @@ const (
ECHONL = 0x10
ECHOPRT = 0x20
EVFILT_AIO = -0x3
EVFILT_EMPTY = -0xd
EVFILT_FS = -0x9
EVFILT_LIO = -0xa
EVFILT_PROC = -0x5
@ -555,11 +595,12 @@ const (
EVFILT_READ = -0x1
EVFILT_SENDFILE = -0xc
EVFILT_SIGNAL = -0x6
EVFILT_SYSCOUNT = 0xc
EVFILT_SYSCOUNT = 0xd
EVFILT_TIMER = -0x7
EVFILT_USER = -0xb
EVFILT_VNODE = -0x4
EVFILT_WRITE = -0x2
EVNAMEMAP_NAME_SIZE = 0x40
EV_ADD = 0x1
EV_CLEAR = 0x20
EV_DELETE = 0x2
@ -576,6 +617,7 @@ const (
EV_RECEIPT = 0x40
EV_SYSFLAGS = 0xf000
EXTA = 0x4b00
EXTATTR_MAXNAMELEN = 0xff
EXTATTR_NAMESPACE_EMPTY = 0x0
EXTATTR_NAMESPACE_SYSTEM = 0x2
EXTATTR_NAMESPACE_USER = 0x1
@ -617,6 +659,7 @@ const (
IEXTEN = 0x400
IFAN_ARRIVAL = 0x0
IFAN_DEPARTURE = 0x1
IFCAP_WOL_MAGIC = 0x2000
IFF_ALLMULTI = 0x200
IFF_ALTPHYS = 0x4000
IFF_BROADCAST = 0x2
@ -633,6 +676,7 @@ const (
IFF_MONITOR = 0x40000
IFF_MULTICAST = 0x8000
IFF_NOARP = 0x80
IFF_NOGROUP = 0x800000
IFF_OACTIVE = 0x400
IFF_POINTOPOINT = 0x10
IFF_PPROMISC = 0x20000
@ -807,6 +851,7 @@ const (
IPV6_DSTOPTS = 0x32
IPV6_FLOWID = 0x43
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_LEN = 0x14
IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOWTYPE = 0x44
IPV6_FRAGTTL = 0x78
@ -827,13 +872,13 @@ const (
IPV6_MAX_GROUP_SRC_FILTER = 0x200
IPV6_MAX_MEMBERSHIPS = 0xfff
IPV6_MAX_SOCK_SRC_FILTER = 0x80
IPV6_MIN_MEMBERSHIPS = 0x1f
IPV6_MMTU = 0x500
IPV6_MSFILTER = 0x4a
IPV6_MULTICAST_HOPS = 0xa
IPV6_MULTICAST_IF = 0x9
IPV6_MULTICAST_LOOP = 0xb
IPV6_NEXTHOP = 0x30
IPV6_ORIGDSTADDR = 0x48
IPV6_PATHMTU = 0x2c
IPV6_PKTINFO = 0x2e
IPV6_PORTRANGE = 0xe
@ -845,6 +890,7 @@ const (
IPV6_RECVFLOWID = 0x46
IPV6_RECVHOPLIMIT = 0x25
IPV6_RECVHOPOPTS = 0x27
IPV6_RECVORIGDSTADDR = 0x48
IPV6_RECVPATHMTU = 0x2b
IPV6_RECVPKTINFO = 0x24
IPV6_RECVRSSBUCKETID = 0x47
@ -905,10 +951,8 @@ const (
IP_MAX_MEMBERSHIPS = 0xfff
IP_MAX_SOCK_MUTE_FILTER = 0x80
IP_MAX_SOCK_SRC_FILTER = 0x80
IP_MAX_SOURCE_FILTER = 0x400
IP_MF = 0x2000
IP_MINTTL = 0x42
IP_MIN_MEMBERSHIPS = 0x1f
IP_MSFILTER = 0x4a
IP_MSS = 0x240
IP_MULTICAST_IF = 0x9
@ -918,6 +962,7 @@ const (
IP_OFFMASK = 0x1fff
IP_ONESBCAST = 0x17
IP_OPTIONS = 0x1
IP_ORIGDSTADDR = 0x1b
IP_PORTRANGE = 0x13
IP_PORTRANGE_DEFAULT = 0x0
IP_PORTRANGE_HIGH = 0x1
@ -926,6 +971,7 @@ const (
IP_RECVFLOWID = 0x5d
IP_RECVIF = 0x14
IP_RECVOPTS = 0x5
IP_RECVORIGDSTADDR = 0x1b
IP_RECVRETOPTS = 0x6
IP_RECVRSSBUCKETID = 0x5e
IP_RECVTOS = 0x44
@ -975,6 +1021,7 @@ const (
MAP_EXCL = 0x4000
MAP_FILE = 0x0
MAP_FIXED = 0x10
MAP_GUARD = 0x2000
MAP_HASSEMAPHORE = 0x200
MAP_NOCORE = 0x20000
MAP_NOSYNC = 0x800
@ -986,6 +1033,15 @@ const (
MAP_RESERVED0100 = 0x100
MAP_SHARED = 0x1
MAP_STACK = 0x400
MCAST_BLOCK_SOURCE = 0x54
MCAST_EXCLUDE = 0x2
MCAST_INCLUDE = 0x1
MCAST_JOIN_GROUP = 0x50
MCAST_JOIN_SOURCE_GROUP = 0x52
MCAST_LEAVE_GROUP = 0x51
MCAST_LEAVE_SOURCE_GROUP = 0x53
MCAST_UNBLOCK_SOURCE = 0x55
MCAST_UNDEFINED = 0x0
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MNT_ACLS = 0x8000000
@ -1026,10 +1082,12 @@ const (
MNT_SUSPEND = 0x4
MNT_SYNCHRONOUS = 0x2
MNT_UNION = 0x20
MNT_UNTRUSTED = 0x800000000
MNT_UPDATE = 0x10000
MNT_UPDATEMASK = 0x2d8d0807e
MNT_UPDATEMASK = 0xad8d0807e
MNT_USER = 0x8000
MNT_VISFLAGMASK = 0x3fef0ffff
MNT_VERIFIED = 0x400000000
MNT_VISFLAGMASK = 0xffef0ffff
MNT_WAIT = 0x1
MSG_CMSG_CLOEXEC = 0x40000
MSG_COMPAT = 0x8000
@ -1058,6 +1116,7 @@ const (
NFDBITS = 0x20
NOFLSH = 0x80000000
NOKERNINFO = 0x2000000
NOTE_ABSTIME = 0x10
NOTE_ATTRIB = 0x8
NOTE_CHILD = 0x4
NOTE_CLOSE = 0x100
@ -1212,7 +1271,6 @@ const (
RTV_WEIGHT = 0x100
RT_ALL_FIBS = -0x1
RT_BLACKHOLE = 0x40
RT_CACHING_CONTEXT = 0x1
RT_DEFAULT_FIB = 0x0
RT_HAS_GW = 0x80
RT_HAS_HEADER = 0x10
@ -1222,15 +1280,17 @@ const (
RT_LLE_CACHE = 0x100
RT_MAY_LOOP = 0x8
RT_MAY_LOOP_BIT = 0x3
RT_NORTREF = 0x2
RT_REJECT = 0x20
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
RUSAGE_THREAD = 0x1
SCM_BINTIME = 0x4
SCM_CREDS = 0x3
SCM_MONOTONIC = 0x6
SCM_REALTIME = 0x5
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x2
SCM_TIME_INFO = 0x7
SHUT_RD = 0x0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
@ -1246,6 +1306,7 @@ const (
SIOCGETSGCNT = 0xc0147210
SIOCGETVIFCNT = 0xc014720f
SIOCGHIWAT = 0x40047301
SIOCGHWADDR = 0xc020693e
SIOCGI2C = 0xc020693d
SIOCGIFADDR = 0xc0206921
SIOCGIFBRDADDR = 0xc0206923
@ -1267,8 +1328,11 @@ const (
SIOCGIFPDSTADDR = 0xc0206948
SIOCGIFPHYS = 0xc0206935
SIOCGIFPSRCADDR = 0xc0206947
SIOCGIFRSSHASH = 0xc0186997
SIOCGIFRSSKEY = 0xc0946996
SIOCGIFSTATUS = 0xc331693b
SIOCGIFXMEDIA = 0xc028698b
SIOCGLANPCP = 0xc0206998
SIOCGLOWAT = 0x40047303
SIOCGPGRP = 0x40047309
SIOCGPRIVATE_0 = 0xc0206950
@ -1299,6 +1363,7 @@ const (
SIOCSIFPHYS = 0x80206936
SIOCSIFRVNET = 0xc020695b
SIOCSIFVNET = 0xc020695a
SIOCSLANPCP = 0x80206999
SIOCSLOWAT = 0x80047302
SIOCSPGRP = 0x80047308
SIOCSTUNFIB = 0x8020695f
@ -1317,6 +1382,7 @@ const (
SO_BINTIME = 0x2000
SO_BROADCAST = 0x20
SO_DEBUG = 0x1
SO_DOMAIN = 0x1019
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
SO_KEEPALIVE = 0x8
@ -1325,6 +1391,7 @@ const (
SO_LISTENINCQLEN = 0x1013
SO_LISTENQLEN = 0x1012
SO_LISTENQLIMIT = 0x1011
SO_MAX_PACING_RATE = 0x1018
SO_NOSIGPIPE = 0x800
SO_NO_DDP = 0x8000
SO_NO_OFFLOAD = 0x4000
@ -1337,11 +1404,19 @@ const (
SO_RCVTIMEO = 0x1006
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_REUSEPORT_LB = 0x10000
SO_SETFIB = 0x1014
SO_SNDBUF = 0x1001
SO_SNDLOWAT = 0x1003
SO_SNDTIMEO = 0x1005
SO_TIMESTAMP = 0x400
SO_TS_BINTIME = 0x1
SO_TS_CLOCK = 0x1017
SO_TS_CLOCK_MAX = 0x3
SO_TS_DEFAULT = 0x0
SO_TS_MONOTONIC = 0x3
SO_TS_REALTIME = 0x2
SO_TS_REALTIME_MICRO = 0x0
SO_TYPE = 0x1008
SO_USELOOPBACK = 0x40
SO_USER_COOKIE = 0x1015
@ -1385,10 +1460,45 @@ const (
TCOFLUSH = 0x2
TCOOFF = 0x1
TCOON = 0x2
TCP_BBR_ACK_COMP_ALG = 0x448
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
TCP_BBR_DRAIN_PG = 0x42e
TCP_BBR_EXTRA_GAIN = 0x449
TCP_BBR_IWINTSO = 0x42b
TCP_BBR_LOWGAIN_FD = 0x436
TCP_BBR_LOWGAIN_HALF = 0x435
TCP_BBR_LOWGAIN_THRESH = 0x434
TCP_BBR_MAX_RTO = 0x439
TCP_BBR_MIN_RTO = 0x438
TCP_BBR_ONE_RETRAN = 0x431
TCP_BBR_PACE_CROSS = 0x442
TCP_BBR_PACE_DEL_TAR = 0x43f
TCP_BBR_PACE_PER_SEC = 0x43e
TCP_BBR_PACE_SEG_MAX = 0x440
TCP_BBR_PACE_SEG_MIN = 0x441
TCP_BBR_PROBE_RTT_GAIN = 0x44d
TCP_BBR_PROBE_RTT_INT = 0x430
TCP_BBR_PROBE_RTT_LEN = 0x44e
TCP_BBR_RACK_RTT_USE = 0x44a
TCP_BBR_RECFORCE = 0x42c
TCP_BBR_REC_OVER_HPTS = 0x43a
TCP_BBR_RETRAN_WTSO = 0x44b
TCP_BBR_RWND_IS_APP = 0x42f
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
TCP_BBR_STARTUP_PG = 0x42d
TCP_BBR_UNLIMITED = 0x43b
TCP_BBR_USEDEL_RATE = 0x437
TCP_BBR_USE_LOWGAIN = 0x433
TCP_CA_NAME_MAX = 0x10
TCP_CCALGOOPT = 0x41
TCP_CONGESTION = 0x40
TCP_DATA_AFTER_CLOSE = 0x44c
TCP_DELACK = 0x48
TCP_FASTOPEN = 0x401
TCP_FASTOPEN_MAX_COOKIE_LEN = 0x10
TCP_FASTOPEN_MIN_COOKIE_LEN = 0x4
TCP_FASTOPEN_PSK_LEN = 0x10
TCP_FUNCTION_BLK = 0x2000
TCP_FUNCTION_NAME_LEN_MAX = 0x20
TCP_INFO = 0x20
@ -1396,6 +1506,12 @@ const (
TCP_KEEPIDLE = 0x100
TCP_KEEPINIT = 0x80
TCP_KEEPINTVL = 0x200
TCP_LOG = 0x22
TCP_LOGBUF = 0x23
TCP_LOGDUMP = 0x25
TCP_LOGDUMPID = 0x26
TCP_LOGID = 0x24
TCP_LOG_ID_LEN = 0x40
TCP_MAXBURST = 0x4
TCP_MAXHLEN = 0x3c
TCP_MAXOLEN = 0x28
@ -1411,8 +1527,30 @@ const (
TCP_NOPUSH = 0x4
TCP_PCAP_IN = 0x1000
TCP_PCAP_OUT = 0x800
TCP_RACK_EARLY_RECOV = 0x423
TCP_RACK_EARLY_SEG = 0x424
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
TCP_RACK_MIN_PACE = 0x445
TCP_RACK_MIN_PACE_SEG = 0x446
TCP_RACK_MIN_TO = 0x422
TCP_RACK_PACE_ALWAYS = 0x41f
TCP_RACK_PACE_MAX_SEG = 0x41e
TCP_RACK_PACE_REDUCE = 0x41d
TCP_RACK_PKT_DELAY = 0x428
TCP_RACK_PROP = 0x41b
TCP_RACK_PROP_RATE = 0x420
TCP_RACK_PRR_SENDALOT = 0x421
TCP_RACK_REORD_FADE = 0x426
TCP_RACK_REORD_THRESH = 0x425
TCP_RACK_SESS_CWV = 0x42a
TCP_RACK_TLP_INC_VAR = 0x429
TCP_RACK_TLP_REDUCE = 0x41c
TCP_RACK_TLP_THRESH = 0x427
TCP_RACK_TLP_USE = 0x447
TCP_VENDOR = 0x80000000
TCSAFLUSH = 0x2
TIMER_ABSTIME = 0x1
TIMER_RELTIME = 0x0
TIOCCBRK = 0x2000747a
TIOCCDTR = 0x20007478
TIOCCONS = 0x80047462
@ -1476,6 +1614,8 @@ const (
TIOCTIMESTAMP = 0x40087459
TIOCUCNTL = 0x80047466
TOSTOP = 0x400000
UTIME_NOW = -0x1
UTIME_OMIT = -0x2
VDISCARD = 0xf
VDSUSP = 0xb
VEOF = 0x0
@ -1487,6 +1627,8 @@ const (
VKILL = 0x5
VLNEXT = 0xe
VMIN = 0x10
VM_BCACHE_SIZE_MAX = 0x70e0000
VM_SWZONE_SIZE_MAX = 0x2280000
VQUIT = 0x9
VREPRINT = 0x6
VSTART = 0xc

@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
@ -355,6 +361,22 @@ const (
CTL_KERN = 0x1
CTL_MAXNAME = 0x18
CTL_NET = 0x4
DIOCGATTR = 0xc148648e
DIOCGDELETE = 0x80106488
DIOCGFLUSH = 0x20006487
DIOCGFRONTSTUFF = 0x40086486
DIOCGFWHEADS = 0x40046483
DIOCGFWSECTORS = 0x40046482
DIOCGIDENT = 0x41006489
DIOCGMEDIASIZE = 0x40086481
DIOCGPHYSPATH = 0x4400648d
DIOCGPROVIDERNAME = 0x4400648a
DIOCGSECTORSIZE = 0x40046480
DIOCGSTRIPEOFFSET = 0x4008648c
DIOCGSTRIPESIZE = 0x4008648b
DIOCSKERNELDUMP = 0x80506490
DIOCSKERNELDUMP_FREEBSD11 = 0x80046485
DIOCZONECMD = 0xc080648f
DLT_A429 = 0xb8
DLT_A653_ICM = 0xb9
DLT_AIRONET_HEADER = 0x78
@ -379,11 +401,14 @@ const (
DLT_CHAOS = 0x5
DLT_CHDLC = 0x68
DLT_CISCO_IOS = 0x76
DLT_CLASS_NETBSD_RAWAF = 0x2240000
DLT_C_HDLC = 0x68
DLT_C_HDLC_WITH_DIR = 0xcd
DLT_DBUS = 0xe7
DLT_DECT = 0xdd
DLT_DISPLAYPORT_AUX = 0x113
DLT_DOCSIS = 0x8f
DLT_DOCSIS31_XRA31 = 0x111
DLT_DVB_CI = 0xeb
DLT_ECONET = 0x73
DLT_EN10MB = 0x1
@ -393,6 +418,7 @@ const (
DLT_ERF = 0xc5
DLT_ERF_ETH = 0xaf
DLT_ERF_POS = 0xb0
DLT_ETHERNET_MPACKET = 0x112
DLT_FC_2 = 0xe0
DLT_FC_2_WITH_FRAME_DELIMS = 0xe1
DLT_FDDI = 0xa
@ -406,7 +432,6 @@ const (
DLT_GPRS_LLC = 0xa9
DLT_GSMTAP_ABIS = 0xda
DLT_GSMTAP_UM = 0xd9
DLT_HHDLC = 0x79
DLT_IBM_SN = 0x92
DLT_IBM_SP = 0x91
DLT_IEEE802 = 0x6
@ -429,6 +454,7 @@ const (
DLT_IPV4 = 0xe4
DLT_IPV6 = 0xe5
DLT_IP_OVER_FC = 0x7a
DLT_ISO_14443 = 0x108
DLT_JUNIPER_ATM1 = 0x89
DLT_JUNIPER_ATM2 = 0x87
DLT_JUNIPER_ATM_CEMIC = 0xee
@ -461,8 +487,9 @@ const (
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
DLT_LINUX_SLL = 0x71
DLT_LOOP = 0x6c
DLT_LORATAP = 0x10e
DLT_LTALK = 0x72
DLT_MATCHING_MAX = 0x104
DLT_MATCHING_MAX = 0x113
DLT_MATCHING_MIN = 0x68
DLT_MFR = 0xb6
DLT_MOST = 0xd3
@ -478,14 +505,16 @@ const (
DLT_NFC_LLCP = 0xf5
DLT_NFLOG = 0xef
DLT_NG40 = 0xf4
DLT_NORDIC_BLE = 0x110
DLT_NULL = 0x0
DLT_OPENFLOW = 0x10b
DLT_PCI_EXP = 0x7d
DLT_PFLOG = 0x75
DLT_PFSYNC = 0x79
DLT_PKTAP = 0x102
DLT_PPI = 0xc0
DLT_PPP = 0x9
DLT_PPP_BSDOS = 0x10
DLT_PPP_BSDOS = 0xe
DLT_PPP_ETHER = 0x33
DLT_PPP_PPPD = 0xa6
DLT_PPP_SERIAL = 0x32
@ -496,19 +525,25 @@ const (
DLT_PRONET = 0x4
DLT_RAIF1 = 0xc6
DLT_RAW = 0xc
DLT_RDS = 0x109
DLT_REDBACK_SMARTEDGE = 0x20
DLT_RIO = 0x7c
DLT_RTAC_SERIAL = 0xfa
DLT_SCCP = 0x8e
DLT_SCTP = 0xf8
DLT_SDLC = 0x10c
DLT_SITA = 0xc4
DLT_SLIP = 0x8
DLT_SLIP_BSDOS = 0xf
DLT_SLIP_BSDOS = 0xd
DLT_STANAG_5066_D_PDU = 0xed
DLT_SUNATM = 0x7b
DLT_SYMANTEC_FIREWALL = 0x63
DLT_TI_LLN_SNIFFER = 0x10d
DLT_TZSP = 0x80
DLT_USB = 0xba
DLT_USBPCAP = 0xf9
DLT_USB_DARWIN = 0x10a
DLT_USB_FREEBSD = 0xba
DLT_USB_LINUX = 0xbd
DLT_USB_LINUX_MMAPPED = 0xdc
DLT_USER0 = 0x93
@ -527,10 +562,14 @@ const (
DLT_USER7 = 0x9a
DLT_USER8 = 0x9b
DLT_USER9 = 0x9c
DLT_VSOCK = 0x10f
DLT_WATTSTOPPER_DLM = 0x107
DLT_WIHART = 0xdf
DLT_WIRESHARK_UPPER_PDU = 0xfc
DLT_X2E_SERIAL = 0xd5
DLT_X2E_XORAYA = 0xd6
DLT_ZWAVE_R1_R2 = 0x105
DLT_ZWAVE_R3 = 0x106
DT_BLK = 0x6
DT_CHR = 0x2
DT_DIR = 0x4
@ -548,6 +587,7 @@ const (
ECHONL = 0x10
ECHOPRT = 0x20
EVFILT_AIO = -0x3
EVFILT_EMPTY = -0xd
EVFILT_FS = -0x9
EVFILT_LIO = -0xa
EVFILT_PROC = -0x5
@ -555,11 +595,12 @@ const (
EVFILT_READ = -0x1
EVFILT_SENDFILE = -0xc
EVFILT_SIGNAL = -0x6
EVFILT_SYSCOUNT = 0xc
EVFILT_SYSCOUNT = 0xd
EVFILT_TIMER = -0x7
EVFILT_USER = -0xb
EVFILT_VNODE = -0x4
EVFILT_WRITE = -0x2
EVNAMEMAP_NAME_SIZE = 0x40
EV_ADD = 0x1
EV_CLEAR = 0x20
EV_DELETE = 0x2
@ -576,6 +617,7 @@ const (
EV_RECEIPT = 0x40
EV_SYSFLAGS = 0xf000
EXTA = 0x4b00
EXTATTR_MAXNAMELEN = 0xff
EXTATTR_NAMESPACE_EMPTY = 0x0
EXTATTR_NAMESPACE_SYSTEM = 0x2
EXTATTR_NAMESPACE_USER = 0x1
@ -617,6 +659,7 @@ const (
IEXTEN = 0x400
IFAN_ARRIVAL = 0x0
IFAN_DEPARTURE = 0x1
IFCAP_WOL_MAGIC = 0x2000
IFF_ALLMULTI = 0x200
IFF_ALTPHYS = 0x4000
IFF_BROADCAST = 0x2
@ -633,6 +676,7 @@ const (
IFF_MONITOR = 0x40000
IFF_MULTICAST = 0x8000
IFF_NOARP = 0x80
IFF_NOGROUP = 0x800000
IFF_OACTIVE = 0x400
IFF_POINTOPOINT = 0x10
IFF_PPROMISC = 0x20000
@ -807,6 +851,7 @@ const (
IPV6_DSTOPTS = 0x32
IPV6_FLOWID = 0x43
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_LEN = 0x14
IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOWTYPE = 0x44
IPV6_FRAGTTL = 0x78
@ -827,13 +872,13 @@ const (
IPV6_MAX_GROUP_SRC_FILTER = 0x200
IPV6_MAX_MEMBERSHIPS = 0xfff
IPV6_MAX_SOCK_SRC_FILTER = 0x80
IPV6_MIN_MEMBERSHIPS = 0x1f
IPV6_MMTU = 0x500
IPV6_MSFILTER = 0x4a
IPV6_MULTICAST_HOPS = 0xa
IPV6_MULTICAST_IF = 0x9
IPV6_MULTICAST_LOOP = 0xb
IPV6_NEXTHOP = 0x30
IPV6_ORIGDSTADDR = 0x48
IPV6_PATHMTU = 0x2c
IPV6_PKTINFO = 0x2e
IPV6_PORTRANGE = 0xe
@ -845,6 +890,7 @@ const (
IPV6_RECVFLOWID = 0x46
IPV6_RECVHOPLIMIT = 0x25
IPV6_RECVHOPOPTS = 0x27
IPV6_RECVORIGDSTADDR = 0x48
IPV6_RECVPATHMTU = 0x2b
IPV6_RECVPKTINFO = 0x24
IPV6_RECVRSSBUCKETID = 0x47
@ -905,10 +951,8 @@ const (
IP_MAX_MEMBERSHIPS = 0xfff
IP_MAX_SOCK_MUTE_FILTER = 0x80
IP_MAX_SOCK_SRC_FILTER = 0x80
IP_MAX_SOURCE_FILTER = 0x400
IP_MF = 0x2000
IP_MINTTL = 0x42
IP_MIN_MEMBERSHIPS = 0x1f
IP_MSFILTER = 0x4a
IP_MSS = 0x240
IP_MULTICAST_IF = 0x9
@ -918,6 +962,7 @@ const (
IP_OFFMASK = 0x1fff
IP_ONESBCAST = 0x17
IP_OPTIONS = 0x1
IP_ORIGDSTADDR = 0x1b
IP_PORTRANGE = 0x13
IP_PORTRANGE_DEFAULT = 0x0
IP_PORTRANGE_HIGH = 0x1
@ -926,6 +971,7 @@ const (
IP_RECVFLOWID = 0x5d
IP_RECVIF = 0x14
IP_RECVOPTS = 0x5
IP_RECVORIGDSTADDR = 0x1b
IP_RECVRETOPTS = 0x6
IP_RECVRSSBUCKETID = 0x5e
IP_RECVTOS = 0x44
@ -976,6 +1022,7 @@ const (
MAP_EXCL = 0x4000
MAP_FILE = 0x0
MAP_FIXED = 0x10
MAP_GUARD = 0x2000
MAP_HASSEMAPHORE = 0x200
MAP_NOCORE = 0x20000
MAP_NOSYNC = 0x800
@ -987,6 +1034,15 @@ const (
MAP_RESERVED0100 = 0x100
MAP_SHARED = 0x1
MAP_STACK = 0x400
MCAST_BLOCK_SOURCE = 0x54
MCAST_EXCLUDE = 0x2
MCAST_INCLUDE = 0x1
MCAST_JOIN_GROUP = 0x50
MCAST_JOIN_SOURCE_GROUP = 0x52
MCAST_LEAVE_GROUP = 0x51
MCAST_LEAVE_SOURCE_GROUP = 0x53
MCAST_UNBLOCK_SOURCE = 0x55
MCAST_UNDEFINED = 0x0
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MNT_ACLS = 0x8000000
@ -1027,10 +1083,12 @@ const (
MNT_SUSPEND = 0x4
MNT_SYNCHRONOUS = 0x2
MNT_UNION = 0x20
MNT_UNTRUSTED = 0x800000000
MNT_UPDATE = 0x10000
MNT_UPDATEMASK = 0x2d8d0807e
MNT_UPDATEMASK = 0xad8d0807e
MNT_USER = 0x8000
MNT_VISFLAGMASK = 0x3fef0ffff
MNT_VERIFIED = 0x400000000
MNT_VISFLAGMASK = 0xffef0ffff
MNT_WAIT = 0x1
MSG_CMSG_CLOEXEC = 0x40000
MSG_COMPAT = 0x8000
@ -1059,6 +1117,7 @@ const (
NFDBITS = 0x40
NOFLSH = 0x80000000
NOKERNINFO = 0x2000000
NOTE_ABSTIME = 0x10
NOTE_ATTRIB = 0x8
NOTE_CHILD = 0x4
NOTE_CLOSE = 0x100
@ -1213,7 +1272,6 @@ const (
RTV_WEIGHT = 0x100
RT_ALL_FIBS = -0x1
RT_BLACKHOLE = 0x40
RT_CACHING_CONTEXT = 0x1
RT_DEFAULT_FIB = 0x0
RT_HAS_GW = 0x80
RT_HAS_HEADER = 0x10
@ -1223,15 +1281,17 @@ const (
RT_LLE_CACHE = 0x100
RT_MAY_LOOP = 0x8
RT_MAY_LOOP_BIT = 0x3
RT_NORTREF = 0x2
RT_REJECT = 0x20
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
RUSAGE_THREAD = 0x1
SCM_BINTIME = 0x4
SCM_CREDS = 0x3
SCM_MONOTONIC = 0x6
SCM_REALTIME = 0x5
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x2
SCM_TIME_INFO = 0x7
SHUT_RD = 0x0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
@ -1247,6 +1307,7 @@ const (
SIOCGETSGCNT = 0xc0207210
SIOCGETVIFCNT = 0xc028720f
SIOCGHIWAT = 0x40047301
SIOCGHWADDR = 0xc020693e
SIOCGI2C = 0xc020693d
SIOCGIFADDR = 0xc0206921
SIOCGIFBRDADDR = 0xc0206923
@ -1268,8 +1329,11 @@ const (
SIOCGIFPDSTADDR = 0xc0206948
SIOCGIFPHYS = 0xc0206935
SIOCGIFPSRCADDR = 0xc0206947
SIOCGIFRSSHASH = 0xc0186997
SIOCGIFRSSKEY = 0xc0946996
SIOCGIFSTATUS = 0xc331693b
SIOCGIFXMEDIA = 0xc030698b
SIOCGLANPCP = 0xc0206998
SIOCGLOWAT = 0x40047303
SIOCGPGRP = 0x40047309
SIOCGPRIVATE_0 = 0xc0206950
@ -1300,6 +1364,7 @@ const (
SIOCSIFPHYS = 0x80206936
SIOCSIFRVNET = 0xc020695b
SIOCSIFVNET = 0xc020695a
SIOCSLANPCP = 0x80206999
SIOCSLOWAT = 0x80047302
SIOCSPGRP = 0x80047308
SIOCSTUNFIB = 0x8020695f
@ -1318,6 +1383,7 @@ const (
SO_BINTIME = 0x2000
SO_BROADCAST = 0x20
SO_DEBUG = 0x1
SO_DOMAIN = 0x1019
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
SO_KEEPALIVE = 0x8
@ -1326,6 +1392,7 @@ const (
SO_LISTENINCQLEN = 0x1013
SO_LISTENQLEN = 0x1012
SO_LISTENQLIMIT = 0x1011
SO_MAX_PACING_RATE = 0x1018
SO_NOSIGPIPE = 0x800
SO_NO_DDP = 0x8000
SO_NO_OFFLOAD = 0x4000
@ -1338,11 +1405,19 @@ const (
SO_RCVTIMEO = 0x1006
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_REUSEPORT_LB = 0x10000
SO_SETFIB = 0x1014
SO_SNDBUF = 0x1001
SO_SNDLOWAT = 0x1003
SO_SNDTIMEO = 0x1005
SO_TIMESTAMP = 0x400
SO_TS_BINTIME = 0x1
SO_TS_CLOCK = 0x1017
SO_TS_CLOCK_MAX = 0x3
SO_TS_DEFAULT = 0x0
SO_TS_MONOTONIC = 0x3
SO_TS_REALTIME = 0x2
SO_TS_REALTIME_MICRO = 0x0
SO_TYPE = 0x1008
SO_USELOOPBACK = 0x40
SO_USER_COOKIE = 0x1015
@ -1386,10 +1461,45 @@ const (
TCOFLUSH = 0x2
TCOOFF = 0x1
TCOON = 0x2
TCP_BBR_ACK_COMP_ALG = 0x448
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
TCP_BBR_DRAIN_PG = 0x42e
TCP_BBR_EXTRA_GAIN = 0x449
TCP_BBR_IWINTSO = 0x42b
TCP_BBR_LOWGAIN_FD = 0x436
TCP_BBR_LOWGAIN_HALF = 0x435
TCP_BBR_LOWGAIN_THRESH = 0x434
TCP_BBR_MAX_RTO = 0x439
TCP_BBR_MIN_RTO = 0x438
TCP_BBR_ONE_RETRAN = 0x431
TCP_BBR_PACE_CROSS = 0x442
TCP_BBR_PACE_DEL_TAR = 0x43f
TCP_BBR_PACE_PER_SEC = 0x43e
TCP_BBR_PACE_SEG_MAX = 0x440
TCP_BBR_PACE_SEG_MIN = 0x441
TCP_BBR_PROBE_RTT_GAIN = 0x44d
TCP_BBR_PROBE_RTT_INT = 0x430
TCP_BBR_PROBE_RTT_LEN = 0x44e
TCP_BBR_RACK_RTT_USE = 0x44a
TCP_BBR_RECFORCE = 0x42c
TCP_BBR_REC_OVER_HPTS = 0x43a
TCP_BBR_RETRAN_WTSO = 0x44b
TCP_BBR_RWND_IS_APP = 0x42f
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
TCP_BBR_STARTUP_PG = 0x42d
TCP_BBR_UNLIMITED = 0x43b
TCP_BBR_USEDEL_RATE = 0x437
TCP_BBR_USE_LOWGAIN = 0x433
TCP_CA_NAME_MAX = 0x10
TCP_CCALGOOPT = 0x41
TCP_CONGESTION = 0x40
TCP_DATA_AFTER_CLOSE = 0x44c
TCP_DELACK = 0x48
TCP_FASTOPEN = 0x401
TCP_FASTOPEN_MAX_COOKIE_LEN = 0x10
TCP_FASTOPEN_MIN_COOKIE_LEN = 0x4
TCP_FASTOPEN_PSK_LEN = 0x10
TCP_FUNCTION_BLK = 0x2000
TCP_FUNCTION_NAME_LEN_MAX = 0x20
TCP_INFO = 0x20
@ -1397,6 +1507,12 @@ const (
TCP_KEEPIDLE = 0x100
TCP_KEEPINIT = 0x80
TCP_KEEPINTVL = 0x200
TCP_LOG = 0x22
TCP_LOGBUF = 0x23
TCP_LOGDUMP = 0x25
TCP_LOGDUMPID = 0x26
TCP_LOGID = 0x24
TCP_LOG_ID_LEN = 0x40
TCP_MAXBURST = 0x4
TCP_MAXHLEN = 0x3c
TCP_MAXOLEN = 0x28
@ -1412,8 +1528,30 @@ const (
TCP_NOPUSH = 0x4
TCP_PCAP_IN = 0x1000
TCP_PCAP_OUT = 0x800
TCP_RACK_EARLY_RECOV = 0x423
TCP_RACK_EARLY_SEG = 0x424
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
TCP_RACK_MIN_PACE = 0x445
TCP_RACK_MIN_PACE_SEG = 0x446
TCP_RACK_MIN_TO = 0x422
TCP_RACK_PACE_ALWAYS = 0x41f
TCP_RACK_PACE_MAX_SEG = 0x41e
TCP_RACK_PACE_REDUCE = 0x41d
TCP_RACK_PKT_DELAY = 0x428
TCP_RACK_PROP = 0x41b
TCP_RACK_PROP_RATE = 0x420
TCP_RACK_PRR_SENDALOT = 0x421
TCP_RACK_REORD_FADE = 0x426
TCP_RACK_REORD_THRESH = 0x425
TCP_RACK_SESS_CWV = 0x42a
TCP_RACK_TLP_INC_VAR = 0x429
TCP_RACK_TLP_REDUCE = 0x41c
TCP_RACK_TLP_THRESH = 0x427
TCP_RACK_TLP_USE = 0x447
TCP_VENDOR = 0x80000000
TCSAFLUSH = 0x2
TIMER_ABSTIME = 0x1
TIMER_RELTIME = 0x0
TIOCCBRK = 0x2000747a
TIOCCDTR = 0x20007478
TIOCCONS = 0x80047462
@ -1477,6 +1615,8 @@ const (
TIOCTIMESTAMP = 0x40107459
TIOCUCNTL = 0x80047466
TOSTOP = 0x400000
UTIME_NOW = -0x1
UTIME_OMIT = -0x2
VDISCARD = 0xf
VDSUSP = 0xb
VEOF = 0x0

@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
@ -355,6 +361,22 @@ const (
CTL_KERN = 0x1
CTL_MAXNAME = 0x18
CTL_NET = 0x4
DIOCGATTR = 0xc144648e
DIOCGDELETE = 0x80106488
DIOCGFLUSH = 0x20006487
DIOCGFRONTSTUFF = 0x40086486
DIOCGFWHEADS = 0x40046483
DIOCGFWSECTORS = 0x40046482
DIOCGIDENT = 0x41006489
DIOCGMEDIASIZE = 0x40086481
DIOCGPHYSPATH = 0x4400648d
DIOCGPROVIDERNAME = 0x4400648a
DIOCGSECTORSIZE = 0x40046480
DIOCGSTRIPEOFFSET = 0x4008648c
DIOCGSTRIPESIZE = 0x4008648b
DIOCSKERNELDUMP = 0x804c6490
DIOCSKERNELDUMP_FREEBSD11 = 0x80046485
DIOCZONECMD = 0xc06c648f
DLT_A429 = 0xb8
DLT_A653_ICM = 0xb9
DLT_AIRONET_HEADER = 0x78

@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
@ -355,6 +361,22 @@ const (
CTL_KERN = 0x1
CTL_MAXNAME = 0x18
CTL_NET = 0x4
DIOCGATTR = 0xc148648e
DIOCGDELETE = 0x80106488
DIOCGFLUSH = 0x20006487
DIOCGFRONTSTUFF = 0x40086486
DIOCGFWHEADS = 0x40046483
DIOCGFWSECTORS = 0x40046482
DIOCGIDENT = 0x41006489
DIOCGMEDIASIZE = 0x40086481
DIOCGPHYSPATH = 0x4400648d
DIOCGPROVIDERNAME = 0x4400648a
DIOCGSECTORSIZE = 0x40046480
DIOCGSTRIPEOFFSET = 0x4008648c
DIOCGSTRIPESIZE = 0x4008648b
DIOCSKERNELDUMP = 0x80506490
DIOCSKERNELDUMP_FREEBSD11 = 0x80046485
DIOCZONECMD = 0xc080648f
DLT_A429 = 0xb8
DLT_A653_ICM = 0xb9
DLT_AIRONET_HEADER = 0x78
@ -379,11 +401,14 @@ const (
DLT_CHAOS = 0x5
DLT_CHDLC = 0x68
DLT_CISCO_IOS = 0x76
DLT_CLASS_NETBSD_RAWAF = 0x2240000
DLT_C_HDLC = 0x68
DLT_C_HDLC_WITH_DIR = 0xcd
DLT_DBUS = 0xe7
DLT_DECT = 0xdd
DLT_DISPLAYPORT_AUX = 0x113
DLT_DOCSIS = 0x8f
DLT_DOCSIS31_XRA31 = 0x111
DLT_DVB_CI = 0xeb
DLT_ECONET = 0x73
DLT_EN10MB = 0x1
@ -393,6 +418,7 @@ const (
DLT_ERF = 0xc5
DLT_ERF_ETH = 0xaf
DLT_ERF_POS = 0xb0
DLT_ETHERNET_MPACKET = 0x112
DLT_FC_2 = 0xe0
DLT_FC_2_WITH_FRAME_DELIMS = 0xe1
DLT_FDDI = 0xa
@ -406,7 +432,6 @@ const (
DLT_GPRS_LLC = 0xa9
DLT_GSMTAP_ABIS = 0xda
DLT_GSMTAP_UM = 0xd9
DLT_HHDLC = 0x79
DLT_IBM_SN = 0x92
DLT_IBM_SP = 0x91
DLT_IEEE802 = 0x6
@ -429,6 +454,7 @@ const (
DLT_IPV4 = 0xe4
DLT_IPV6 = 0xe5
DLT_IP_OVER_FC = 0x7a
DLT_ISO_14443 = 0x108
DLT_JUNIPER_ATM1 = 0x89
DLT_JUNIPER_ATM2 = 0x87
DLT_JUNIPER_ATM_CEMIC = 0xee
@ -461,8 +487,9 @@ const (
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
DLT_LINUX_SLL = 0x71
DLT_LOOP = 0x6c
DLT_LORATAP = 0x10e
DLT_LTALK = 0x72
DLT_MATCHING_MAX = 0x104
DLT_MATCHING_MAX = 0x113
DLT_MATCHING_MIN = 0x68
DLT_MFR = 0xb6
DLT_MOST = 0xd3
@ -478,14 +505,16 @@ const (
DLT_NFC_LLCP = 0xf5
DLT_NFLOG = 0xef
DLT_NG40 = 0xf4
DLT_NORDIC_BLE = 0x110
DLT_NULL = 0x0
DLT_OPENFLOW = 0x10b
DLT_PCI_EXP = 0x7d
DLT_PFLOG = 0x75
DLT_PFSYNC = 0x79
DLT_PKTAP = 0x102
DLT_PPI = 0xc0
DLT_PPP = 0x9
DLT_PPP_BSDOS = 0x10
DLT_PPP_BSDOS = 0xe
DLT_PPP_ETHER = 0x33
DLT_PPP_PPPD = 0xa6
DLT_PPP_SERIAL = 0x32
@ -496,19 +525,25 @@ const (
DLT_PRONET = 0x4
DLT_RAIF1 = 0xc6
DLT_RAW = 0xc
DLT_RDS = 0x109
DLT_REDBACK_SMARTEDGE = 0x20
DLT_RIO = 0x7c
DLT_RTAC_SERIAL = 0xfa
DLT_SCCP = 0x8e
DLT_SCTP = 0xf8
DLT_SDLC = 0x10c
DLT_SITA = 0xc4
DLT_SLIP = 0x8
DLT_SLIP_BSDOS = 0xf
DLT_SLIP_BSDOS = 0xd
DLT_STANAG_5066_D_PDU = 0xed
DLT_SUNATM = 0x7b
DLT_SYMANTEC_FIREWALL = 0x63
DLT_TI_LLN_SNIFFER = 0x10d
DLT_TZSP = 0x80
DLT_USB = 0xba
DLT_USBPCAP = 0xf9
DLT_USB_DARWIN = 0x10a
DLT_USB_FREEBSD = 0xba
DLT_USB_LINUX = 0xbd
DLT_USB_LINUX_MMAPPED = 0xdc
DLT_USER0 = 0x93
@ -527,10 +562,14 @@ const (
DLT_USER7 = 0x9a
DLT_USER8 = 0x9b
DLT_USER9 = 0x9c
DLT_VSOCK = 0x10f
DLT_WATTSTOPPER_DLM = 0x107
DLT_WIHART = 0xdf
DLT_WIRESHARK_UPPER_PDU = 0xfc
DLT_X2E_SERIAL = 0xd5
DLT_X2E_XORAYA = 0xd6
DLT_ZWAVE_R1_R2 = 0x105
DLT_ZWAVE_R3 = 0x106
DT_BLK = 0x6
DT_CHR = 0x2
DT_DIR = 0x4
@ -548,6 +587,7 @@ const (
ECHONL = 0x10
ECHOPRT = 0x20
EVFILT_AIO = -0x3
EVFILT_EMPTY = -0xd
EVFILT_FS = -0x9
EVFILT_LIO = -0xa
EVFILT_PROC = -0x5
@ -555,11 +595,12 @@ const (
EVFILT_READ = -0x1
EVFILT_SENDFILE = -0xc
EVFILT_SIGNAL = -0x6
EVFILT_SYSCOUNT = 0xc
EVFILT_SYSCOUNT = 0xd
EVFILT_TIMER = -0x7
EVFILT_USER = -0xb
EVFILT_VNODE = -0x4
EVFILT_WRITE = -0x2
EVNAMEMAP_NAME_SIZE = 0x40
EV_ADD = 0x1
EV_CLEAR = 0x20
EV_DELETE = 0x2
@ -576,6 +617,7 @@ const (
EV_RECEIPT = 0x40
EV_SYSFLAGS = 0xf000
EXTA = 0x4b00
EXTATTR_MAXNAMELEN = 0xff
EXTATTR_NAMESPACE_EMPTY = 0x0
EXTATTR_NAMESPACE_SYSTEM = 0x2
EXTATTR_NAMESPACE_USER = 0x1
@ -617,6 +659,7 @@ const (
IEXTEN = 0x400
IFAN_ARRIVAL = 0x0
IFAN_DEPARTURE = 0x1
IFCAP_WOL_MAGIC = 0x2000
IFF_ALLMULTI = 0x200
IFF_ALTPHYS = 0x4000
IFF_BROADCAST = 0x2
@ -633,6 +676,7 @@ const (
IFF_MONITOR = 0x40000
IFF_MULTICAST = 0x8000
IFF_NOARP = 0x80
IFF_NOGROUP = 0x800000
IFF_OACTIVE = 0x400
IFF_POINTOPOINT = 0x10
IFF_PPROMISC = 0x20000
@ -807,6 +851,7 @@ const (
IPV6_DSTOPTS = 0x32
IPV6_FLOWID = 0x43
IPV6_FLOWINFO_MASK = 0xffffff0f
IPV6_FLOWLABEL_LEN = 0x14
IPV6_FLOWLABEL_MASK = 0xffff0f00
IPV6_FLOWTYPE = 0x44
IPV6_FRAGTTL = 0x78
@ -827,13 +872,13 @@ const (
IPV6_MAX_GROUP_SRC_FILTER = 0x200
IPV6_MAX_MEMBERSHIPS = 0xfff
IPV6_MAX_SOCK_SRC_FILTER = 0x80
IPV6_MIN_MEMBERSHIPS = 0x1f
IPV6_MMTU = 0x500
IPV6_MSFILTER = 0x4a
IPV6_MULTICAST_HOPS = 0xa
IPV6_MULTICAST_IF = 0x9
IPV6_MULTICAST_LOOP = 0xb
IPV6_NEXTHOP = 0x30
IPV6_ORIGDSTADDR = 0x48
IPV6_PATHMTU = 0x2c
IPV6_PKTINFO = 0x2e
IPV6_PORTRANGE = 0xe
@ -845,6 +890,7 @@ const (
IPV6_RECVFLOWID = 0x46
IPV6_RECVHOPLIMIT = 0x25
IPV6_RECVHOPOPTS = 0x27
IPV6_RECVORIGDSTADDR = 0x48
IPV6_RECVPATHMTU = 0x2b
IPV6_RECVPKTINFO = 0x24
IPV6_RECVRSSBUCKETID = 0x47
@ -905,10 +951,8 @@ const (
IP_MAX_MEMBERSHIPS = 0xfff
IP_MAX_SOCK_MUTE_FILTER = 0x80
IP_MAX_SOCK_SRC_FILTER = 0x80
IP_MAX_SOURCE_FILTER = 0x400
IP_MF = 0x2000
IP_MINTTL = 0x42
IP_MIN_MEMBERSHIPS = 0x1f
IP_MSFILTER = 0x4a
IP_MSS = 0x240
IP_MULTICAST_IF = 0x9
@ -918,6 +962,7 @@ const (
IP_OFFMASK = 0x1fff
IP_ONESBCAST = 0x17
IP_OPTIONS = 0x1
IP_ORIGDSTADDR = 0x1b
IP_PORTRANGE = 0x13
IP_PORTRANGE_DEFAULT = 0x0
IP_PORTRANGE_HIGH = 0x1
@ -926,6 +971,7 @@ const (
IP_RECVFLOWID = 0x5d
IP_RECVIF = 0x14
IP_RECVOPTS = 0x5
IP_RECVORIGDSTADDR = 0x1b
IP_RECVRETOPTS = 0x6
IP_RECVRSSBUCKETID = 0x5e
IP_RECVTOS = 0x44
@ -976,6 +1022,7 @@ const (
MAP_EXCL = 0x4000
MAP_FILE = 0x0
MAP_FIXED = 0x10
MAP_GUARD = 0x2000
MAP_HASSEMAPHORE = 0x200
MAP_NOCORE = 0x20000
MAP_NOSYNC = 0x800
@ -987,6 +1034,15 @@ const (
MAP_RESERVED0100 = 0x100
MAP_SHARED = 0x1
MAP_STACK = 0x400
MCAST_BLOCK_SOURCE = 0x54
MCAST_EXCLUDE = 0x2
MCAST_INCLUDE = 0x1
MCAST_JOIN_GROUP = 0x50
MCAST_JOIN_SOURCE_GROUP = 0x52
MCAST_LEAVE_GROUP = 0x51
MCAST_LEAVE_SOURCE_GROUP = 0x53
MCAST_UNBLOCK_SOURCE = 0x55
MCAST_UNDEFINED = 0x0
MCL_CURRENT = 0x1
MCL_FUTURE = 0x2
MNT_ACLS = 0x8000000
@ -1027,10 +1083,12 @@ const (
MNT_SUSPEND = 0x4
MNT_SYNCHRONOUS = 0x2
MNT_UNION = 0x20
MNT_UNTRUSTED = 0x800000000
MNT_UPDATE = 0x10000
MNT_UPDATEMASK = 0x2d8d0807e
MNT_UPDATEMASK = 0xad8d0807e
MNT_USER = 0x8000
MNT_VISFLAGMASK = 0x3fef0ffff
MNT_VERIFIED = 0x400000000
MNT_VISFLAGMASK = 0xffef0ffff
MNT_WAIT = 0x1
MSG_CMSG_CLOEXEC = 0x40000
MSG_COMPAT = 0x8000
@ -1059,6 +1117,7 @@ const (
NFDBITS = 0x40
NOFLSH = 0x80000000
NOKERNINFO = 0x2000000
NOTE_ABSTIME = 0x10
NOTE_ATTRIB = 0x8
NOTE_CHILD = 0x4
NOTE_CLOSE = 0x100
@ -1213,7 +1272,6 @@ const (
RTV_WEIGHT = 0x100
RT_ALL_FIBS = -0x1
RT_BLACKHOLE = 0x40
RT_CACHING_CONTEXT = 0x1
RT_DEFAULT_FIB = 0x0
RT_HAS_GW = 0x80
RT_HAS_HEADER = 0x10
@ -1223,15 +1281,17 @@ const (
RT_LLE_CACHE = 0x100
RT_MAY_LOOP = 0x8
RT_MAY_LOOP_BIT = 0x3
RT_NORTREF = 0x2
RT_REJECT = 0x20
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
RUSAGE_THREAD = 0x1
SCM_BINTIME = 0x4
SCM_CREDS = 0x3
SCM_MONOTONIC = 0x6
SCM_REALTIME = 0x5
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x2
SCM_TIME_INFO = 0x7
SHUT_RD = 0x0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
@ -1247,6 +1307,7 @@ const (
SIOCGETSGCNT = 0xc0207210
SIOCGETVIFCNT = 0xc028720f
SIOCGHIWAT = 0x40047301
SIOCGHWADDR = 0xc020693e
SIOCGI2C = 0xc020693d
SIOCGIFADDR = 0xc0206921
SIOCGIFBRDADDR = 0xc0206923
@ -1268,8 +1329,11 @@ const (
SIOCGIFPDSTADDR = 0xc0206948
SIOCGIFPHYS = 0xc0206935
SIOCGIFPSRCADDR = 0xc0206947
SIOCGIFRSSHASH = 0xc0186997
SIOCGIFRSSKEY = 0xc0946996
SIOCGIFSTATUS = 0xc331693b
SIOCGIFXMEDIA = 0xc030698b
SIOCGLANPCP = 0xc0206998
SIOCGLOWAT = 0x40047303
SIOCGPGRP = 0x40047309
SIOCGPRIVATE_0 = 0xc0206950
@ -1300,6 +1364,7 @@ const (
SIOCSIFPHYS = 0x80206936
SIOCSIFRVNET = 0xc020695b
SIOCSIFVNET = 0xc020695a
SIOCSLANPCP = 0x80206999
SIOCSLOWAT = 0x80047302
SIOCSPGRP = 0x80047308
SIOCSTUNFIB = 0x8020695f
@ -1318,6 +1383,7 @@ const (
SO_BINTIME = 0x2000
SO_BROADCAST = 0x20
SO_DEBUG = 0x1
SO_DOMAIN = 0x1019
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
SO_KEEPALIVE = 0x8
@ -1326,6 +1392,7 @@ const (
SO_LISTENINCQLEN = 0x1013
SO_LISTENQLEN = 0x1012
SO_LISTENQLIMIT = 0x1011
SO_MAX_PACING_RATE = 0x1018
SO_NOSIGPIPE = 0x800
SO_NO_DDP = 0x8000
SO_NO_OFFLOAD = 0x4000
@ -1338,11 +1405,19 @@ const (
SO_RCVTIMEO = 0x1006
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_REUSEPORT_LB = 0x10000
SO_SETFIB = 0x1014
SO_SNDBUF = 0x1001
SO_SNDLOWAT = 0x1003
SO_SNDTIMEO = 0x1005
SO_TIMESTAMP = 0x400
SO_TS_BINTIME = 0x1
SO_TS_CLOCK = 0x1017
SO_TS_CLOCK_MAX = 0x3
SO_TS_DEFAULT = 0x0
SO_TS_MONOTONIC = 0x3
SO_TS_REALTIME = 0x2
SO_TS_REALTIME_MICRO = 0x0
SO_TYPE = 0x1008
SO_USELOOPBACK = 0x40
SO_USER_COOKIE = 0x1015
@ -1386,10 +1461,45 @@ const (
TCOFLUSH = 0x2
TCOOFF = 0x1
TCOON = 0x2
TCP_BBR_ACK_COMP_ALG = 0x448
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
TCP_BBR_DRAIN_PG = 0x42e
TCP_BBR_EXTRA_GAIN = 0x449
TCP_BBR_IWINTSO = 0x42b
TCP_BBR_LOWGAIN_FD = 0x436
TCP_BBR_LOWGAIN_HALF = 0x435
TCP_BBR_LOWGAIN_THRESH = 0x434
TCP_BBR_MAX_RTO = 0x439
TCP_BBR_MIN_RTO = 0x438
TCP_BBR_ONE_RETRAN = 0x431
TCP_BBR_PACE_CROSS = 0x442
TCP_BBR_PACE_DEL_TAR = 0x43f
TCP_BBR_PACE_PER_SEC = 0x43e
TCP_BBR_PACE_SEG_MAX = 0x440
TCP_BBR_PACE_SEG_MIN = 0x441
TCP_BBR_PROBE_RTT_GAIN = 0x44d
TCP_BBR_PROBE_RTT_INT = 0x430
TCP_BBR_PROBE_RTT_LEN = 0x44e
TCP_BBR_RACK_RTT_USE = 0x44a
TCP_BBR_RECFORCE = 0x42c
TCP_BBR_REC_OVER_HPTS = 0x43a
TCP_BBR_RETRAN_WTSO = 0x44b
TCP_BBR_RWND_IS_APP = 0x42f
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
TCP_BBR_STARTUP_PG = 0x42d
TCP_BBR_UNLIMITED = 0x43b
TCP_BBR_USEDEL_RATE = 0x437
TCP_BBR_USE_LOWGAIN = 0x433
TCP_CA_NAME_MAX = 0x10
TCP_CCALGOOPT = 0x41
TCP_CONGESTION = 0x40
TCP_DATA_AFTER_CLOSE = 0x44c
TCP_DELACK = 0x48
TCP_FASTOPEN = 0x401
TCP_FASTOPEN_MAX_COOKIE_LEN = 0x10
TCP_FASTOPEN_MIN_COOKIE_LEN = 0x4
TCP_FASTOPEN_PSK_LEN = 0x10
TCP_FUNCTION_BLK = 0x2000
TCP_FUNCTION_NAME_LEN_MAX = 0x20
TCP_INFO = 0x20
@ -1397,6 +1507,12 @@ const (
TCP_KEEPIDLE = 0x100
TCP_KEEPINIT = 0x80
TCP_KEEPINTVL = 0x200
TCP_LOG = 0x22
TCP_LOGBUF = 0x23
TCP_LOGDUMP = 0x25
TCP_LOGDUMPID = 0x26
TCP_LOGID = 0x24
TCP_LOG_ID_LEN = 0x40
TCP_MAXBURST = 0x4
TCP_MAXHLEN = 0x3c
TCP_MAXOLEN = 0x28
@ -1412,8 +1528,30 @@ const (
TCP_NOPUSH = 0x4
TCP_PCAP_IN = 0x1000
TCP_PCAP_OUT = 0x800
TCP_RACK_EARLY_RECOV = 0x423
TCP_RACK_EARLY_SEG = 0x424
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
TCP_RACK_MIN_PACE = 0x445
TCP_RACK_MIN_PACE_SEG = 0x446
TCP_RACK_MIN_TO = 0x422
TCP_RACK_PACE_ALWAYS = 0x41f
TCP_RACK_PACE_MAX_SEG = 0x41e
TCP_RACK_PACE_REDUCE = 0x41d
TCP_RACK_PKT_DELAY = 0x428
TCP_RACK_PROP = 0x41b
TCP_RACK_PROP_RATE = 0x420
TCP_RACK_PRR_SENDALOT = 0x421
TCP_RACK_REORD_FADE = 0x426
TCP_RACK_REORD_THRESH = 0x425
TCP_RACK_SESS_CWV = 0x42a
TCP_RACK_TLP_INC_VAR = 0x429
TCP_RACK_TLP_REDUCE = 0x41c
TCP_RACK_TLP_THRESH = 0x427
TCP_RACK_TLP_USE = 0x447
TCP_VENDOR = 0x80000000
TCSAFLUSH = 0x2
TIMER_ABSTIME = 0x1
TIMER_RELTIME = 0x0
TIOCCBRK = 0x2000747a
TIOCCDTR = 0x20007478
TIOCCONS = 0x80047462
@ -1477,6 +1615,8 @@ const (
TIOCTIMESTAMP = 0x40107459
TIOCUCNTL = 0x80047466
TOSTOP = 0x400000
UTIME_NOW = -0x1
UTIME_OMIT = -0x2
VDISCARD = 0xf
VDSUSP = 0xb
VEOF = 0x0
@ -1488,6 +1628,7 @@ const (
VKILL = 0x5
VLNEXT = 0xe
VMIN = 0x10
VM_BCACHE_SIZE_MAX = 0x19000000
VQUIT = 0x9
VREPRINT = 0x6
VSTART = 0xc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save