Browse Source

Implement email alerting

Brendan Abolivier 4 years ago
parent
commit
c39d6de4b5
Signed by: Brendan Abolivier <contact@brendanabolivier.com> GPG key ID: 8EF1500759F70623
100 changed files with 9761 additions and 13 deletions
  1. 8
    2
      config.sample.yaml
  2. 18
    6
      src/metrics-alerting/alert/alert.go
  3. 48
    2
      src/metrics-alerting/alert/email.go
  4. 25
    1
      src/metrics-alerting/config/config.go
  5. 2
    2
      src/metrics-alerting/main.go
  6. 26
    0
      vendor/manifest
  7. 951
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/terminal.go
  8. 350
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/terminal_test.go
  9. 116
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/util.go
  10. 12
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/util_bsd.go
  11. 10
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/util_linux.go
  12. 58
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/util_plan9.go
  13. 128
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/util_solaris.go
  14. 102
    0
      vendor/src/golang.org/x/crypto/ssh/terminal/util_windows.go
  15. 173
    0
      vendor/src/golang.org/x/sys/unix/README.md
  16. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_darwin_386.s
  17. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_darwin_amd64.s
  18. 30
    0
      vendor/src/golang.org/x/sys/unix/asm_darwin_arm.s
  19. 30
    0
      vendor/src/golang.org/x/sys/unix/asm_darwin_arm64.s
  20. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_dragonfly_amd64.s
  21. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_freebsd_386.s
  22. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_freebsd_amd64.s
  23. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_freebsd_arm.s
  24. 35
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_386.s
  25. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_amd64.s
  26. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_arm.s
  27. 24
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_arm64.s
  28. 28
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_mips64x.s
  29. 31
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_mipsx.s
  30. 28
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_ppc64x.s
  31. 28
    0
      vendor/src/golang.org/x/sys/unix/asm_linux_s390x.s
  32. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_netbsd_386.s
  33. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_netbsd_amd64.s
  34. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_netbsd_arm.s
  35. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_openbsd_386.s
  36. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_openbsd_amd64.s
  37. 29
    0
      vendor/src/golang.org/x/sys/unix/asm_openbsd_arm.s
  38. 17
    0
      vendor/src/golang.org/x/sys/unix/asm_solaris_amd64.s
  39. 35
    0
      vendor/src/golang.org/x/sys/unix/bluetooth_linux.go
  40. 195
    0
      vendor/src/golang.org/x/sys/unix/cap_freebsd.go
  41. 13
    0
      vendor/src/golang.org/x/sys/unix/constants.go
  42. 136
    0
      vendor/src/golang.org/x/sys/unix/creds_test.go
  43. 24
    0
      vendor/src/golang.org/x/sys/unix/dev_darwin.go
  44. 51
    0
      vendor/src/golang.org/x/sys/unix/dev_darwin_test.go
  45. 30
    0
      vendor/src/golang.org/x/sys/unix/dev_dragonfly.go
  46. 50
    0
      vendor/src/golang.org/x/sys/unix/dev_dragonfly_test.go
  47. 30
    0
      vendor/src/golang.org/x/sys/unix/dev_freebsd.go
  48. 42
    0
      vendor/src/golang.org/x/sys/unix/dev_linux.go
  49. 53
    0
      vendor/src/golang.org/x/sys/unix/dev_linux_test.go
  50. 29
    0
      vendor/src/golang.org/x/sys/unix/dev_netbsd.go
  51. 52
    0
      vendor/src/golang.org/x/sys/unix/dev_netbsd_test.go
  52. 29
    0
      vendor/src/golang.org/x/sys/unix/dev_openbsd.go
  53. 54
    0
      vendor/src/golang.org/x/sys/unix/dev_openbsd_test.go
  54. 51
    0
      vendor/src/golang.org/x/sys/unix/dev_solaris_test.go
  55. 102
    0
      vendor/src/golang.org/x/sys/unix/dirent.go
  56. 9
    0
      vendor/src/golang.org/x/sys/unix/endian_big.go
  57. 9
    0
      vendor/src/golang.org/x/sys/unix/endian_little.go
  58. 27
    0
      vendor/src/golang.org/x/sys/unix/env_unix.go
  59. 14
    0
      vendor/src/golang.org/x/sys/unix/env_unset.go
  60. 227
    0
      vendor/src/golang.org/x/sys/unix/errors_freebsd_386.go
  61. 227
    0
      vendor/src/golang.org/x/sys/unix/errors_freebsd_amd64.go
  62. 226
    0
      vendor/src/golang.org/x/sys/unix/errors_freebsd_arm.go
  63. 9
    0
      vendor/src/golang.org/x/sys/unix/export_test.go
  64. 22
    0
      vendor/src/golang.org/x/sys/unix/flock.go
  65. 13
    0
      vendor/src/golang.org/x/sys/unix/flock_linux_32bit.go
  66. 46
    0
      vendor/src/golang.org/x/sys/unix/gccgo.go
  67. 41
    0
      vendor/src/golang.org/x/sys/unix/gccgo_c.c
  68. 20
    0
      vendor/src/golang.org/x/sys/unix/gccgo_linux_amd64.go
  69. 51
    0
      vendor/src/golang.org/x/sys/unix/linux/Dockerfile
  70. 482
    0
      vendor/src/golang.org/x/sys/unix/linux/mkall.go
  71. 85
    0
      vendor/src/golang.org/x/sys/unix/linux/mksysnum.pl
  72. 595
    0
      vendor/src/golang.org/x/sys/unix/linux/types.go
  73. 194
    0
      vendor/src/golang.org/x/sys/unix/mkall.sh
  74. 577
    0
      vendor/src/golang.org/x/sys/unix/mkerrors.sh
  75. 93
    0
      vendor/src/golang.org/x/sys/unix/mkpost.go
  76. 328
    0
      vendor/src/golang.org/x/sys/unix/mksyscall.pl
  77. 289
    0
      vendor/src/golang.org/x/sys/unix/mksyscall_solaris.pl
  78. 264
    0
      vendor/src/golang.org/x/sys/unix/mksysctl_openbsd.pl
  79. 39
    0
      vendor/src/golang.org/x/sys/unix/mksysnum_darwin.pl
  80. 50
    0
      vendor/src/golang.org/x/sys/unix/mksysnum_dragonfly.pl
  81. 50
    0
      vendor/src/golang.org/x/sys/unix/mksysnum_freebsd.pl
  82. 58
    0
      vendor/src/golang.org/x/sys/unix/mksysnum_netbsd.pl
  83. 50
    0
      vendor/src/golang.org/x/sys/unix/mksysnum_openbsd.pl
  84. 35
    0
      vendor/src/golang.org/x/sys/unix/mmap_unix_test.go
  85. 38
    0
      vendor/src/golang.org/x/sys/unix/openbsd_pledge.go
  86. 113
    0
      vendor/src/golang.org/x/sys/unix/openbsd_test.go
  87. 15
    0
      vendor/src/golang.org/x/sys/unix/pagesize_unix.go
  88. 30
    0
      vendor/src/golang.org/x/sys/unix/race.go
  89. 25
    0
      vendor/src/golang.org/x/sys/unix/race0.go
  90. 36
    0
      vendor/src/golang.org/x/sys/unix/sockcmsg_linux.go
  91. 104
    0
      vendor/src/golang.org/x/sys/unix/sockcmsg_unix.go
  92. 26
    0
      vendor/src/golang.org/x/sys/unix/str.go
  93. 51
    0
      vendor/src/golang.org/x/sys/unix/syscall.go
  94. 653
    0
      vendor/src/golang.org/x/sys/unix/syscall_bsd.go
  95. 70
    0
      vendor/src/golang.org/x/sys/unix/syscall_bsd_test.go
  96. 612
    0
      vendor/src/golang.org/x/sys/unix/syscall_darwin.go
  97. 68
    0
      vendor/src/golang.org/x/sys/unix/syscall_darwin_386.go
  98. 68
    0
      vendor/src/golang.org/x/sys/unix/syscall_darwin_amd64.go
  99. 62
    0
      vendor/src/golang.org/x/sys/unix/syscall_darwin_arm.go
  100. 0
    0
      vendor/src/golang.org/x/sys/unix/syscall_darwin_arm64.go

+ 8
- 2
config.sample.yaml View File

@@ -1,3 +1,11 @@
1
+mail:
2
+    sender: foo@bar.baz
3
+    recipient: admin@bar.baz
4
+    smtp:
5
+        host: smtp.bar.baz
6
+        port: 465
7
+        username: foo@bar.baz
8
+        password: hackme
1 9
 warp10_exec: http://localhost/api/v0/exec
2 10
 token: READ_TOKEN
3 11
 scripts:
@@ -13,9 +21,7 @@ scripts:
13 21
             ] FETCH
14 22
             VALUES LIST-> DROP LIST-> DROP
15 23
             "
16
-        # bool | number
17 24
         type: number
18
-        # only required if type == number
19 25
         threshold: 50
20 26
         action: http
21 27
         target: http://localhost:9996/alert

+ 18
- 6
src/metrics-alerting/alert/alert.go View File

@@ -7,7 +7,11 @@ import (
7 7
 	"metrics-alerting/warp10"
8 8
 )
9 9
 
10
-func ProcessNumber(client warp10.Warp10Client, script config.Script) error {
10
+func ProcessNumber(
11
+	client warp10.Warp10Client,
12
+	script config.Script,
13
+	ms config.MailSettings,
14
+) error {
11 15
 	value, err := client.ReadNumber(script.Script)
12 16
 	if err != nil {
13 17
 		return err
@@ -18,10 +22,14 @@ func ProcessNumber(client warp10.Warp10Client, script config.Script) error {
18 22
 		return nil
19 23
 	}
20 24
 
21
-	return alert(script, value)
25
+	return alert(script, value, ms)
22 26
 }
23 27
 
24
-func ProcessBool(client warp10.Warp10Client, script config.Script) error {
28
+func ProcessBool(
29
+	client warp10.Warp10Client,
30
+	script config.Script,
31
+	ms config.MailSettings,
32
+) error {
25 33
 	value, err := client.ReadBool(script.Script)
26 34
 	if err != nil {
27 35
 		return err
@@ -31,15 +39,19 @@ func ProcessBool(client warp10.Warp10Client, script config.Script) error {
31 39
 		return nil
32 40
 	}
33 41
 
34
-	return alert(script, value)
42
+	return alert(script, value, ms)
35 43
 }
36 44
 
37
-func alert(script config.Script, result interface{}) error {
45
+func alert(
46
+	script config.Script,
47
+	result interface{},
48
+	ms config.MailSettings,
49
+) error {
38 50
 	switch script.Action {
39 51
 	case "http":
40 52
 		return alertHttp(script, result)
41 53
 	case "email":
42
-		return alertEmail(script, result)
54
+		return alertEmail(script, result, ms)
43 55
 	default:
44 56
 		return fmt.Errorf("invalid action type: %s", script.Action)
45 57
 	}

+ 48
- 2
src/metrics-alerting/alert/email.go View File

@@ -1,9 +1,55 @@
1 1
 package alert
2 2
 
3 3
 import (
4
+	"fmt"
5
+
4 6
 	"metrics-alerting/config"
7
+
8
+	"gopkg.in/gomail.v2"
5 9
 )
6 10
 
7
-func alertEmail(script config.Script, result interface{}) error {
8
-	return nil
11
+func alertEmail(
12
+	script config.Script,
13
+	result interface{},
14
+	ms config.MailSettings,
15
+) error {
16
+	formatNumber := `
17
+Script %s just exceeded its threshold of %f and now returns %f
18
+
19
+Script:
20
+
21
+%s
22
+	`
23
+
24
+	formatBool := `
25
+Test for script %s and returned false instead of true
26
+
27
+Script:
28
+
29
+%s
30
+	`
31
+
32
+	var body, subject string
33
+	switch script.Type {
34
+	case "number":
35
+		subject = fmt.Sprintf("Threshold exceeded for script %s", script.Key)
36
+		body = fmt.Sprintf(
37
+			formatNumber, script.Key, script.Threshold, result.(float64),
38
+			script.Script,
39
+		)
40
+	case "bool":
41
+		subject = fmt.Sprintf("Test for script %s failed", script.Key)
42
+		body = fmt.Sprintf(formatBool, script.Key, script.Script)
43
+	}
44
+
45
+	m := gomail.NewMessage()
46
+	m.SetHeader("From", ms.Sender)
47
+	m.SetHeader("To", ms.Recipient)
48
+	m.SetHeader("Subject", subject)
49
+	m.SetBody("text/plain", body)
50
+
51
+	d := gomail.NewDialer(
52
+		ms.SMTP.Host, ms.SMTP.Port, ms.SMTP.Username, ms.SMTP.Password,
53
+	)
54
+	return d.DialAndSend(m)
9 55
 }

+ 25
- 1
src/metrics-alerting/config/config.go View File

@@ -6,6 +6,26 @@ import (
6 6
 	"gopkg.in/yaml.v2"
7 7
 )
8 8
 
9
+type MailSettings struct {
10
+	// Sender of the alert emails
11
+	Sender string `yaml:"sender"`
12
+	// Recipient of the alert emails
13
+	Recipient string `yaml:"recipient"`
14
+	// Settings to connect to the mail server
15
+	SMTP SMTPSettings `yaml:"smtp"`
16
+}
17
+
18
+type SMTPSettings struct {
19
+	// Host of the mail server
20
+	Host string `yaml:"host"`
21
+	// Port of the mail server
22
+	Port int `yaml:"port"`
23
+	// Username used to authenticate on the mail server
24
+	Username string `yaml:"username"`
25
+	// Password used to authenticate on the mail server
26
+	Password string `yaml:"password"`
27
+}
28
+
9 29
 type Script struct {
10 30
 	// An identifying key for the script
11 31
 	Key string `yaml:"key"`
@@ -13,7 +33,8 @@ type Script struct {
13 33
 	Script string `yaml:"script"`
14 34
 	// The type of the value returned by the script
15 35
 	Type string `yaml:"type"`
16
-	// Value above which an action is required
36
+	// Value above which an action is required, only required if the type is
37
+	// "number"
17 38
 	Threshold float64 `yaml:"threshold,omitempty"`
18 39
 	// The action to take (either "http" or "email")
19 40
 	Action string `yaml:"action"`
@@ -22,6 +43,9 @@ type Script struct {
22 43
 }
23 44
 
24 45
 type Config struct {
46
+	// Settings to send email alerts, only required if the action of at least 1
47
+	// script is "email"
48
+	Mail MailSettings `yaml:"mail,omitempty"`
25 49
 	// Full URL to Warp10's /exec
26 50
 	Warp10Exec string `yaml:"warp10_exec"`
27 51
 	// Warp10 read token

+ 2
- 2
src/metrics-alerting/main.go View File

@@ -28,10 +28,10 @@ func main() {
28 28
 		var err error
29 29
 		switch script.Type {
30 30
 		case "number":
31
-			err = alert.ProcessNumber(client, script)
31
+			err = alert.ProcessNumber(client, script, cfg.Mail)
32 32
 			break
33 33
 		case "bool":
34
-			err = alert.ProcessBool(client, script)
34
+			err = alert.ProcessBool(client, script, cfg.Mail)
35 35
 			break
36 36
 		default:
37 37
 			err = fmt.Errorf("invalid return type: %s", script.Type)

+ 26
- 0
vendor/manifest View File

@@ -2,6 +2,32 @@
2 2
 	"version": 0,
3 3
 	"dependencies": [
4 4
 		{
5
+			"importpath": "github.com/sirupsen/logrus",
6
+			"repository": "https://github.com/sirupsen/logrus",
7
+			"revision": "95cd2b9c79aa5e72ab0bc69b7ccc2be15bf850f6",
8
+			"branch": "master"
9
+		},
10
+		{
11
+			"importpath": "golang.org/x/crypto/ssh/terminal",
12
+			"repository": "https://go.googlesource.com/crypto",
13
+			"revision": "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94",
14
+			"branch": "master",
15
+			"path": "/ssh/terminal"
16
+		},
17
+		{
18
+			"importpath": "golang.org/x/sys/unix",
19
+			"repository": "https://go.googlesource.com/sys",
20
+			"revision": "328643532ee3c60c099171d4ce2cad0ca0354ca9",
21
+			"branch": "master",
22
+			"path": "/unix"
23
+		},
24
+		{
25
+			"importpath": "gopkg.in/gomail.v2",
26
+			"repository": "https://gopkg.in/gomail.v2",
27
+			"revision": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1",
28
+			"branch": "v2"
29
+		},
30
+		{
5 31
 			"importpath": "gopkg.in/yaml.v2",
6 32
 			"repository": "https://gopkg.in/yaml.v2",
7 33
 			"revision": "287cf08546ab5e7e37d55a84f7ed3fd1db036de5",

+ 951
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/terminal.go View File

@@ -0,0 +1,951 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package terminal
6
+
7
+import (
8
+	"bytes"
9
+	"io"
10
+	"sync"
11
+	"unicode/utf8"
12
+)
13
+
14
+// EscapeCodes contains escape sequences that can be written to the terminal in
15
+// order to achieve different styles of text.
16
+type EscapeCodes struct {
17
+	// Foreground colors
18
+	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
19
+
20
+	// Reset all attributes
21
+	Reset []byte
22
+}
23
+
24
+var vt100EscapeCodes = EscapeCodes{
25
+	Black:   []byte{keyEscape, '[', '3', '0', 'm'},
26
+	Red:     []byte{keyEscape, '[', '3', '1', 'm'},
27
+	Green:   []byte{keyEscape, '[', '3', '2', 'm'},
28
+	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'},
29
+	Blue:    []byte{keyEscape, '[', '3', '4', 'm'},
30
+	Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
31
+	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'},
32
+	White:   []byte{keyEscape, '[', '3', '7', 'm'},
33
+
34
+	Reset: []byte{keyEscape, '[', '0', 'm'},
35
+}
36
+
37
+// Terminal contains the state for running a VT100 terminal that is capable of
38
+// reading lines of input.
39
+type Terminal struct {
40
+	// AutoCompleteCallback, if non-null, is called for each keypress with
41
+	// the full input line and the current position of the cursor (in
42
+	// bytes, as an index into |line|). If it returns ok=false, the key
43
+	// press is processed normally. Otherwise it returns a replacement line
44
+	// and the new cursor position.
45
+	AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
46
+
47
+	// Escape contains a pointer to the escape codes for this terminal.
48
+	// It's always a valid pointer, although the escape codes themselves
49
+	// may be empty if the terminal doesn't support them.
50
+	Escape *EscapeCodes
51
+
52
+	// lock protects the terminal and the state in this object from
53
+	// concurrent processing of a key press and a Write() call.
54
+	lock sync.Mutex
55
+
56
+	c      io.ReadWriter
57
+	prompt []rune
58
+
59
+	// line is the current line being entered.
60
+	line []rune
61
+	// pos is the logical position of the cursor in line
62
+	pos int
63
+	// echo is true if local echo is enabled
64
+	echo bool
65
+	// pasteActive is true iff there is a bracketed paste operation in
66
+	// progress.
67
+	pasteActive bool
68
+
69
+	// cursorX contains the current X value of the cursor where the left
70
+	// edge is 0. cursorY contains the row number where the first row of
71
+	// the current line is 0.
72
+	cursorX, cursorY int
73
+	// maxLine is the greatest value of cursorY so far.
74
+	maxLine int
75
+
76
+	termWidth, termHeight int
77
+
78
+	// outBuf contains the terminal data to be sent.
79
+	outBuf []byte
80
+	// remainder contains the remainder of any partial key sequences after
81
+	// a read. It aliases into inBuf.
82
+	remainder []byte
83
+	inBuf     [256]byte
84
+
85
+	// history contains previously entered commands so that they can be
86
+	// accessed with the up and down keys.
87
+	history stRingBuffer
88
+	// historyIndex stores the currently accessed history entry, where zero
89
+	// means the immediately previous entry.
90
+	historyIndex int
91
+	// When navigating up and down the history it's possible to return to
92
+	// the incomplete, initial line. That value is stored in
93
+	// historyPending.
94
+	historyPending string
95
+}
96
+
97
+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
98
+// a local terminal, that terminal must first have been put into raw mode.
99
+// prompt is a string that is written at the start of each input line (i.e.
100
+// "> ").
101
+func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
102
+	return &Terminal{
103
+		Escape:       &vt100EscapeCodes,
104
+		c:            c,
105
+		prompt:       []rune(prompt),
106
+		termWidth:    80,
107
+		termHeight:   24,
108
+		echo:         true,
109
+		historyIndex: -1,
110
+	}
111
+}
112
+
113
+const (
114
+	keyCtrlD     = 4
115
+	keyCtrlU     = 21
116
+	keyEnter     = '\r'
117
+	keyEscape    = 27
118
+	keyBackspace = 127
119
+	keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota
120
+	keyUp
121
+	keyDown
122
+	keyLeft
123
+	keyRight
124
+	keyAltLeft
125
+	keyAltRight
126
+	keyHome
127
+	keyEnd
128
+	keyDeleteWord
129
+	keyDeleteLine
130
+	keyClearScreen
131
+	keyPasteStart
132
+	keyPasteEnd
133
+)
134
+
135
+var (
136
+	crlf       = []byte{'\r', '\n'}
137
+	pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
138
+	pasteEnd   = []byte{keyEscape, '[', '2', '0', '1', '~'}
139
+)
140
+
141
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
142
+// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
143
+func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
144
+	if len(b) == 0 {
145
+		return utf8.RuneError, nil
146
+	}
147
+
148
+	if !pasteActive {
149
+		switch b[0] {
150
+		case 1: // ^A
151
+			return keyHome, b[1:]
152
+		case 5: // ^E
153
+			return keyEnd, b[1:]
154
+		case 8: // ^H
155
+			return keyBackspace, b[1:]
156
+		case 11: // ^K
157
+			return keyDeleteLine, b[1:]
158
+		case 12: // ^L
159
+			return keyClearScreen, b[1:]
160
+		case 23: // ^W
161
+			return keyDeleteWord, b[1:]
162
+		}
163
+	}
164
+
165
+	if b[0] != keyEscape {
166
+		if !utf8.FullRune(b) {
167
+			return utf8.RuneError, b
168
+		}
169
+		r, l := utf8.DecodeRune(b)
170
+		return r, b[l:]
171
+	}
172
+
173
+	if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
174
+		switch b[2] {
175
+		case 'A':
176
+			return keyUp, b[3:]
177
+		case 'B':
178
+			return keyDown, b[3:]
179
+		case 'C':
180
+			return keyRight, b[3:]
181
+		case 'D':
182
+			return keyLeft, b[3:]
183
+		case 'H':
184
+			return keyHome, b[3:]
185
+		case 'F':
186
+			return keyEnd, b[3:]
187
+		}
188
+	}
189
+
190
+	if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
191
+		switch b[5] {
192
+		case 'C':
193
+			return keyAltRight, b[6:]
194
+		case 'D':
195
+			return keyAltLeft, b[6:]
196
+		}
197
+	}
198
+
199
+	if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
200
+		return keyPasteStart, b[6:]
201
+	}
202
+
203
+	if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
204
+		return keyPasteEnd, b[6:]
205
+	}
206
+
207
+	// If we get here then we have a key that we don't recognise, or a
208
+	// partial sequence. It's not clear how one should find the end of a
209
+	// sequence without knowing them all, but it seems that [a-zA-Z~] only
210
+	// appears at the end of a sequence.
211
+	for i, c := range b[0:] {
212
+		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
213
+			return keyUnknown, b[i+1:]
214
+		}
215
+	}
216
+
217
+	return utf8.RuneError, b
218
+}
219
+
220
+// queue appends data to the end of t.outBuf
221
+func (t *Terminal) queue(data []rune) {
222
+	t.outBuf = append(t.outBuf, []byte(string(data))...)
223
+}
224
+
225
+var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'}
226
+var space = []rune{' '}
227
+
228
+func isPrintable(key rune) bool {
229
+	isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
230
+	return key >= 32 && !isInSurrogateArea
231
+}
232
+
233
+// moveCursorToPos appends data to t.outBuf which will move the cursor to the
234
+// given, logical position in the text.
235
+func (t *Terminal) moveCursorToPos(pos int) {
236
+	if !t.echo {
237
+		return
238
+	}
239
+
240
+	x := visualLength(t.prompt) + pos
241
+	y := x / t.termWidth
242
+	x = x % t.termWidth
243
+
244
+	up := 0
245
+	if y < t.cursorY {
246
+		up = t.cursorY - y
247
+	}
248
+
249
+	down := 0
250
+	if y > t.cursorY {
251
+		down = y - t.cursorY
252
+	}
253
+
254
+	left := 0
255
+	if x < t.cursorX {
256
+		left = t.cursorX - x
257
+	}
258
+
259
+	right := 0
260
+	if x > t.cursorX {
261
+		right = x - t.cursorX
262
+	}
263
+
264
+	t.cursorX = x
265
+	t.cursorY = y
266
+	t.move(up, down, left, right)
267
+}
268
+
269
+func (t *Terminal) move(up, down, left, right int) {
270
+	movement := make([]rune, 3*(up+down+left+right))
271
+	m := movement
272
+	for i := 0; i < up; i++ {
273
+		m[0] = keyEscape
274
+		m[1] = '['
275
+		m[2] = 'A'
276
+		m = m[3:]
277
+	}
278
+	for i := 0; i < down; i++ {
279
+		m[0] = keyEscape
280
+		m[1] = '['
281
+		m[2] = 'B'
282
+		m = m[3:]
283
+	}
284
+	for i := 0; i < left; i++ {
285
+		m[0] = keyEscape
286
+		m[1] = '['
287
+		m[2] = 'D'
288
+		m = m[3:]
289
+	}
290
+	for i := 0; i < right; i++ {
291
+		m[0] = keyEscape
292
+		m[1] = '['
293
+		m[2] = 'C'
294
+		m = m[3:]
295
+	}
296
+
297
+	t.queue(movement)
298
+}
299
+
300
+func (t *Terminal) clearLineToRight() {
301
+	op := []rune{keyEscape, '[', 'K'}
302
+	t.queue(op)
303
+}
304
+
305
+const maxLineLength = 4096
306
+
307
+func (t *Terminal) setLine(newLine []rune, newPos int) {
308
+	if t.echo {
309
+		t.moveCursorToPos(0)
310
+		t.writeLine(newLine)
311
+		for i := len(newLine); i < len(t.line); i++ {
312
+			t.writeLine(space)
313
+		}
314
+		t.moveCursorToPos(newPos)
315
+	}
316
+	t.line = newLine
317
+	t.pos = newPos
318
+}
319
+
320
+func (t *Terminal) advanceCursor(places int) {
321
+	t.cursorX += places
322
+	t.cursorY += t.cursorX / t.termWidth
323
+	if t.cursorY > t.maxLine {
324
+		t.maxLine = t.cursorY
325
+	}
326
+	t.cursorX = t.cursorX % t.termWidth
327
+
328
+	if places > 0 && t.cursorX == 0 {
329
+		// Normally terminals will advance the current position
330
+		// when writing a character. But that doesn't happen
331
+		// for the last character in a line. However, when
332
+		// writing a character (except a new line) that causes
333
+		// a line wrap, the position will be advanced two
334
+		// places.
335
+		//
336
+		// So, if we are stopping at the end of a line, we
337
+		// need to write a newline so that our cursor can be
338
+		// advanced to the next line.
339
+		t.outBuf = append(t.outBuf, '\r', '\n')
340
+	}
341
+}
342
+
343
+func (t *Terminal) eraseNPreviousChars(n int) {
344
+	if n == 0 {
345
+		return
346
+	}
347
+
348
+	if t.pos < n {
349
+		n = t.pos
350
+	}
351
+	t.pos -= n
352
+	t.moveCursorToPos(t.pos)
353
+
354
+	copy(t.line[t.pos:], t.line[n+t.pos:])
355
+	t.line = t.line[:len(t.line)-n]
356
+	if t.echo {
357
+		t.writeLine(t.line[t.pos:])
358
+		for i := 0; i < n; i++ {
359
+			t.queue(space)
360
+		}
361
+		t.advanceCursor(n)
362
+		t.moveCursorToPos(t.pos)
363
+	}
364
+}
365
+
366
+// countToLeftWord returns then number of characters from the cursor to the
367
+// start of the previous word.
368
+func (t *Terminal) countToLeftWord() int {
369
+	if t.pos == 0 {
370
+		return 0
371
+	}
372
+
373
+	pos := t.pos - 1
374
+	for pos > 0 {
375
+		if t.line[pos] != ' ' {
376
+			break
377
+		}
378
+		pos--
379
+	}
380
+	for pos > 0 {
381
+		if t.line[pos] == ' ' {
382
+			pos++
383
+			break
384
+		}
385
+		pos--
386
+	}
387
+
388
+	return t.pos - pos
389
+}
390
+
391
+// countToRightWord returns then number of characters from the cursor to the
392
+// start of the next word.
393
+func (t *Terminal) countToRightWord() int {
394
+	pos := t.pos
395
+	for pos < len(t.line) {
396
+		if t.line[pos] == ' ' {
397
+			break
398
+		}
399
+		pos++
400
+	}
401
+	for pos < len(t.line) {
402
+		if t.line[pos] != ' ' {
403
+			break
404
+		}
405
+		pos++
406
+	}
407
+	return pos - t.pos
408
+}
409
+
410
+// visualLength returns the number of visible glyphs in s.
411
+func visualLength(runes []rune) int {
412
+	inEscapeSeq := false
413
+	length := 0
414
+
415
+	for _, r := range runes {
416
+		switch {
417
+		case inEscapeSeq:
418
+			if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
419
+				inEscapeSeq = false
420
+			}
421
+		case r == '\x1b':
422
+			inEscapeSeq = true
423
+		default:
424
+			length++
425
+		}
426
+	}
427
+
428
+	return length
429
+}
430
+
431
+// handleKey processes the given key and, optionally, returns a line of text
432
+// that the user has entered.
433
+func (t *Terminal) handleKey(key rune) (line string, ok bool) {
434
+	if t.pasteActive && key != keyEnter {
435
+		t.addKeyToLine(key)
436
+		return
437
+	}
438
+
439
+	switch key {
440
+	case keyBackspace:
441
+		if t.pos == 0 {
442
+			return
443
+		}
444
+		t.eraseNPreviousChars(1)
445
+	case keyAltLeft:
446
+		// move left by a word.
447
+		t.pos -= t.countToLeftWord()
448
+		t.moveCursorToPos(t.pos)
449
+	case keyAltRight:
450
+		// move right by a word.
451
+		t.pos += t.countToRightWord()
452
+		t.moveCursorToPos(t.pos)
453
+	case keyLeft:
454
+		if t.pos == 0 {
455
+			return
456
+		}
457
+		t.pos--
458
+		t.moveCursorToPos(t.pos)
459
+	case keyRight:
460
+		if t.pos == len(t.line) {
461
+			return
462
+		}
463
+		t.pos++
464
+		t.moveCursorToPos(t.pos)
465
+	case keyHome:
466
+		if t.pos == 0 {
467
+			return
468
+		}
469
+		t.pos = 0
470
+		t.moveCursorToPos(t.pos)
471
+	case keyEnd:
472
+		if t.pos == len(t.line) {
473
+			return
474
+		}
475
+		t.pos = len(t.line)
476
+		t.moveCursorToPos(t.pos)
477
+	case keyUp:
478
+		entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
479
+		if !ok {
480
+			return "", false
481
+		}
482
+		if t.historyIndex == -1 {
483
+			t.historyPending = string(t.line)
484
+		}
485
+		t.historyIndex++
486
+		runes := []rune(entry)
487
+		t.setLine(runes, len(runes))
488
+	case keyDown:
489
+		switch t.historyIndex {
490
+		case -1:
491
+			return
492
+		case 0:
493
+			runes := []rune(t.historyPending)
494
+			t.setLine(runes, len(runes))
495
+			t.historyIndex--
496
+		default:
497
+			entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
498
+			if ok {
499
+				t.historyIndex--
500
+				runes := []rune(entry)
501
+				t.setLine(runes, len(runes))
502
+			}
503
+		}
504
+	case keyEnter:
505
+		t.moveCursorToPos(len(t.line))
506
+		t.queue([]rune("\r\n"))
507
+		line = string(t.line)
508
+		ok = true
509
+		t.line = t.line[:0]
510
+		t.pos = 0
511
+		t.cursorX = 0
512
+		t.cursorY = 0
513
+		t.maxLine = 0
514
+	case keyDeleteWord:
515
+		// Delete zero or more spaces and then one or more characters.
516
+		t.eraseNPreviousChars(t.countToLeftWord())
517
+	case keyDeleteLine:
518
+		// Delete everything from the current cursor position to the
519
+		// end of line.
520
+		for i := t.pos; i < len(t.line); i++ {
521
+			t.queue(space)
522
+			t.advanceCursor(1)
523
+		}
524
+		t.line = t.line[:t.pos]
525
+		t.moveCursorToPos(t.pos)
526
+	case keyCtrlD:
527
+		// Erase the character under the current position.
528
+		// The EOF case when the line is empty is handled in
529
+		// readLine().
530
+		if t.pos < len(t.line) {
531
+			t.pos++
532
+			t.eraseNPreviousChars(1)
533
+		}
534
+	case keyCtrlU:
535
+		t.eraseNPreviousChars(t.pos)
536
+	case keyClearScreen:
537
+		// Erases the screen and moves the cursor to the home position.
538
+		t.queue([]rune("\x1b[2J\x1b[H"))
539
+		t.queue(t.prompt)
540
+		t.cursorX, t.cursorY = 0, 0
541
+		t.advanceCursor(visualLength(t.prompt))
542
+		t.setLine(t.line, t.pos)
543
+	default:
544
+		if t.AutoCompleteCallback != nil {
545
+			prefix := string(t.line[:t.pos])
546
+			suffix := string(t.line[t.pos:])
547
+
548
+			t.lock.Unlock()
549
+			newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
550
+			t.lock.Lock()
551
+
552
+			if completeOk {
553
+				t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
554
+				return
555
+			}
556
+		}
557
+		if !isPrintable(key) {
558
+			return
559
+		}
560
+		if len(t.line) == maxLineLength {
561
+			return
562
+		}
563
+		t.addKeyToLine(key)
564
+	}
565
+	return
566
+}
567
+
568
+// addKeyToLine inserts the given key at the current position in the current
569
+// line.
570
+func (t *Terminal) addKeyToLine(key rune) {
571
+	if len(t.line) == cap(t.line) {
572
+		newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
573
+		copy(newLine, t.line)
574
+		t.line = newLine
575
+	}
576
+	t.line = t.line[:len(t.line)+1]
577
+	copy(t.line[t.pos+1:], t.line[t.pos:])
578
+	t.line[t.pos] = key
579
+	if t.echo {
580
+		t.writeLine(t.line[t.pos:])
581
+	}
582
+	t.pos++
583
+	t.moveCursorToPos(t.pos)
584
+}
585
+
586
+func (t *Terminal) writeLine(line []rune) {
587
+	for len(line) != 0 {
588
+		remainingOnLine := t.termWidth - t.cursorX
589
+		todo := len(line)
590
+		if todo > remainingOnLine {
591
+			todo = remainingOnLine
592
+		}
593
+		t.queue(line[:todo])
594
+		t.advanceCursor(visualLength(line[:todo]))
595
+		line = line[todo:]
596
+	}
597
+}
598
+
599
+// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
600
+func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
601
+	for len(buf) > 0 {
602
+		i := bytes.IndexByte(buf, '\n')
603
+		todo := len(buf)
604
+		if i >= 0 {
605
+			todo = i
606
+		}
607
+
608
+		var nn int
609
+		nn, err = w.Write(buf[:todo])
610
+		n += nn
611
+		if err != nil {
612
+			return n, err
613
+		}
614
+		buf = buf[todo:]
615
+
616
+		if i >= 0 {
617
+			if _, err = w.Write(crlf); err != nil {
618
+				return n, err
619
+			}
620
+			n += 1
621
+			buf = buf[1:]
622
+		}
623
+	}
624
+
625
+	return n, nil
626
+}
627
+
628
+func (t *Terminal) Write(buf []byte) (n int, err error) {
629
+	t.lock.Lock()
630
+	defer t.lock.Unlock()
631
+
632
+	if t.cursorX == 0 && t.cursorY == 0 {
633
+		// This is the easy case: there's nothing on the screen that we
634
+		// have to move out of the way.
635
+		return writeWithCRLF(t.c, buf)
636
+	}
637
+
638
+	// We have a prompt and possibly user input on the screen. We
639
+	// have to clear it first.
640
+	t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
641
+	t.cursorX = 0
642
+	t.clearLineToRight()
643
+
644
+	for t.cursorY > 0 {
645
+		t.move(1 /* up */, 0, 0, 0)
646
+		t.cursorY--
647
+		t.clearLineToRight()
648
+	}
649
+
650
+	if _, err = t.c.Write(t.outBuf); err != nil {
651
+		return
652
+	}
653
+	t.outBuf = t.outBuf[:0]
654
+
655
+	if n, err = writeWithCRLF(t.c, buf); err != nil {
656
+		return
657
+	}
658
+
659
+	t.writeLine(t.prompt)
660
+	if t.echo {
661
+		t.writeLine(t.line)
662
+	}
663
+
664
+	t.moveCursorToPos(t.pos)
665
+
666
+	if _, err = t.c.Write(t.outBuf); err != nil {
667
+		return
668
+	}
669
+	t.outBuf = t.outBuf[:0]
670
+	return
671
+}
672
+
673
+// ReadPassword temporarily changes the prompt and reads a password, without
674
+// echo, from the terminal.
675
+func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
676
+	t.lock.Lock()
677
+	defer t.lock.Unlock()
678
+
679
+	oldPrompt := t.prompt
680
+	t.prompt = []rune(prompt)
681
+	t.echo = false
682
+
683
+	line, err = t.readLine()
684
+
685
+	t.prompt = oldPrompt
686
+	t.echo = true
687
+
688
+	return
689
+}
690
+
691
+// ReadLine returns a line of input from the terminal.
692
+func (t *Terminal) ReadLine() (line string, err error) {
693
+	t.lock.Lock()
694
+	defer t.lock.Unlock()
695
+
696
+	return t.readLine()
697
+}
698
+
699
+func (t *Terminal) readLine() (line string, err error) {
700
+	// t.lock must be held at this point
701
+
702
+	if t.cursorX == 0 && t.cursorY == 0 {
703
+		t.writeLine(t.prompt)
704
+		t.c.Write(t.outBuf)
705
+		t.outBuf = t.outBuf[:0]
706
+	}
707
+
708
+	lineIsPasted := t.pasteActive
709
+
710
+	for {
711
+		rest := t.remainder
712
+		lineOk := false
713
+		for !lineOk {
714
+			var key rune
715
+			key, rest = bytesToKey(rest, t.pasteActive)
716
+			if key == utf8.RuneError {
717
+				break
718
+			}
719
+			if !t.pasteActive {
720
+				if key == keyCtrlD {
721
+					if len(t.line) == 0 {
722
+						return "", io.EOF
723
+					}
724
+				}
725
+				if key == keyPasteStart {
726
+					t.pasteActive = true
727
+					if len(t.line) == 0 {
728
+						lineIsPasted = true
729
+					}
730
+					continue
731
+				}
732
+			} else if key == keyPasteEnd {
733
+				t.pasteActive = false
734
+				continue
735
+			}
736
+			if !t.pasteActive {
737
+				lineIsPasted = false
738
+			}
739
+			line, lineOk = t.handleKey(key)
740
+		}
741
+		if len(rest) > 0 {
742
+			n := copy(t.inBuf[:], rest)
743
+			t.remainder = t.inBuf[:n]
744
+		} else {
745
+			t.remainder = nil
746
+		}
747
+		t.c.Write(t.outBuf)
748
+		t.outBuf = t.outBuf[:0]
749
+		if lineOk {
750
+			if t.echo {
751
+				t.historyIndex = -1
752
+				t.history.Add(line)
753
+			}
754
+			if lineIsPasted {
755
+				err = ErrPasteIndicator
756
+			}
757
+			return
758
+		}
759
+
760
+		// t.remainder is a slice at the beginning of t.inBuf
761
+		// containing a partial key sequence
762
+		readBuf := t.inBuf[len(t.remainder):]
763
+		var n int
764
+
765
+		t.lock.Unlock()
766
+		n, err = t.c.Read(readBuf)
767
+		t.lock.Lock()
768
+
769
+		if err != nil {
770
+			return
771
+		}
772
+
773
+		t.remainder = t.inBuf[:n+len(t.remainder)]
774
+	}
775
+}
776
+
777
+// SetPrompt sets the prompt to be used when reading subsequent lines.
778
+func (t *Terminal) SetPrompt(prompt string) {
779
+	t.lock.Lock()
780
+	defer t.lock.Unlock()
781
+
782
+	t.prompt = []rune(prompt)
783
+}
784
+
785
+func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
786
+	// Move cursor to column zero at the start of the line.
787
+	t.move(t.cursorY, 0, t.cursorX, 0)
788
+	t.cursorX, t.cursorY = 0, 0
789
+	t.clearLineToRight()
790
+	for t.cursorY < numPrevLines {
791
+		// Move down a line
792
+		t.move(0, 1, 0, 0)
793
+		t.cursorY++
794
+		t.clearLineToRight()
795
+	}
796
+	// Move back to beginning.
797
+	t.move(t.cursorY, 0, 0, 0)
798
+	t.cursorX, t.cursorY = 0, 0
799
+
800
+	t.queue(t.prompt)
801
+	t.advanceCursor(visualLength(t.prompt))
802
+	t.writeLine(t.line)
803
+	t.moveCursorToPos(t.pos)
804
+}
805
+
806
+func (t *Terminal) SetSize(width, height int) error {
807
+	t.lock.Lock()
808
+	defer t.lock.Unlock()
809
+
810
+	if width == 0 {
811
+		width = 1
812
+	}
813
+
814
+	oldWidth := t.termWidth
815
+	t.termWidth, t.termHeight = width, height
816
+
817
+	switch {
818
+	case width == oldWidth:
819
+		// If the width didn't change then nothing else needs to be
820
+		// done.
821
+		return nil
822
+	case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
823
+		// If there is nothing on current line and no prompt printed,
824
+		// just do nothing
825
+		return nil
826
+	case width < oldWidth:
827
+		// Some terminals (e.g. xterm) will truncate lines that were
828
+		// too long when shinking. Others, (e.g. gnome-terminal) will
829
+		// attempt to wrap them. For the former, repainting t.maxLine
830
+		// works great, but that behaviour goes badly wrong in the case
831
+		// of the latter because they have doubled every full line.
832
+
833
+		// We assume that we are working on a terminal that wraps lines
834
+		// and adjust the cursor position based on every previous line
835
+		// wrapping and turning into two. This causes the prompt on
836
+		// xterms to move upwards, which isn't great, but it avoids a
837
+		// huge mess with gnome-terminal.
838
+		if t.cursorX >= t.termWidth {
839
+			t.cursorX = t.termWidth - 1
840
+		}
841
+		t.cursorY *= 2
842
+		t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
843
+	case width > oldWidth:
844
+		// If the terminal expands then our position calculations will
845
+		// be wrong in the future because we think the cursor is
846
+		// |t.pos| chars into the string, but there will be a gap at
847
+		// the end of any wrapped line.
848
+		//
849
+		// But the position will actually be correct until we move, so
850
+		// we can move back to the beginning and repaint everything.
851
+		t.clearAndRepaintLinePlusNPrevious(t.maxLine)
852
+	}
853
+
854
+	_, err := t.c.Write(t.outBuf)
855
+	t.outBuf = t.outBuf[:0]
856
+	return err
857
+}
858
+
859
+type pasteIndicatorError struct{}
860
+
861
+func (pasteIndicatorError) Error() string {
862
+	return "terminal: ErrPasteIndicator not correctly handled"
863
+}
864
+
865
+// ErrPasteIndicator may be returned from ReadLine as the error, in addition
866
+// to valid line data. It indicates that bracketed paste mode is enabled and
867
+// that the returned line consists only of pasted data. Programs may wish to
868
+// interpret pasted data more literally than typed data.
869
+var ErrPasteIndicator = pasteIndicatorError{}
870
+
871
+// SetBracketedPasteMode requests that the terminal bracket paste operations
872
+// with markers. Not all terminals support this but, if it is supported, then
873
+// enabling this mode will stop any autocomplete callback from running due to
874
+// pastes. Additionally, any lines that are completely pasted will be returned
875
+// from ReadLine with the error set to ErrPasteIndicator.
876
+func (t *Terminal) SetBracketedPasteMode(on bool) {
877
+	if on {
878
+		io.WriteString(t.c, "\x1b[?2004h")
879
+	} else {
880
+		io.WriteString(t.c, "\x1b[?2004l")
881
+	}
882
+}
883
+
884
+// stRingBuffer is a ring buffer of strings.
885
+type stRingBuffer struct {
886
+	// entries contains max elements.
887
+	entries []string
888
+	max     int
889
+	// head contains the index of the element most recently added to the ring.
890
+	head int
891
+	// size contains the number of elements in the ring.
892
+	size int
893
+}
894
+
895
+func (s *stRingBuffer) Add(a string) {
896
+	if s.entries == nil {
897
+		const defaultNumEntries = 100
898
+		s.entries = make([]string, defaultNumEntries)
899
+		s.max = defaultNumEntries
900
+	}
901
+
902
+	s.head = (s.head + 1) % s.max
903
+	s.entries[s.head] = a
904
+	if s.size < s.max {
905
+		s.size++
906
+	}
907
+}
908
+
909
+// NthPreviousEntry returns the value passed to the nth previous call to Add.
910
+// If n is zero then the immediately prior value is returned, if one, then the
911
+// next most recent, and so on. If such an element doesn't exist then ok is
912
+// false.
913
+func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
914
+	if n >= s.size {
915
+		return "", false
916
+	}
917
+	index := s.head - n
918
+	if index < 0 {
919
+		index += s.max
920
+	}
921
+	return s.entries[index], true
922
+}
923
+
924
+// readPasswordLine reads from reader until it finds \n or io.EOF.
925
+// The slice returned does not include the \n.
926
+// readPasswordLine also ignores any \r it finds.
927
+func readPasswordLine(reader io.Reader) ([]byte, error) {
928
+	var buf [1]byte
929
+	var ret []byte
930
+
931
+	for {
932
+		n, err := reader.Read(buf[:])
933
+		if n > 0 {
934
+			switch buf[0] {
935
+			case '\n':
936
+				return ret, nil
937
+			case '\r':
938
+				// remove \r from passwords on Windows
939
+			default:
940
+				ret = append(ret, buf[0])
941
+			}
942
+			continue
943
+		}
944
+		if err != nil {
945
+			if err == io.EOF && len(ret) > 0 {
946
+				return ret, nil
947
+			}
948
+			return ret, err
949
+		}
950
+	}
951
+}

+ 350
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/terminal_test.go View File

@@ -0,0 +1,350 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package terminal
6
+
7
+import (
8
+	"bytes"
9
+	"io"
10
+	"os"
11
+	"testing"
12
+)
13
+
14
+type MockTerminal struct {
15
+	toSend       []byte
16
+	bytesPerRead int
17
+	received     []byte
18
+}
19
+
20
+func (c *MockTerminal) Read(data []byte) (n int, err error) {
21
+	n = len(data)
22
+	if n == 0 {
23
+		return
24
+	}
25
+	if n > len(c.toSend) {
26
+		n = len(c.toSend)
27
+	}
28
+	if n == 0 {
29
+		return 0, io.EOF
30
+	}
31
+	if c.bytesPerRead > 0 && n > c.bytesPerRead {
32
+		n = c.bytesPerRead
33
+	}
34
+	copy(data, c.toSend[:n])
35
+	c.toSend = c.toSend[n:]
36
+	return
37
+}
38
+
39
+func (c *MockTerminal) Write(data []byte) (n int, err error) {
40
+	c.received = append(c.received, data...)
41
+	return len(data), nil
42
+}
43
+
44
+func TestClose(t *testing.T) {
45
+	c := &MockTerminal{}
46
+	ss := NewTerminal(c, "> ")
47
+	line, err := ss.ReadLine()
48
+	if line != "" {
49
+		t.Errorf("Expected empty line but got: %s", line)
50
+	}
51
+	if err != io.EOF {
52
+		t.Errorf("Error should have been EOF but got: %s", err)
53
+	}
54
+}
55
+
56
+var keyPressTests = []struct {
57
+	in             string
58
+	line           string
59
+	err            error
60
+	throwAwayLines int
61
+}{
62
+	{
63
+		err: io.EOF,
64
+	},
65
+	{
66
+		in:   "\r",
67
+		line: "",
68
+	},
69
+	{
70
+		in:   "foo\r",
71
+		line: "foo",
72
+	},
73
+	{
74
+		in:   "a\x1b[Cb\r", // right
75
+		line: "ab",
76
+	},
77
+	{
78
+		in:   "a\x1b[Db\r", // left
79
+		line: "ba",
80
+	},
81
+	{
82
+		in:   "a\177b\r", // backspace
83
+		line: "b",
84
+	},
85
+	{
86
+		in: "\x1b[A\r", // up
87
+	},
88
+	{
89
+		in: "\x1b[B\r", // down
90
+	},
91
+	{
92
+		in:   "line\x1b[A\x1b[B\r", // up then down
93
+		line: "line",
94
+	},
95
+	{
96
+		in:             "line1\rline2\x1b[A\r", // recall previous line.
97
+		line:           "line1",
98
+		throwAwayLines: 1,
99
+	},
100
+	{
101
+		// recall two previous lines and append.
102
+		in:             "line1\rline2\rline3\x1b[A\x1b[Axxx\r",
103
+		line:           "line1xxx",
104
+		throwAwayLines: 2,
105
+	},
106
+	{
107
+		// Ctrl-A to move to beginning of line followed by ^K to kill
108
+		// line.
109
+		in:   "a b \001\013\r",
110
+		line: "",
111
+	},
112
+	{
113
+		// Ctrl-A to move to beginning of line, Ctrl-E to move to end,
114
+		// finally ^K to kill nothing.
115
+		in:   "a b \001\005\013\r",
116
+		line: "a b ",
117
+	},
118
+	{
119
+		in:   "\027\r",
120
+		line: "",
121
+	},
122
+	{
123
+		in:   "a\027\r",
124
+		line: "",
125
+	},
126
+	{
127
+		in:   "a \027\r",
128
+		line: "",
129
+	},
130
+	{
131
+		in:   "a b\027\r",
132
+		line: "a ",
133
+	},
134
+	{
135
+		in:   "a b \027\r",
136
+		line: "a ",
137
+	},
138
+	{
139
+		in:   "one two thr\x1b[D\027\r",
140
+		line: "one two r",
141
+	},
142
+	{
143
+		in:   "\013\r",
144
+		line: "",
145
+	},
146
+	{
147
+		in:   "a\013\r",
148
+		line: "a",
149
+	},
150
+	{
151
+		in:   "ab\x1b[D\013\r",
152
+		line: "a",
153
+	},
154
+	{
155
+		in:   "Ξεσκεπάζω\r",
156
+		line: "Ξεσκεπάζω",
157
+	},
158
+	{
159
+		in:             "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace.
160
+		line:           "",
161
+		throwAwayLines: 1,
162
+	},
163
+	{
164
+		in:             "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter.
165
+		line:           "£",
166
+		throwAwayLines: 1,
167
+	},
168
+	{
169
+		// Ctrl-D at the end of the line should be ignored.
170
+		in:   "a\004\r",
171
+		line: "a",
172
+	},
173
+	{
174
+		// a, b, left, Ctrl-D should erase the b.
175
+		in:   "ab\x1b[D\004\r",
176
+		line: "a",
177
+	},
178
+	{
179
+		// a, b, c, d, left, left, ^U should erase to the beginning of
180
+		// the line.
181
+		in:   "abcd\x1b[D\x1b[D\025\r",
182
+		line: "cd",
183
+	},
184
+	{
185
+		// Bracketed paste mode: control sequences should be returned
186
+		// verbatim in paste mode.
187
+		in:   "abc\x1b[200~de\177f\x1b[201~\177\r",
188
+		line: "abcde\177",
189
+	},
190
+	{
191
+		// Enter in bracketed paste mode should still work.
192
+		in:             "abc\x1b[200~d\refg\x1b[201~h\r",
193
+		line:           "efgh",
194
+		throwAwayLines: 1,
195
+	},
196
+	{
197
+		// Lines consisting entirely of pasted data should be indicated as such.
198
+		in:   "\x1b[200~a\r",
199
+		line: "a",
200
+		err:  ErrPasteIndicator,
201
+	},
202
+}
203
+
204
+func TestKeyPresses(t *testing.T) {
205
+	for i, test := range keyPressTests {
206
+		for j := 1; j < len(test.in); j++ {
207
+			c := &MockTerminal{
208
+				toSend:       []byte(test.in),
209
+				bytesPerRead: j,
210
+			}
211
+			ss := NewTerminal(c, "> ")
212
+			for k := 0; k < test.throwAwayLines; k++ {
213
+				_, err := ss.ReadLine()
214
+				if err != nil {
215
+					t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err)
216
+				}
217
+			}
218
+			line, err := ss.ReadLine()
219
+			if line != test.line {
220
+				t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
221
+				break
222
+			}
223
+			if err != test.err {
224
+				t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
225
+				break
226
+			}
227
+		}
228
+	}
229
+}
230
+
231
+func TestPasswordNotSaved(t *testing.T) {
232
+	c := &MockTerminal{
233
+		toSend:       []byte("password\r\x1b[A\r"),
234
+		bytesPerRead: 1,
235
+	}
236
+	ss := NewTerminal(c, "> ")
237
+	pw, _ := ss.ReadPassword("> ")
238
+	if pw != "password" {
239
+		t.Fatalf("failed to read password, got %s", pw)
240
+	}
241
+	line, _ := ss.ReadLine()
242
+	if len(line) > 0 {
243
+		t.Fatalf("password was saved in history")
244
+	}
245
+}
246
+
247
+var setSizeTests = []struct {
248
+	width, height int
249
+}{
250
+	{40, 13},
251
+	{80, 24},
252
+	{132, 43},
253
+}
254
+
255
+func TestTerminalSetSize(t *testing.T) {
256
+	for _, setSize := range setSizeTests {
257
+		c := &MockTerminal{
258
+			toSend:       []byte("password\r\x1b[A\r"),
259
+			bytesPerRead: 1,
260
+		}
261
+		ss := NewTerminal(c, "> ")
262
+		ss.SetSize(setSize.width, setSize.height)
263
+		pw, _ := ss.ReadPassword("Password: ")
264
+		if pw != "password" {
265
+			t.Fatalf("failed to read password, got %s", pw)
266
+		}
267
+		if string(c.received) != "Password: \r\n" {
268
+			t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received)
269
+		}
270
+	}
271
+}
272
+
273
+func TestReadPasswordLineEnd(t *testing.T) {
274
+	var tests = []struct {
275
+		input string
276
+		want  string
277
+	}{
278
+		{"\n", ""},
279
+		{"\r\n", ""},
280
+		{"test\r\n", "test"},
281
+		{"testtesttesttes\n", "testtesttesttes"},
282
+		{"testtesttesttes\r\n", "testtesttesttes"},
283
+		{"testtesttesttesttest\n", "testtesttesttesttest"},
284
+		{"testtesttesttesttest\r\n", "testtesttesttesttest"},
285
+	}
286
+	for _, test := range tests {
287
+		buf := new(bytes.Buffer)
288
+		if _, err := buf.WriteString(test.input); err != nil {
289
+			t.Fatal(err)
290
+		}
291
+
292
+		have, err := readPasswordLine(buf)
293
+		if err != nil {
294
+			t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
295
+			continue
296
+		}
297
+		if string(have) != test.want {
298
+			t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
299
+			continue
300
+		}
301
+
302
+		if _, err = buf.WriteString(test.input); err != nil {
303
+			t.Fatal(err)
304
+		}
305
+		have, err = readPasswordLine(buf)
306
+		if err != nil {
307
+			t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
308
+			continue
309
+		}
310
+		if string(have) != test.want {
311
+			t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
312
+			continue
313
+		}
314
+	}
315
+}
316
+
317
+func TestMakeRawState(t *testing.T) {
318
+	fd := int(os.Stdout.Fd())
319
+	if !IsTerminal(fd) {
320
+		t.Skip("stdout is not a terminal; skipping test")
321
+	}
322
+
323
+	st, err := GetState(fd)
324
+	if err != nil {
325
+		t.Fatalf("failed to get terminal state from GetState: %s", err)
326
+	}
327
+	defer Restore(fd, st)
328
+	raw, err := MakeRaw(fd)
329
+	if err != nil {
330
+		t.Fatalf("failed to get terminal state from MakeRaw: %s", err)
331
+	}
332
+
333
+	if *st != *raw {
334
+		t.Errorf("states do not match; was %v, expected %v", raw, st)
335
+	}
336
+}
337
+
338
+func TestOutputNewlines(t *testing.T) {
339
+	// \n should be changed to \r\n in terminal output.
340
+	buf := new(bytes.Buffer)
341
+	term := NewTerminal(buf, ">")
342
+
343
+	term.Write([]byte("1\n2\n"))
344
+	output := string(buf.Bytes())
345
+	const expected = "1\r\n2\r\n"
346
+
347
+	if output != expected {
348
+		t.Errorf("incorrect output: was %q, expected %q", output, expected)
349
+	}
350
+}

+ 116
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/util.go View File

@@ -0,0 +1,116 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
6
+
7
+// Package terminal provides support functions for dealing with terminals, as
8
+// commonly found on UNIX systems.
9
+//
10
+// Putting a terminal into raw mode is the most common requirement:
11
+//
12
+// 	oldState, err := terminal.MakeRaw(0)
13
+// 	if err != nil {
14
+// 	        panic(err)
15
+// 	}
16
+// 	defer terminal.Restore(0, oldState)
17
+package terminal // import "golang.org/x/crypto/ssh/terminal"
18
+
19
+import (
20
+	"golang.org/x/sys/unix"
21
+)
22
+
23
+// State contains the state of a terminal.
24
+type State struct {
25
+	termios unix.Termios
26
+}
27
+
28
+// IsTerminal returns true if the given file descriptor is a terminal.
29
+func IsTerminal(fd int) bool {
30
+	_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
31
+	return err == nil
32
+}
33
+
34
+// MakeRaw put the terminal connected to the given file descriptor into raw
35
+// mode and returns the previous state of the terminal so that it can be
36
+// restored.
37
+func MakeRaw(fd int) (*State, error) {
38
+	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
39
+	if err != nil {
40
+		return nil, err
41
+	}
42
+
43
+	oldState := State{termios: *termios}
44
+
45
+	// This attempts to replicate the behaviour documented for cfmakeraw in
46
+	// the termios(3) manpage.
47
+	termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
48
+	termios.Oflag &^= unix.OPOST
49
+	termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
50
+	termios.Cflag &^= unix.CSIZE | unix.PARENB
51
+	termios.Cflag |= unix.CS8
52
+	termios.Cc[unix.VMIN] = 1
53
+	termios.Cc[unix.VTIME] = 0
54
+	if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
55
+		return nil, err
56
+	}
57
+
58
+	return &oldState, nil
59
+}
60
+
61
+// GetState returns the current state of a terminal which may be useful to
62
+// restore the terminal after a signal.
63
+func GetState(fd int) (*State, error) {
64
+	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
65
+	if err != nil {
66
+		return nil, err
67
+	}
68
+
69
+	return &State{termios: *termios}, nil
70
+}
71
+
72
+// Restore restores the terminal connected to the given file descriptor to a
73
+// previous state.
74
+func Restore(fd int, state *State) error {
75
+	return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
76
+}
77
+
78
+// GetSize returns the dimensions of the given terminal.
79
+func GetSize(fd int) (width, height int, err error) {
80
+	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
81
+	if err != nil {
82
+		return -1, -1, err
83
+	}
84
+	return int(ws.Col), int(ws.Row), nil
85
+}
86
+
87
+// passwordReader is an io.Reader that reads from a specific file descriptor.
88
+type passwordReader int
89
+
90
+func (r passwordReader) Read(buf []byte) (int, error) {
91
+	return unix.Read(int(r), buf)
92
+}
93
+
94
+// ReadPassword reads a line of input from a terminal without local echo.  This
95
+// is commonly used for inputting passwords and other sensitive data. The slice
96
+// returned does not include the \n.
97
+func ReadPassword(fd int) ([]byte, error) {
98
+	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
99
+	if err != nil {
100
+		return nil, err
101
+	}
102
+
103
+	newState := *termios
104
+	newState.Lflag &^= unix.ECHO
105
+	newState.Lflag |= unix.ICANON | unix.ISIG
106
+	newState.Iflag |= unix.ICRNL
107
+	if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
108
+		return nil, err
109
+	}
110
+
111
+	defer func() {
112
+		unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
113
+	}()
114
+
115
+	return readPasswordLine(passwordReader(fd))
116
+}

+ 12
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/util_bsd.go View File

@@ -0,0 +1,12 @@
1
+// Copyright 2013 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build darwin dragonfly freebsd netbsd openbsd
6
+
7
+package terminal
8
+
9
+import "golang.org/x/sys/unix"
10
+
11
+const ioctlReadTermios = unix.TIOCGETA
12
+const ioctlWriteTermios = unix.TIOCSETA

+ 10
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/util_linux.go View File

@@ -0,0 +1,10 @@
1
+// Copyright 2013 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package terminal
6
+
7
+import "golang.org/x/sys/unix"
8
+
9
+const ioctlReadTermios = unix.TCGETS
10
+const ioctlWriteTermios = unix.TCSETS

+ 58
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/util_plan9.go View File

@@ -0,0 +1,58 @@
1
+// Copyright 2016 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// Package terminal provides support functions for dealing with terminals, as
6
+// commonly found on UNIX systems.
7
+//
8
+// Putting a terminal into raw mode is the most common requirement:
9
+//
10
+// 	oldState, err := terminal.MakeRaw(0)
11
+// 	if err != nil {
12
+// 	        panic(err)
13
+// 	}
14
+// 	defer terminal.Restore(0, oldState)
15
+package terminal
16
+
17
+import (
18
+	"fmt"
19
+	"runtime"
20
+)
21
+
22
+type State struct{}
23
+
24
+// IsTerminal returns true if the given file descriptor is a terminal.
25
+func IsTerminal(fd int) bool {
26
+	return false
27
+}
28
+
29
+// MakeRaw put the terminal connected to the given file descriptor into raw
30
+// mode and returns the previous state of the terminal so that it can be
31
+// restored.
32
+func MakeRaw(fd int) (*State, error) {
33
+	return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
34
+}
35
+
36
+// GetState returns the current state of a terminal which may be useful to
37
+// restore the terminal after a signal.
38
+func GetState(fd int) (*State, error) {
39
+	return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
40
+}
41
+
42
+// Restore restores the terminal connected to the given file descriptor to a
43
+// previous state.
44
+func Restore(fd int, state *State) error {
45
+	return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
46
+}
47
+
48
+// GetSize returns the dimensions of the given terminal.
49
+func GetSize(fd int) (width, height int, err error) {
50
+	return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
51
+}
52
+
53
+// ReadPassword reads a line of input from a terminal without local echo.  This
54
+// is commonly used for inputting passwords and other sensitive data. The slice
55
+// returned does not include the \n.
56
+func ReadPassword(fd int) ([]byte, error) {
57
+	return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
58
+}

+ 128
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/util_solaris.go View File

@@ -0,0 +1,128 @@
1
+// Copyright 2015 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build solaris
6
+
7
+package terminal // import "golang.org/x/crypto/ssh/terminal"
8
+
9
+import (
10
+	"golang.org/x/sys/unix"
11
+	"io"
12
+	"syscall"
13
+)
14
+
15
+// State contains the state of a terminal.
16
+type State struct {
17
+	state *unix.Termios
18
+}
19
+
20
+// IsTerminal returns true if the given file descriptor is a terminal.
21
+func IsTerminal(fd int) bool {
22
+	_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
23
+	return err == nil
24
+}
25
+
26
+// ReadPassword reads a line of input from a terminal without local echo.  This
27
+// is commonly used for inputting passwords and other sensitive data. The slice
28
+// returned does not include the \n.
29
+func ReadPassword(fd int) ([]byte, error) {
30
+	// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
31
+	val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
32
+	if err != nil {
33
+		return nil, err
34
+	}
35
+	oldState := *val
36
+
37
+	newState := oldState
38
+	newState.Lflag &^= syscall.ECHO
39
+	newState.Lflag |= syscall.ICANON | syscall.ISIG
40
+	newState.Iflag |= syscall.ICRNL
41
+	err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
42
+	if err != nil {
43
+		return nil, err
44
+	}
45
+
46
+	defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
47
+
48
+	var buf [16]byte
49
+	var ret []byte
50
+	for {
51
+		n, err := syscall.Read(fd, buf[:])
52
+		if err != nil {
53
+			return nil, err
54
+		}
55
+		if n == 0 {
56
+			if len(ret) == 0 {
57
+				return nil, io.EOF
58
+			}
59
+			break
60
+		}
61
+		if buf[n-1] == '\n' {
62
+			n--
63
+		}
64
+		ret = append(ret, buf[:n]...)
65
+		if n < len(buf) {
66
+			break
67
+		}
68
+	}
69
+
70
+	return ret, nil
71
+}
72
+
73
+// MakeRaw puts the terminal connected to the given file descriptor into raw
74
+// mode and returns the previous state of the terminal so that it can be
75
+// restored.
76
+// see http://cr.illumos.org/~webrev/andy_js/1060/
77
+func MakeRaw(fd int) (*State, error) {
78
+	oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
79
+	if err != nil {
80
+		return nil, err
81
+	}
82
+	oldTermios := *oldTermiosPtr
83
+
84
+	newTermios := oldTermios
85
+	newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
86
+	newTermios.Oflag &^= syscall.OPOST
87
+	newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
88
+	newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
89
+	newTermios.Cflag |= syscall.CS8
90
+	newTermios.Cc[unix.VMIN] = 1
91
+	newTermios.Cc[unix.VTIME] = 0
92
+
93
+	if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
94
+		return nil, err
95
+	}
96
+
97
+	return &State{
98
+		state: oldTermiosPtr,
99
+	}, nil
100
+}
101
+
102
+// Restore restores the terminal connected to the given file descriptor to a
103
+// previous state.
104
+func Restore(fd int, oldState *State) error {
105
+	return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
106
+}
107
+
108
+// GetState returns the current state of a terminal which may be useful to
109
+// restore the terminal after a signal.
110
+func GetState(fd int) (*State, error) {
111
+	oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
112
+	if err != nil {
113
+		return nil, err
114
+	}
115
+
116
+	return &State{
117
+		state: oldTermiosPtr,
118
+	}, nil
119
+}
120
+
121
+// GetSize returns the dimensions of the given terminal.
122
+func GetSize(fd int) (width, height int, err error) {
123
+	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
124
+	if err != nil {
125
+		return 0, 0, err
126
+	}
127
+	return int(ws.Col), int(ws.Row), nil
128
+}

+ 102
- 0
vendor/src/golang.org/x/crypto/ssh/terminal/util_windows.go View File

@@ -0,0 +1,102 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build windows
6
+
7
+// Package terminal provides support functions for dealing with terminals, as
8
+// commonly found on UNIX systems.
9
+//
10
+// Putting a terminal into raw mode is the most common requirement:
11
+//
12
+// 	oldState, err := terminal.MakeRaw(0)
13
+// 	if err != nil {
14
+// 	        panic(err)
15
+// 	}
16
+// 	defer terminal.Restore(0, oldState)
17
+package terminal
18
+
19
+import (
20
+	"golang.org/x/sys/windows"
21
+)
22
+
23
+type State struct {
24
+	mode uint32
25
+}
26
+
27
+// IsTerminal returns true if the given file descriptor is a terminal.
28
+func IsTerminal(fd int) bool {
29
+	var st uint32
30
+	err := windows.GetConsoleMode(windows.Handle(fd), &st)
31
+	return err == nil
32
+}
33
+
34
+// MakeRaw put the terminal connected to the given file descriptor into raw
35
+// mode and returns the previous state of the terminal so that it can be
36
+// restored.
37
+func MakeRaw(fd int) (*State, error) {
38
+	var st uint32
39
+	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
40
+		return nil, err
41
+	}
42
+	raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
43
+	if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
44
+		return nil, err
45
+	}
46
+	return &State{st}, nil
47
+}
48
+
49
+// GetState returns the current state of a terminal which may be useful to
50
+// restore the terminal after a signal.
51
+func GetState(fd int) (*State, error) {
52
+	var st uint32
53
+	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
54
+		return nil, err
55
+	}
56
+	return &State{st}, nil
57
+}
58
+
59
+// Restore restores the terminal connected to the given file descriptor to a
60
+// previous state.
61
+func Restore(fd int, state *State) error {
62
+	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
63
+}
64
+
65
+// GetSize returns the dimensions of the given terminal.
66
+func GetSize(fd int) (width, height int, err error) {
67
+	var info windows.ConsoleScreenBufferInfo
68
+	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
69
+		return 0, 0, err
70
+	}
71
+	return int(info.Size.X), int(info.Size.Y), nil
72
+}
73
+
74
+// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
75
+type passwordReader int
76
+
77
+func (r passwordReader) Read(buf []byte) (int, error) {
78
+	return windows.Read(windows.Handle(r), buf)
79
+}
80
+
81
+// ReadPassword reads a line of input from a terminal without local echo.  This
82
+// is commonly used for inputting passwords and other sensitive data. The slice
83
+// returned does not include the \n.
84
+func ReadPassword(fd int) ([]byte, error) {
85
+	var st uint32
86
+	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
87
+		return nil, err
88
+	}
89
+	old := st
90
+
91
+	st &^= (windows.ENABLE_ECHO_INPUT)
92
+	st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
93
+	if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
94
+		return nil, err
95
+	}
96
+
97
+	defer func() {
98
+		windows.SetConsoleMode(windows.Handle(fd), old)
99
+	}()
100
+
101
+	return readPasswordLine(passwordReader(fd))
102
+}

+ 173
- 0
vendor/src/golang.org/x/sys/unix/README.md View File

@@ -0,0 +1,173 @@
1
+# Building `sys/unix`
2
+
3
+The sys/unix package provides access to the raw system call interface of the
4
+underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
5
+
6
+Porting Go to a new architecture/OS combination or adding syscalls, types, or
7
+constants to an existing architecture/OS pair requires some manual effort;
8
+however, there are tools that automate much of the process.
9
+
10
+## Build Systems
11
+
12
+There are currently two ways we generate the necessary files. We are currently
13
+migrating the build system to use containers so the builds are reproducible.
14
+This is being done on an OS-by-OS basis. Please update this documentation as
15
+components of the build system change.
16
+
17
+### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
18
+
19
+The old build system generates the Go files based on the C header files
20
+present on your system. This means that files
21
+for a given GOOS/GOARCH pair must be generated on a system with that OS and
22
+architecture. This also means that the generated code can differ from system
23
+to system, based on differences in the header files.
24
+
25
+To avoid this, if you are using the old build system, only generate the Go
26
+files on an installation with unmodified header files. It is also important to
27
+keep track of which version of the OS the files were generated from (ex.
28
+Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
29
+and have each OS upgrade correspond to a single change.
30
+
31
+To build the files for your current OS and architecture, make sure GOOS and
32
+GOARCH are set correctly and run `mkall.sh`. This will generate the files for
33
+your specific system. Running `mkall.sh -n` shows the commands that will be run.
34
+
35
+Requirements: bash, perl, go
36
+
37
+### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
38
+
39
+The new build system uses a Docker container to generate the go files directly
40
+from source checkouts of the kernel and various system libraries. This means
41
+that on any platform that supports Docker, all the files using the new build
42
+system can be generated at once, and generated files will not change based on
43
+what the person running the scripts has installed on their computer.
44
+
45
+The OS specific files for the new build system are located in the `${GOOS}`
46
+directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
47
+the kernel or system library updates, modify the Dockerfile at
48
+`${GOOS}/Dockerfile` to checkout the new release of the source.
49
+
50
+To build all the files under the new build system, you must be on an amd64/Linux
51
+system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
52
+then generate all of the files for all of the GOOS/GOARCH pairs in the new build
53
+system. Running `mkall.sh -n` shows the commands that will be run.
54
+
55
+Requirements: bash, perl, go, docker
56
+
57
+## Component files
58
+
59
+This section describes the various files used in the code generation process.
60
+It also contains instructions on how to modify these files to add a new
61
+architecture/OS or to add additional syscalls, types, or constants. Note that
62
+if you are using the new build system, the scripts cannot be called normally.
63
+They must be called from within the docker container.
64
+
65
+### asm files
66
+
67
+The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
68
+call dispatch. There are three entry points:
69
+```
70
+  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
71
+  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
72
+  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
73
+```
74
+The first and second are the standard ones; they differ only in how many
75
+arguments can be passed to the kernel. The third is for low-level use by the
76
+ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
77
+let it know that a system call is running.
78
+
79
+When porting Go to an new architecture/OS, this file must be implemented for
80
+each GOOS/GOARCH pair.
81
+
82
+### mksysnum
83
+
84
+Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
85
+for the old system). This script takes in a list of header files containing the
86
+syscall number declarations and parses them to produce the corresponding list of
87
+Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
88
+constants.
89
+
90
+Adding new syscall numbers is mostly done by running the build on a sufficiently
91
+new installation of the target OS (or updating the source checkouts for the
92
+new build system). However, depending on the OS, you make need to update the
93
+parsing in mksysnum.
94
+
95
+### mksyscall.pl
96
+
97
+The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
98
+hand-written Go files which implement system calls (for unix, the specific OS,
99
+or the specific OS/Architecture pair respectively) that need special handling
100
+and list `//sys` comments giving prototypes for ones that can be generated.
101
+
102
+The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
103
+them into syscalls. This requires the name of the prototype in the comment to
104
+match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
105
+prototype can be exported (capitalized) or not.
106
+
107
+Adding a new syscall often just requires adding a new `//sys` function prototype
108
+with the desired arguments and a capitalized name so it is exported. However, if
109
+you want the interface to the syscall to be different, often one will make an
110
+unexported `//sys` prototype, an then write a custom wrapper in
111
+`syscall_${GOOS}.go`.
112
+
113
+### types files
114
+
115
+For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
116
+`types_${GOOS}.go` on the old system). This file includes standard C headers and
117
+creates Go type aliases to the corresponding C types. The file is then fed
118
+through godef to get the Go compatible definitions. Finally, the generated code
119
+is fed though mkpost.go to format the code correctly and remove any hidden or
120
+private identifiers. This cleaned-up code is written to
121
+`ztypes_${GOOS}_${GOARCH}.go`.
122
+
123
+The hardest part about preparing this file is figuring out which headers to
124
+include and which symbols need to be `#define`d to get the actual data
125
+structures that pass through to the kernel system calls. Some C libraries
126
+preset alternate versions for binary compatibility and translate them on the
127
+way in and out of system calls, but there is almost always a `#define` that can
128
+get the real ones.
129
+See `types_darwin.go` and `linux/types.go` for examples.
130
+
131
+To add a new type, add in the necessary include statement at the top of the
132
+file (if it is not already there) and add in a type alias line. Note that if
133
+your type is significantly different on different architectures, you may need
134
+some `#if/#elif` macros in your include statements.
135
+
136
+### mkerrors.sh
137
+
138
+This script is used to generate the system's various constants. This doesn't
139
+just include the error numbers and error strings, but also the signal numbers
140
+an a wide variety of miscellaneous constants. The constants come from the list
141
+of include files in the `includes_${uname}` variable. A regex then picks out
142
+the desired `#define` statements, and generates the corresponding Go constants.
143
+The error numbers and strings are generated from `#include <errno.h>`, and the
144
+signal numbers and strings are generated from `#include <signal.h>`. All of
145
+these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
146
+`_errors.c`, which prints out all the constants.
147
+
148
+To add a constant, add the header that includes it to the appropriate variable.
149
+Then, edit the regex (if necessary) to match the desired constant. Avoid making
150
+the regex too broad to avoid matching unintended constants.
151
+
152
+
153
+## Generated files
154
+
155
+### `zerror_${GOOS}_${GOARCH}.go`
156
+
157
+A file containing all of the system's generated error numbers, error strings,
158
+signal numbers, and constants. Generated by `mkerrors.sh` (see above).
159
+
160
+### `zsyscall_${GOOS}_${GOARCH}.go`
161
+
162
+A file containing all the generated syscalls for a specific GOOS and GOARCH.
163
+Generated by `mksyscall.pl` (see above).
164
+
165
+### `zsysnum_${GOOS}_${GOARCH}.go`
166
+
167
+A list of numeric constants for all the syscall number of the specific GOOS
168
+and GOARCH. Generated by mksysnum (see above).
169
+
170
+### `ztypes_${GOOS}_${GOARCH}.go`
171
+
172
+A file containing Go types for passing into (or returning from) syscalls.
173
+Generated by godefs and the types file (see above).

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_darwin_386.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System call support for 386, Darwin
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-28
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT	·Syscall9(SB),NOSPLIT,$0-52
23
+	JMP	syscall·Syscall9(SB)
24
+
25
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
26
+	JMP	syscall·RawSyscall(SB)
27
+
28
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
29
+	JMP	syscall·RawSyscall6(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_darwin_amd64.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System call support for AMD64, Darwin
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-56
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-80
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT	·Syscall9(SB),NOSPLIT,$0-104
23
+	JMP	syscall·Syscall9(SB)
24
+
25
+TEXT	·RawSyscall(SB),NOSPLIT,$0-56
26
+	JMP	syscall·RawSyscall(SB)
27
+
28
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-80
29
+	JMP	syscall·RawSyscall6(SB)

+ 30
- 0
vendor/src/golang.org/x/sys/unix/asm_darwin_arm.s View File

@@ -0,0 +1,30 @@
1
+// Copyright 2015 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+// +build arm,darwin
7
+
8
+#include "textflag.h"
9
+
10
+//
11
+// System call support for ARM, Darwin
12
+//
13
+
14
+// Just jump to package syscall's implementation for all these functions.
15
+// The runtime may know about them.
16
+
17
+TEXT	·Syscall(SB),NOSPLIT,$0-28
18
+	B	syscall·Syscall(SB)
19
+
20
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
21
+	B	syscall·Syscall6(SB)
22
+
23
+TEXT	·Syscall9(SB),NOSPLIT,$0-52
24
+	B	syscall·Syscall9(SB)
25
+
26
+TEXT	·RawSyscall(SB),NOSPLIT,$0-28
27
+	B	syscall·RawSyscall(SB)
28
+
29
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
30
+	B	syscall·RawSyscall6(SB)

+ 30
- 0
vendor/src/golang.org/x/sys/unix/asm_darwin_arm64.s View File

@@ -0,0 +1,30 @@
1
+// Copyright 2015 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+// +build arm64,darwin
7
+
8
+#include "textflag.h"
9
+
10
+//
11
+// System call support for AMD64, Darwin
12
+//
13
+
14
+// Just jump to package syscall's implementation for all these functions.
15
+// The runtime may know about them.
16
+
17
+TEXT	·Syscall(SB),NOSPLIT,$0-56
18
+	B	syscall·Syscall(SB)
19
+
20
+TEXT	·Syscall6(SB),NOSPLIT,$0-80
21
+	B	syscall·Syscall6(SB)
22
+
23
+TEXT	·Syscall9(SB),NOSPLIT,$0-104
24
+	B	syscall·Syscall9(SB)
25
+
26
+TEXT	·RawSyscall(SB),NOSPLIT,$0-56
27
+	B	syscall·RawSyscall(SB)
28
+
29
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-80
30
+	B	syscall·RawSyscall6(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_dragonfly_amd64.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System call support for AMD64, DragonFly
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-64
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-88
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT	·Syscall9(SB),NOSPLIT,$0-112
23
+	JMP	syscall·Syscall9(SB)
24
+
25
+TEXT ·RawSyscall(SB),NOSPLIT,$0-64
26
+	JMP	syscall·RawSyscall(SB)
27
+
28
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-88
29
+	JMP	syscall·RawSyscall6(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_freebsd_386.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System call support for 386, FreeBSD
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-28
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT	·Syscall9(SB),NOSPLIT,$0-52
23
+	JMP	syscall·Syscall9(SB)
24
+
25
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
26
+	JMP	syscall·RawSyscall(SB)
27
+
28
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
29
+	JMP	syscall·RawSyscall6(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_freebsd_amd64.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System call support for AMD64, FreeBSD
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-56
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-80
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT	·Syscall9(SB),NOSPLIT,$0-104
23
+	JMP	syscall·Syscall9(SB)
24
+
25
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
26
+	JMP	syscall·RawSyscall(SB)
27
+
28
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-80
29
+	JMP	syscall·RawSyscall6(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_freebsd_arm.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2012 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System call support for ARM, FreeBSD
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-28
17
+	B	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
20
+	B	syscall·Syscall6(SB)
21
+
22
+TEXT	·Syscall9(SB),NOSPLIT,$0-52
23
+	B	syscall·Syscall9(SB)
24
+
25
+TEXT	·RawSyscall(SB),NOSPLIT,$0-28
26
+	B	syscall·RawSyscall(SB)
27
+
28
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
29
+	B	syscall·RawSyscall6(SB)

+ 35
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_386.s View File

@@ -0,0 +1,35 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System calls for 386, Linux
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-28
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
23
+	JMP	syscall·RawSyscall(SB)
24
+
25
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
26
+	JMP	syscall·RawSyscall6(SB)
27
+
28
+TEXT ·socketcall(SB),NOSPLIT,$0-36
29
+	JMP	syscall·socketcall(SB)
30
+
31
+TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
32
+	JMP	syscall·rawsocketcall(SB)
33
+
34
+TEXT ·seek(SB),NOSPLIT,$0-28
35
+	JMP	syscall·seek(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_amd64.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System calls for AMD64, Linux
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-56
17
+	JMP	syscall·Syscall(SB)
18
+
19
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
20
+	JMP	syscall·Syscall6(SB)
21
+
22
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
23
+	JMP	syscall·RawSyscall(SB)
24
+
25
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
26
+	JMP	syscall·RawSyscall6(SB)
27
+
28
+TEXT ·gettimeofday(SB),NOSPLIT,$0-16
29
+	JMP	syscall·gettimeofday(SB)

+ 29
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_arm.s View File

@@ -0,0 +1,29 @@
1
+// Copyright 2009 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build !gccgo
6
+
7
+#include "textflag.h"
8
+
9
+//
10
+// System calls for arm, Linux
11
+//
12
+
13
+// Just jump to package syscall's implementation for all these functions.
14
+// The runtime may know about them.
15
+
16
+TEXT	·Syscall(SB),NOSPLIT,$0-28
17
+	B	syscall·Syscall(SB)
18
+
19
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
20
+	B	syscall·Syscall6(SB)
21
+
22
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
23
+	B	syscall·RawSyscall(SB)
24
+
25
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
26
+	B	syscall·RawSyscall6(SB)
27
+
28
+TEXT ·seek(SB),NOSPLIT,$0-32
29
+	B	syscall·seek(SB)

+ 24
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_arm64.s View File

@@ -0,0 +1,24 @@
1
+// Copyright 2015 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build linux
6
+// +build arm64
7
+// +build !gccgo
8
+
9
+#include "textflag.h"
10
+
11
+// Just jump to package syscall's implementation for all these functions.
12
+// The runtime may know about them.
13
+
14
+TEXT	·Syscall(SB),NOSPLIT,$0-56
15
+	B	syscall·Syscall(SB)
16
+
17
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
18
+	B	syscall·Syscall6(SB)
19
+
20
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
21
+	B	syscall·RawSyscall(SB)
22
+
23
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
24
+	B	syscall·RawSyscall6(SB)

+ 28
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_mips64x.s View File

@@ -0,0 +1,28 @@
1
+// Copyright 2015 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build linux
6
+// +build mips64 mips64le
7
+// +build !gccgo
8
+
9
+#include "textflag.h"
10
+
11
+//
12
+// System calls for mips64, Linux
13
+//
14
+
15
+// Just jump to package syscall's implementation for all these functions.
16
+// The runtime may know about them.
17
+
18
+TEXT	·Syscall(SB),NOSPLIT,$0-56
19
+	JMP	syscall·Syscall(SB)
20
+
21
+TEXT	·Syscall6(SB),NOSPLIT,$0-80
22
+	JMP	syscall·Syscall6(SB)
23
+
24
+TEXT	·RawSyscall(SB),NOSPLIT,$0-56
25
+	JMP	syscall·RawSyscall(SB)
26
+
27
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-80
28
+	JMP	syscall·RawSyscall6(SB)

+ 31
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_mipsx.s View File

@@ -0,0 +1,31 @@
1
+// Copyright 2016 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build linux
6
+// +build mips mipsle
7
+// +build !gccgo
8
+
9
+#include "textflag.h"
10
+
11
+//
12
+// System calls for mips, Linux
13
+//
14
+
15
+// Just jump to package syscall's implementation for all these functions.
16
+// The runtime may know about them.
17
+
18
+TEXT	·Syscall(SB),NOSPLIT,$0-28
19
+	JMP syscall·Syscall(SB)
20
+
21
+TEXT	·Syscall6(SB),NOSPLIT,$0-40
22
+	JMP syscall·Syscall6(SB)
23
+
24
+TEXT	·Syscall9(SB),NOSPLIT,$0-52
25
+	JMP syscall·Syscall9(SB)
26
+
27
+TEXT	·RawSyscall(SB),NOSPLIT,$0-28
28
+	JMP syscall·RawSyscall(SB)
29
+
30
+TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
31
+	JMP syscall·RawSyscall6(SB)

+ 28
- 0
vendor/src/golang.org/x/sys/unix/asm_linux_ppc64x.s View File

@@ -0,0 +1,28 @@
1
+// Copyright 2014 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+// +build linux
6
+// +build ppc64 ppc64le
7
+// +build !gccgo
8
+
9
+#include "textflag.h"
10
+
11
+//
12