mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 05:40:42 +00:00 
			
		
		
		
	Merge pull request #31586 from brendandburns/kubectl
Automatic merge from submit-queue When prompting for passwords, don't echo to the terminal @deads2k @kubernetes/kubectl
This commit is contained in:
		
							
								
								
									
										8
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							| @@ -1369,6 +1369,10 @@ | |||||||
| 			"Comment": "v2.1.0-dev-2-gcb07059", | 			"Comment": "v2.1.0-dev-2-gcb07059", | ||||||
| 			"Rev": "cb07059aed8760ef857a58d37598b9e51c36a9ae" | 			"Rev": "cb07059aed8760ef857a58d37598b9e51c36a9ae" | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"ImportPath": "github.com/howeyc/gopass", | ||||||
|  | 			"Rev": "3ca23474a7c7203e0a0a070fd33508f6efdb9b3d" | ||||||
|  | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/imdario/mergo", | 			"ImportPath": "github.com/imdario/mergo", | ||||||
| 			"Comment": "0.1.3-8-g6633656", | 			"Comment": "0.1.3-8-g6633656", | ||||||
| @@ -2207,6 +2211,10 @@ | |||||||
| 			"ImportPath": "golang.org/x/crypto/ssh", | 			"ImportPath": "golang.org/x/crypto/ssh", | ||||||
| 			"Rev": "1f22c0103821b9390939b6776727195525381532" | 			"Rev": "1f22c0103821b9390939b6776727195525381532" | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"ImportPath": "golang.org/x/crypto/ssh/terminal", | ||||||
|  | 			"Rev": "1f22c0103821b9390939b6776727195525381532" | ||||||
|  | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "golang.org/x/exp/inotify", | 			"ImportPath": "golang.org/x/exp/inotify", | ||||||
| 			"Rev": "292a51b8d262487dab23a588950e8052d63d9113" | 			"Rev": "292a51b8d262487dab23a588950e8052d63d9113" | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								Godeps/LICENSES
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										58
									
								
								Godeps/LICENSES
									
									
									
										generated
									
									
									
								
							| @@ -46485,6 +46485,29 @@ Apache License | |||||||
| ================================================================================ | ================================================================================ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | ================================================================================ | ||||||
|  | = vendor/github.com/howeyc/gopass licensed under: = | ||||||
|  | 
 | ||||||
|  | ISC License | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2012 Chris Howey | ||||||
|  | 
 | ||||||
|  | Permission to use, copy, modify, and distribute this software for any | ||||||
|  | purpose with or without fee is hereby granted, provided that the above | ||||||
|  | copyright notice and this permission notice appear in all copies. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  | 
 | ||||||
|  | = vendor/github.com/howeyc/gopass/LICENSE.txt b24abd09a925eaf2b6de5a9b4c9bea07  - | ||||||
|  | ================================================================================ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ================================================================================ | ================================================================================ | ||||||
| = vendor/github.com/imdario/mergo licensed under: = | = vendor/github.com/imdario/mergo licensed under: = | ||||||
| 
 | 
 | ||||||
| @@ -68402,6 +68425,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| ================================================================================ | ================================================================================ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | ================================================================================ | ||||||
|  | = vendor/golang.org/x/crypto/ssh/terminal licensed under: = | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2009 The Go Authors. All rights reserved. | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are | ||||||
|  | met: | ||||||
|  | 
 | ||||||
|  |    * Redistributions of source code must retain the above copyright | ||||||
|  | notice, this list of conditions and the following disclaimer. | ||||||
|  |    * Redistributions in binary form must reproduce the above | ||||||
|  | copyright notice, this list of conditions and the following disclaimer | ||||||
|  | in the documentation and/or other materials provided with the | ||||||
|  | distribution. | ||||||
|  |    * Neither the name of Google Inc. nor the names of its | ||||||
|  | contributors may be used to endorse or promote products derived from | ||||||
|  | this software without specific prior written permission. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | 
 | ||||||
|  | = vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707  - | ||||||
|  | ================================================================================ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ================================================================================ | ================================================================================ | ||||||
| = vendor/golang.org/x/exp/inotify licensed under: = | = vendor/golang.org/x/exp/inotify licensed under: = | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ import ( | |||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/howeyc/gopass" | ||||||
| 	clientauth "k8s.io/kubernetes/pkg/client/unversioned/auth" | 	clientauth "k8s.io/kubernetes/pkg/client/unversioned/auth" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -46,10 +47,13 @@ type PromptingAuthLoader struct { | |||||||
|  |  | ||||||
| // LoadAuth parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. | // LoadAuth parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. | ||||||
| func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { | func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { | ||||||
| 	var auth clientauth.Info |  | ||||||
| 	// Prompt for user/pass and write a file if none exists. | 	// Prompt for user/pass and write a file if none exists. | ||||||
| 	if _, err := os.Stat(path); os.IsNotExist(err) { | 	if _, err := os.Stat(path); os.IsNotExist(err) { | ||||||
| 		auth = *a.Prompt() | 		authPtr, err := a.Prompt() | ||||||
|  | 		auth := *authPtr | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
| 		data, err := json.Marshal(auth) | 		data, err := json.Marshal(auth) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return &auth, err | 			return &auth, err | ||||||
| @@ -65,19 +69,30 @@ func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // Prompt pulls the user and password from a reader | // Prompt pulls the user and password from a reader | ||||||
| func (a *PromptingAuthLoader) Prompt() *clientauth.Info { | func (a *PromptingAuthLoader) Prompt() (*clientauth.Info, error) { | ||||||
|  | 	var err error | ||||||
| 	auth := &clientauth.Info{} | 	auth := &clientauth.Info{} | ||||||
| 	auth.User = promptForString("Username", a.reader) | 	auth.User, err = promptForString("Username", a.reader, true) | ||||||
| 	auth.Password = promptForString("Password", a.reader) | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
| 	return auth | 	} | ||||||
|  | 	auth.Password, err = promptForString("Password", nil, false) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return auth, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func promptForString(field string, r io.Reader) string { | func promptForString(field string, r io.Reader, show bool) (result string, err error) { | ||||||
| 	fmt.Printf("Please enter %s: ", field) | 	fmt.Printf("Please enter %s: ", field) | ||||||
| 	var result string | 	if show { | ||||||
| 	fmt.Fscan(r, &result) | 		_, err = fmt.Fscan(r, &result) | ||||||
| 	return result | 	} else { | ||||||
|  | 		var data []byte | ||||||
|  | 		data, err = gopass.GetPasswdMasked() | ||||||
|  | 		result = string(data) | ||||||
|  | 	} | ||||||
|  | 	return result, err | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewPromptingAuthLoader is an AuthLoader that parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. | // NewPromptingAuthLoader is an AuthLoader that parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. | ||||||
|   | |||||||
| @@ -195,8 +195,10 @@ func getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fa | |||||||
| 	// if there still isn't enough information to authenticate the user, try prompting | 	// if there still isn't enough information to authenticate the user, try prompting | ||||||
| 	if !canIdentifyUser(*mergedConfig) && (fallbackReader != nil) { | 	if !canIdentifyUser(*mergedConfig) && (fallbackReader != nil) { | ||||||
| 		prompter := NewPromptingAuthLoader(fallbackReader) | 		prompter := NewPromptingAuthLoader(fallbackReader) | ||||||
| 		promptedAuthInfo := prompter.Prompt() | 		promptedAuthInfo, err := prompter.Prompt() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
| 		promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo) | 		promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo) | ||||||
| 		previouslyMergedConfig := mergedConfig | 		previouslyMergedConfig := mergedConfig | ||||||
| 		mergedConfig = &restclient.Config{} | 		mergedConfig = &restclient.Config{} | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								vendor/github.com/howeyc/gopass/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/howeyc/gopass/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | language: go | ||||||
|  |  | ||||||
|  | os: | ||||||
|  |   - linux | ||||||
|  |   - osx | ||||||
|  |  | ||||||
|  | go: | ||||||
|  |   - 1.3 | ||||||
|  |   - 1.4 | ||||||
|  |   - 1.5 | ||||||
|  |   - tip | ||||||
							
								
								
									
										15
									
								
								vendor/github.com/howeyc/gopass/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/howeyc/gopass/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | ISC License | ||||||
|  |  | ||||||
|  | Copyright (c) 2012 Chris Howey | ||||||
|  |  | ||||||
|  | Permission to use, copy, modify, and distribute this software for any | ||||||
|  | purpose with or without fee is hereby granted, provided that the above | ||||||
|  | copyright notice and this permission notice appear in all copies. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
							
								
								
									
										384
									
								
								vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								vendor/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,384 @@ | |||||||
|  | Unless otherwise noted, all files in this distribution are released | ||||||
|  | under the Common Development and Distribution License (CDDL). | ||||||
|  | Exceptions are noted within the associated source files. | ||||||
|  |  | ||||||
|  | -------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  |  | ||||||
|  | COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0 | ||||||
|  |  | ||||||
|  | 1. Definitions. | ||||||
|  |  | ||||||
|  |     1.1. "Contributor" means each individual or entity that creates | ||||||
|  |          or contributes to the creation of Modifications. | ||||||
|  |  | ||||||
|  |     1.2. "Contributor Version" means the combination of the Original | ||||||
|  |          Software, prior Modifications used by a Contributor (if any), | ||||||
|  |          and the Modifications made by that particular Contributor. | ||||||
|  |  | ||||||
|  |     1.3. "Covered Software" means (a) the Original Software, or (b) | ||||||
|  |          Modifications, or (c) the combination of files containing | ||||||
|  |          Original Software with files containing Modifications, in | ||||||
|  |          each case including portions thereof. | ||||||
|  |  | ||||||
|  |     1.4. "Executable" means the Covered Software in any form other | ||||||
|  |          than Source Code. | ||||||
|  |  | ||||||
|  |     1.5. "Initial Developer" means the individual or entity that first | ||||||
|  |          makes Original Software available under this License. | ||||||
|  |  | ||||||
|  |     1.6. "Larger Work" means a work which combines Covered Software or | ||||||
|  |          portions thereof with code not governed by the terms of this | ||||||
|  |          License. | ||||||
|  |  | ||||||
|  |     1.7. "License" means this document. | ||||||
|  |  | ||||||
|  |     1.8. "Licensable" means having the right to grant, to the maximum | ||||||
|  |          extent possible, whether at the time of the initial grant or | ||||||
|  |          subsequently acquired, any and all of the rights conveyed | ||||||
|  |          herein. | ||||||
|  |  | ||||||
|  |     1.9. "Modifications" means the Source Code and Executable form of | ||||||
|  |          any of the following: | ||||||
|  |  | ||||||
|  |         A. Any file that results from an addition to, deletion from or | ||||||
|  |            modification of the contents of a file containing Original | ||||||
|  |            Software or previous Modifications; | ||||||
|  |  | ||||||
|  |         B. Any new file that contains any part of the Original | ||||||
|  |            Software or previous Modifications; or | ||||||
|  |  | ||||||
|  |         C. Any new file that is contributed or otherwise made | ||||||
|  |            available under the terms of this License. | ||||||
|  |  | ||||||
|  |     1.10. "Original Software" means the Source Code and Executable | ||||||
|  |           form of computer software code that is originally released | ||||||
|  |           under this License. | ||||||
|  |  | ||||||
|  |     1.11. "Patent Claims" means any patent claim(s), now owned or | ||||||
|  |           hereafter acquired, including without limitation, method, | ||||||
|  |           process, and apparatus claims, in any patent Licensable by | ||||||
|  |           grantor. | ||||||
|  |  | ||||||
|  |     1.12. "Source Code" means (a) the common form of computer software | ||||||
|  |           code in which modifications are made and (b) associated | ||||||
|  |           documentation included in or with such code. | ||||||
|  |  | ||||||
|  |     1.13. "You" (or "Your") means an individual or a legal entity | ||||||
|  |           exercising rights under, and complying with all of the terms | ||||||
|  |           of, this License.  For legal entities, "You" includes any | ||||||
|  |           entity which controls, is controlled by, or is under common | ||||||
|  |           control with You.  For purposes of this definition, | ||||||
|  |           "control" means (a) the power, direct or indirect, to cause | ||||||
|  |           the direction or management of such entity, whether by | ||||||
|  |           contract or otherwise, or (b) ownership of more than fifty | ||||||
|  |           percent (50%) of the outstanding shares or beneficial | ||||||
|  |           ownership of such entity. | ||||||
|  |  | ||||||
|  | 2. License Grants. | ||||||
|  |  | ||||||
|  |     2.1. The Initial Developer Grant. | ||||||
|  |  | ||||||
|  |     Conditioned upon Your compliance with Section 3.1 below and | ||||||
|  |     subject to third party intellectual property claims, the Initial | ||||||
|  |     Developer hereby grants You a world-wide, royalty-free, | ||||||
|  |     non-exclusive license: | ||||||
|  |  | ||||||
|  |         (a) under intellectual property rights (other than patent or | ||||||
|  |             trademark) Licensable by Initial Developer, to use, | ||||||
|  |             reproduce, modify, display, perform, sublicense and | ||||||
|  |             distribute the Original Software (or portions thereof), | ||||||
|  |             with or without Modifications, and/or as part of a Larger | ||||||
|  |             Work; and | ||||||
|  |  | ||||||
|  |         (b) under Patent Claims infringed by the making, using or | ||||||
|  |             selling of Original Software, to make, have made, use, | ||||||
|  |             practice, sell, and offer for sale, and/or otherwise | ||||||
|  |             dispose of the Original Software (or portions thereof). | ||||||
|  |  | ||||||
|  |         (c) The licenses granted in Sections 2.1(a) and (b) are | ||||||
|  |             effective on the date Initial Developer first distributes | ||||||
|  |             or otherwise makes the Original Software available to a | ||||||
|  |             third party under the terms of this License. | ||||||
|  |  | ||||||
|  |         (d) Notwithstanding Section 2.1(b) above, no patent license is | ||||||
|  |             granted: (1) for code that You delete from the Original | ||||||
|  |             Software, or (2) for infringements caused by: (i) the | ||||||
|  |             modification of the Original Software, or (ii) the | ||||||
|  |             combination of the Original Software with other software | ||||||
|  |             or devices. | ||||||
|  |  | ||||||
|  |     2.2. Contributor Grant. | ||||||
|  |  | ||||||
|  |     Conditioned upon Your compliance with Section 3.1 below and | ||||||
|  |     subject to third party intellectual property claims, each | ||||||
|  |     Contributor hereby grants You a world-wide, royalty-free, | ||||||
|  |     non-exclusive license: | ||||||
|  |  | ||||||
|  |         (a) under intellectual property rights (other than patent or | ||||||
|  |             trademark) Licensable by Contributor to use, reproduce, | ||||||
|  |             modify, display, perform, sublicense and distribute the | ||||||
|  |             Modifications created by such Contributor (or portions | ||||||
|  |             thereof), either on an unmodified basis, with other | ||||||
|  |             Modifications, as Covered Software and/or as part of a | ||||||
|  |             Larger Work; and | ||||||
|  |  | ||||||
|  |         (b) under Patent Claims infringed by the making, using, or | ||||||
|  |             selling of Modifications made by that Contributor either | ||||||
|  |             alone and/or in combination with its Contributor Version | ||||||
|  |             (or portions of such combination), to make, use, sell, | ||||||
|  |             offer for sale, have made, and/or otherwise dispose of: | ||||||
|  |             (1) Modifications made by that Contributor (or portions | ||||||
|  |             thereof); and (2) the combination of Modifications made by | ||||||
|  |             that Contributor with its Contributor Version (or portions | ||||||
|  |             of such combination). | ||||||
|  |  | ||||||
|  |         (c) The licenses granted in Sections 2.2(a) and 2.2(b) are | ||||||
|  |             effective on the date Contributor first distributes or | ||||||
|  |             otherwise makes the Modifications available to a third | ||||||
|  |             party. | ||||||
|  |  | ||||||
|  |         (d) Notwithstanding Section 2.2(b) above, no patent license is | ||||||
|  |             granted: (1) for any code that Contributor has deleted | ||||||
|  |             from the Contributor Version; (2) for infringements caused | ||||||
|  |             by: (i) third party modifications of Contributor Version, | ||||||
|  |             or (ii) the combination of Modifications made by that | ||||||
|  |             Contributor with other software (except as part of the | ||||||
|  |             Contributor Version) or other devices; or (3) under Patent | ||||||
|  |             Claims infringed by Covered Software in the absence of | ||||||
|  |             Modifications made by that Contributor. | ||||||
|  |  | ||||||
|  | 3. Distribution Obligations. | ||||||
|  |  | ||||||
|  |     3.1. Availability of Source Code. | ||||||
|  |  | ||||||
|  |     Any Covered Software that You distribute or otherwise make | ||||||
|  |     available in Executable form must also be made available in Source | ||||||
|  |     Code form and that Source Code form must be distributed only under | ||||||
|  |     the terms of this License.  You must include a copy of this | ||||||
|  |     License with every copy of the Source Code form of the Covered | ||||||
|  |     Software You distribute or otherwise make available.  You must | ||||||
|  |     inform recipients of any such Covered Software in Executable form | ||||||
|  |     as to how they can obtain such Covered Software in Source Code | ||||||
|  |     form in a reasonable manner on or through a medium customarily | ||||||
|  |     used for software exchange. | ||||||
|  |  | ||||||
|  |     3.2. Modifications. | ||||||
|  |  | ||||||
|  |     The Modifications that You create or to which You contribute are | ||||||
|  |     governed by the terms of this License.  You represent that You | ||||||
|  |     believe Your Modifications are Your original creation(s) and/or | ||||||
|  |     You have sufficient rights to grant the rights conveyed by this | ||||||
|  |     License. | ||||||
|  |  | ||||||
|  |     3.3. Required Notices. | ||||||
|  |  | ||||||
|  |     You must include a notice in each of Your Modifications that | ||||||
|  |     identifies You as the Contributor of the Modification.  You may | ||||||
|  |     not remove or alter any copyright, patent or trademark notices | ||||||
|  |     contained within the Covered Software, or any notices of licensing | ||||||
|  |     or any descriptive text giving attribution to any Contributor or | ||||||
|  |     the Initial Developer. | ||||||
|  |  | ||||||
|  |     3.4. Application of Additional Terms. | ||||||
|  |  | ||||||
|  |     You may not offer or impose any terms on any Covered Software in | ||||||
|  |     Source Code form that alters or restricts the applicable version | ||||||
|  |     of this License or the recipients' rights hereunder.  You may | ||||||
|  |     choose to offer, and to charge a fee for, warranty, support, | ||||||
|  |     indemnity or liability obligations to one or more recipients of | ||||||
|  |     Covered Software.  However, you may do so only on Your own behalf, | ||||||
|  |     and not on behalf of the Initial Developer or any Contributor. | ||||||
|  |     You must make it absolutely clear that any such warranty, support, | ||||||
|  |     indemnity or liability obligation is offered by You alone, and You | ||||||
|  |     hereby agree to indemnify the Initial Developer and every | ||||||
|  |     Contributor for any liability incurred by the Initial Developer or | ||||||
|  |     such Contributor as a result of warranty, support, indemnity or | ||||||
|  |     liability terms You offer. | ||||||
|  |  | ||||||
|  |     3.5. Distribution of Executable Versions. | ||||||
|  |  | ||||||
|  |     You may distribute the Executable form of the Covered Software | ||||||
|  |     under the terms of this License or under the terms of a license of | ||||||
|  |     Your choice, which may contain terms different from this License, | ||||||
|  |     provided that You are in compliance with the terms of this License | ||||||
|  |     and that the license for the Executable form does not attempt to | ||||||
|  |     limit or alter the recipient's rights in the Source Code form from | ||||||
|  |     the rights set forth in this License.  If You distribute the | ||||||
|  |     Covered Software in Executable form under a different license, You | ||||||
|  |     must make it absolutely clear that any terms which differ from | ||||||
|  |     this License are offered by You alone, not by the Initial | ||||||
|  |     Developer or Contributor.  You hereby agree to indemnify the | ||||||
|  |     Initial Developer and every Contributor for any liability incurred | ||||||
|  |     by the Initial Developer or such Contributor as a result of any | ||||||
|  |     such terms You offer. | ||||||
|  |  | ||||||
|  |     3.6. Larger Works. | ||||||
|  |  | ||||||
|  |     You may create a Larger Work by combining Covered Software with | ||||||
|  |     other code not governed by the terms of this License and | ||||||
|  |     distribute the Larger Work as a single product.  In such a case, | ||||||
|  |     You must make sure the requirements of this License are fulfilled | ||||||
|  |     for the Covered Software. | ||||||
|  |  | ||||||
|  | 4. Versions of the License. | ||||||
|  |  | ||||||
|  |     4.1. New Versions. | ||||||
|  |  | ||||||
|  |     Sun Microsystems, Inc. is the initial license steward and may | ||||||
|  |     publish revised and/or new versions of this License from time to | ||||||
|  |     time.  Each version will be given a distinguishing version number. | ||||||
|  |     Except as provided in Section 4.3, no one other than the license | ||||||
|  |     steward has the right to modify this License. | ||||||
|  |  | ||||||
|  |     4.2. Effect of New Versions. | ||||||
|  |  | ||||||
|  |     You may always continue to use, distribute or otherwise make the | ||||||
|  |     Covered Software available under the terms of the version of the | ||||||
|  |     License under which You originally received the Covered Software. | ||||||
|  |     If the Initial Developer includes a notice in the Original | ||||||
|  |     Software prohibiting it from being distributed or otherwise made | ||||||
|  |     available under any subsequent version of the License, You must | ||||||
|  |     distribute and make the Covered Software available under the terms | ||||||
|  |     of the version of the License under which You originally received | ||||||
|  |     the Covered Software.  Otherwise, You may also choose to use, | ||||||
|  |     distribute or otherwise make the Covered Software available under | ||||||
|  |     the terms of any subsequent version of the License published by | ||||||
|  |     the license steward. | ||||||
|  |  | ||||||
|  |     4.3. Modified Versions. | ||||||
|  |  | ||||||
|  |     When You are an Initial Developer and You want to create a new | ||||||
|  |     license for Your Original Software, You may create and use a | ||||||
|  |     modified version of this License if You: (a) rename the license | ||||||
|  |     and remove any references to the name of the license steward | ||||||
|  |     (except to note that the license differs from this License); and | ||||||
|  |     (b) otherwise make it clear that the license contains terms which | ||||||
|  |     differ from this License. | ||||||
|  |  | ||||||
|  | 5. DISCLAIMER OF WARRANTY. | ||||||
|  |  | ||||||
|  |     COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" | ||||||
|  |     BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, | ||||||
|  |     INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED | ||||||
|  |     SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR | ||||||
|  |     PURPOSE OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND | ||||||
|  |     PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU.  SHOULD ANY | ||||||
|  |     COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE | ||||||
|  |     INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY | ||||||
|  |     NECESSARY SERVICING, REPAIR OR CORRECTION.  THIS DISCLAIMER OF | ||||||
|  |     WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.  NO USE OF | ||||||
|  |     ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS | ||||||
|  |     DISCLAIMER. | ||||||
|  |  | ||||||
|  | 6. TERMINATION. | ||||||
|  |  | ||||||
|  |     6.1. This License and the rights granted hereunder will terminate | ||||||
|  |     automatically if You fail to comply with terms herein and fail to | ||||||
|  |     cure such breach within 30 days of becoming aware of the breach. | ||||||
|  |     Provisions which, by their nature, must remain in effect beyond | ||||||
|  |     the termination of this License shall survive. | ||||||
|  |  | ||||||
|  |     6.2. If You assert a patent infringement claim (excluding | ||||||
|  |     declaratory judgment actions) against Initial Developer or a | ||||||
|  |     Contributor (the Initial Developer or Contributor against whom You | ||||||
|  |     assert such claim is referred to as "Participant") alleging that | ||||||
|  |     the Participant Software (meaning the Contributor Version where | ||||||
|  |     the Participant is a Contributor or the Original Software where | ||||||
|  |     the Participant is the Initial Developer) directly or indirectly | ||||||
|  |     infringes any patent, then any and all rights granted directly or | ||||||
|  |     indirectly to You by such Participant, the Initial Developer (if | ||||||
|  |     the Initial Developer is not the Participant) and all Contributors | ||||||
|  |     under Sections 2.1 and/or 2.2 of this License shall, upon 60 days | ||||||
|  |     notice from Participant terminate prospectively and automatically | ||||||
|  |     at the expiration of such 60 day notice period, unless if within | ||||||
|  |     such 60 day period You withdraw Your claim with respect to the | ||||||
|  |     Participant Software against such Participant either unilaterally | ||||||
|  |     or pursuant to a written agreement with Participant. | ||||||
|  |  | ||||||
|  |     6.3. In the event of termination under Sections 6.1 or 6.2 above, | ||||||
|  |     all end user licenses that have been validly granted by You or any | ||||||
|  |     distributor hereunder prior to termination (excluding licenses | ||||||
|  |     granted to You by any distributor) shall survive termination. | ||||||
|  |  | ||||||
|  | 7. LIMITATION OF LIABILITY. | ||||||
|  |  | ||||||
|  |     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT | ||||||
|  |     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE | ||||||
|  |     INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF | ||||||
|  |     COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE | ||||||
|  |     LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR | ||||||
|  |     CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT | ||||||
|  |     LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK | ||||||
|  |     STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER | ||||||
|  |     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN | ||||||
|  |     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES.  THIS LIMITATION OF | ||||||
|  |     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL | ||||||
|  |     INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT | ||||||
|  |     APPLICABLE LAW PROHIBITS SUCH LIMITATION.  SOME JURISDICTIONS DO | ||||||
|  |     NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR | ||||||
|  |     CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT | ||||||
|  |     APPLY TO YOU. | ||||||
|  |  | ||||||
|  | 8. U.S. GOVERNMENT END USERS. | ||||||
|  |  | ||||||
|  |     The Covered Software is a "commercial item," as that term is | ||||||
|  |     defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial | ||||||
|  |     computer software" (as that term is defined at 48 | ||||||
|  |     C.F.R. 252.227-7014(a)(1)) and "commercial computer software | ||||||
|  |     documentation" as such terms are used in 48 C.F.R. 12.212 | ||||||
|  |     (Sept. 1995).  Consistent with 48 C.F.R. 12.212 and 48 | ||||||
|  |     C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all | ||||||
|  |     U.S. Government End Users acquire Covered Software with only those | ||||||
|  |     rights set forth herein.  This U.S. Government Rights clause is in | ||||||
|  |     lieu of, and supersedes, any other FAR, DFAR, or other clause or | ||||||
|  |     provision that addresses Government rights in computer software | ||||||
|  |     under this License. | ||||||
|  |  | ||||||
|  | 9. MISCELLANEOUS. | ||||||
|  |  | ||||||
|  |     This License represents the complete agreement concerning subject | ||||||
|  |     matter hereof.  If any provision of this License is held to be | ||||||
|  |     unenforceable, such provision shall be reformed only to the extent | ||||||
|  |     necessary to make it enforceable.  This License shall be governed | ||||||
|  |     by the law of the jurisdiction specified in a notice contained | ||||||
|  |     within the Original Software (except to the extent applicable law, | ||||||
|  |     if any, provides otherwise), excluding such jurisdiction's | ||||||
|  |     conflict-of-law provisions.  Any litigation relating to this | ||||||
|  |     License shall be subject to the jurisdiction of the courts located | ||||||
|  |     in the jurisdiction and venue specified in a notice contained | ||||||
|  |     within the Original Software, with the losing party responsible | ||||||
|  |     for costs, including, without limitation, court costs and | ||||||
|  |     reasonable attorneys' fees and expenses.  The application of the | ||||||
|  |     United Nations Convention on Contracts for the International Sale | ||||||
|  |     of Goods is expressly excluded.  Any law or regulation which | ||||||
|  |     provides that the language of a contract shall be construed | ||||||
|  |     against the drafter shall not apply to this License.  You agree | ||||||
|  |     that You alone are responsible for compliance with the United | ||||||
|  |     States export administration regulations (and the export control | ||||||
|  |     laws and regulation of any other countries) when You use, | ||||||
|  |     distribute or otherwise make available any Covered Software. | ||||||
|  |  | ||||||
|  | 10. RESPONSIBILITY FOR CLAIMS. | ||||||
|  |  | ||||||
|  |     As between Initial Developer and the Contributors, each party is | ||||||
|  |     responsible for claims and damages arising, directly or | ||||||
|  |     indirectly, out of its utilization of rights under this License | ||||||
|  |     and You agree to work with Initial Developer and Contributors to | ||||||
|  |     distribute such responsibility on an equitable basis.  Nothing | ||||||
|  |     herein is intended or shall be deemed to constitute any admission | ||||||
|  |     of liability. | ||||||
|  |  | ||||||
|  | -------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND | ||||||
|  | DISTRIBUTION LICENSE (CDDL) | ||||||
|  |  | ||||||
|  | For Covered Software in this distribution, this License shall | ||||||
|  | be governed by the laws of the State of California (excluding | ||||||
|  | conflict-of-law provisions). | ||||||
|  |  | ||||||
|  | Any litigation relating to this License shall be subject to the | ||||||
|  | jurisdiction of the Federal Courts of the Northern District of | ||||||
|  | California and the state courts of the State of California, with | ||||||
|  | venue lying in Santa Clara County, California. | ||||||
							
								
								
									
										27
									
								
								vendor/github.com/howeyc/gopass/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/howeyc/gopass/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | # getpasswd in Go [](https://godoc.org/github.com/howeyc/gopass) [](http://travis-ci.org/howeyc/gopass) | ||||||
|  |  | ||||||
|  | Retrieve password from user terminal or piped input without echo. | ||||||
|  |  | ||||||
|  | Verified on BSD, Linux, and Windows. | ||||||
|  |  | ||||||
|  | Example: | ||||||
|  | ```go | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  | import "github.com/howeyc/gopass" | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	fmt.Printf("Password: ") | ||||||
|  |  | ||||||
|  | 	// Silent. For printing *'s use gopass.GetPasswdMasked() | ||||||
|  | 	pass, err := gopass.GetPasswd() | ||||||
|  | 	if err != nil { | ||||||
|  | 		// Handle gopass.ErrInterrupted or getch() read error | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Do something with pass | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Caution: Multi-byte characters not supported! | ||||||
							
								
								
									
										91
									
								
								vendor/github.com/howeyc/gopass/pass.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/howeyc/gopass/pass.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | package gopass | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var defaultGetCh = func() (byte, error) { | ||||||
|  | 	buf := make([]byte, 1) | ||||||
|  | 	if n, err := os.Stdin.Read(buf); n == 0 || err != nil { | ||||||
|  | 		if err != nil { | ||||||
|  | 			return 0, err | ||||||
|  | 		} | ||||||
|  | 		return 0, io.EOF | ||||||
|  | 	} | ||||||
|  | 	return buf[0], nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	maxLength            = 512 | ||||||
|  | 	ErrInterrupted       = errors.New("interrupted") | ||||||
|  | 	ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength) | ||||||
|  |  | ||||||
|  | 	// Provide variable so that tests can provide a mock implementation. | ||||||
|  | 	getch = defaultGetCh | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // getPasswd returns the input read from terminal. | ||||||
|  | // If masked is true, typing will be matched by asterisks on the screen. | ||||||
|  | // Otherwise, typing will echo nothing. | ||||||
|  | func getPasswd(masked bool) ([]byte, error) { | ||||||
|  | 	var err error | ||||||
|  | 	var pass, bs, mask []byte | ||||||
|  | 	if masked { | ||||||
|  | 		bs = []byte("\b \b") | ||||||
|  | 		mask = []byte("*") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if isTerminal(os.Stdin.Fd()) { | ||||||
|  | 		if oldState, err := makeRaw(os.Stdin.Fd()); err != nil { | ||||||
|  | 			return pass, err | ||||||
|  | 		} else { | ||||||
|  | 			defer restore(os.Stdin.Fd(), oldState) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Track total bytes read, not just bytes in the password.  This ensures any | ||||||
|  | 	// errors that might flood the console with nil or -1 bytes infinitely are | ||||||
|  | 	// capped. | ||||||
|  | 	var counter int | ||||||
|  | 	for counter = 0; counter <= maxLength; counter++ { | ||||||
|  | 		if v, e := getch(); e != nil { | ||||||
|  | 			err = e | ||||||
|  | 			break | ||||||
|  | 		} else if v == 127 || v == 8 { | ||||||
|  | 			if l := len(pass); l > 0 { | ||||||
|  | 				pass = pass[:l-1] | ||||||
|  | 				fmt.Print(string(bs)) | ||||||
|  | 			} | ||||||
|  | 		} else if v == 13 || v == 10 { | ||||||
|  | 			break | ||||||
|  | 		} else if v == 3 { | ||||||
|  | 			err = ErrInterrupted | ||||||
|  | 			break | ||||||
|  | 		} else if v != 0 { | ||||||
|  | 			pass = append(pass, v) | ||||||
|  | 			fmt.Print(string(mask)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if counter > maxLength { | ||||||
|  | 		err = ErrMaxLengthExceeded | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Println() | ||||||
|  | 	return pass, err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetPasswd returns the password read from the terminal without echoing input. | ||||||
|  | // The returned byte array does not include end-of-line characters. | ||||||
|  | func GetPasswd() ([]byte, error) { | ||||||
|  | 	return getPasswd(false) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetPasswdMasked returns the password read from the terminal, echoing asterisks. | ||||||
|  | // The returned byte array does not include end-of-line characters. | ||||||
|  | func GetPasswdMasked() ([]byte, error) { | ||||||
|  | 	return getPasswd(true) | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								vendor/github.com/howeyc/gopass/terminal.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/howeyc/gopass/terminal.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // +build !solaris | ||||||
|  |  | ||||||
|  | package gopass | ||||||
|  |  | ||||||
|  | import "golang.org/x/crypto/ssh/terminal" | ||||||
|  |  | ||||||
|  | type terminalState struct { | ||||||
|  | 	state *terminal.State | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func isTerminal(fd uintptr) bool { | ||||||
|  | 	return terminal.IsTerminal(int(fd)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func makeRaw(fd uintptr) (*terminalState, error) { | ||||||
|  | 	state, err := terminal.MakeRaw(int(fd)) | ||||||
|  |  | ||||||
|  | 	return &terminalState{ | ||||||
|  | 		state: state, | ||||||
|  | 	}, err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func restore(fd uintptr, oldState *terminalState) error { | ||||||
|  | 	return terminal.Restore(int(fd), oldState.state) | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								vendor/github.com/howeyc/gopass/terminal_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/howeyc/gopass/terminal_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | /* | ||||||
|  |  * CDDL HEADER START | ||||||
|  |  * | ||||||
|  |  * The contents of this file are subject to the terms of the | ||||||
|  |  * Common Development and Distribution License, Version 1.0 only | ||||||
|  |  * (the "License").  You may not use this file except in compliance | ||||||
|  |  * with the License. | ||||||
|  |  * | ||||||
|  |  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||||||
|  |  * or http://www.opensolaris.org/os/licensing. | ||||||
|  |  * See the License for the specific language governing permissions | ||||||
|  |  * and limitations under the License. | ||||||
|  |  * | ||||||
|  |  * When distributing Covered Code, include this CDDL HEADER in each | ||||||
|  |  * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||||||
|  |  * If applicable, add the following below this CDDL HEADER, with the | ||||||
|  |  * fields enclosed by brackets "[]" replaced with your own identifying | ||||||
|  |  * information: Portions Copyright [yyyy] [name of copyright owner] | ||||||
|  |  * | ||||||
|  |  * CDDL HEADER END | ||||||
|  |  */ | ||||||
|  | // Below is derived from Solaris source, so CDDL license is included. | ||||||
|  |  | ||||||
|  | package gopass | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"syscall" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/sys/unix" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type terminalState struct { | ||||||
|  | 	state *unix.Termios | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // isTerminal returns true if there is a terminal attached to the given | ||||||
|  | // file descriptor. | ||||||
|  | // Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c | ||||||
|  | func isTerminal(fd uintptr) bool { | ||||||
|  | 	var termio unix.Termio | ||||||
|  | 	err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) | ||||||
|  | 	return err == nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 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. | ||||||
|  | // Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c | ||||||
|  | func makeRaw(fd uintptr) (*terminalState, error) { | ||||||
|  | 	oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	oldTermios := *oldTermiosPtr | ||||||
|  |  | ||||||
|  | 	newTermios := oldTermios | ||||||
|  | 	newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL | ||||||
|  | 	if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &terminalState{ | ||||||
|  | 		state: oldTermiosPtr, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func restore(fd uintptr, oldState *terminalState) error { | ||||||
|  | 	return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state) | ||||||
|  | } | ||||||
							
								
								
									
										892
									
								
								vendor/golang.org/x/crypto/ssh/terminal/terminal.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										892
									
								
								vendor/golang.org/x/crypto/ssh/terminal/terminal.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,892 @@ | |||||||
|  | // Copyright 2011 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 terminal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"io" | ||||||
|  | 	"sync" | ||||||
|  | 	"unicode/utf8" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // EscapeCodes contains escape sequences that can be written to the terminal in | ||||||
|  | // order to achieve different styles of text. | ||||||
|  | type EscapeCodes struct { | ||||||
|  | 	// Foreground colors | ||||||
|  | 	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte | ||||||
|  |  | ||||||
|  | 	// Reset all attributes | ||||||
|  | 	Reset []byte | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var vt100EscapeCodes = EscapeCodes{ | ||||||
|  | 	Black:   []byte{keyEscape, '[', '3', '0', 'm'}, | ||||||
|  | 	Red:     []byte{keyEscape, '[', '3', '1', 'm'}, | ||||||
|  | 	Green:   []byte{keyEscape, '[', '3', '2', 'm'}, | ||||||
|  | 	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'}, | ||||||
|  | 	Blue:    []byte{keyEscape, '[', '3', '4', 'm'}, | ||||||
|  | 	Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, | ||||||
|  | 	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'}, | ||||||
|  | 	White:   []byte{keyEscape, '[', '3', '7', 'm'}, | ||||||
|  |  | ||||||
|  | 	Reset: []byte{keyEscape, '[', '0', 'm'}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Terminal contains the state for running a VT100 terminal that is capable of | ||||||
|  | // reading lines of input. | ||||||
|  | type Terminal struct { | ||||||
|  | 	// AutoCompleteCallback, if non-null, is called for each keypress with | ||||||
|  | 	// the full input line and the current position of the cursor (in | ||||||
|  | 	// bytes, as an index into |line|). If it returns ok=false, the key | ||||||
|  | 	// press is processed normally. Otherwise it returns a replacement line | ||||||
|  | 	// and the new cursor position. | ||||||
|  | 	AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) | ||||||
|  |  | ||||||
|  | 	// Escape contains a pointer to the escape codes for this terminal. | ||||||
|  | 	// It's always a valid pointer, although the escape codes themselves | ||||||
|  | 	// may be empty if the terminal doesn't support them. | ||||||
|  | 	Escape *EscapeCodes | ||||||
|  |  | ||||||
|  | 	// lock protects the terminal and the state in this object from | ||||||
|  | 	// concurrent processing of a key press and a Write() call. | ||||||
|  | 	lock sync.Mutex | ||||||
|  |  | ||||||
|  | 	c      io.ReadWriter | ||||||
|  | 	prompt []rune | ||||||
|  |  | ||||||
|  | 	// line is the current line being entered. | ||||||
|  | 	line []rune | ||||||
|  | 	// pos is the logical position of the cursor in line | ||||||
|  | 	pos int | ||||||
|  | 	// echo is true if local echo is enabled | ||||||
|  | 	echo bool | ||||||
|  | 	// pasteActive is true iff there is a bracketed paste operation in | ||||||
|  | 	// progress. | ||||||
|  | 	pasteActive bool | ||||||
|  |  | ||||||
|  | 	// cursorX contains the current X value of the cursor where the left | ||||||
|  | 	// edge is 0. cursorY contains the row number where the first row of | ||||||
|  | 	// the current line is 0. | ||||||
|  | 	cursorX, cursorY int | ||||||
|  | 	// maxLine is the greatest value of cursorY so far. | ||||||
|  | 	maxLine int | ||||||
|  |  | ||||||
|  | 	termWidth, termHeight int | ||||||
|  |  | ||||||
|  | 	// outBuf contains the terminal data to be sent. | ||||||
|  | 	outBuf []byte | ||||||
|  | 	// remainder contains the remainder of any partial key sequences after | ||||||
|  | 	// a read. It aliases into inBuf. | ||||||
|  | 	remainder []byte | ||||||
|  | 	inBuf     [256]byte | ||||||
|  |  | ||||||
|  | 	// history contains previously entered commands so that they can be | ||||||
|  | 	// accessed with the up and down keys. | ||||||
|  | 	history stRingBuffer | ||||||
|  | 	// historyIndex stores the currently accessed history entry, where zero | ||||||
|  | 	// means the immediately previous entry. | ||||||
|  | 	historyIndex int | ||||||
|  | 	// When navigating up and down the history it's possible to return to | ||||||
|  | 	// the incomplete, initial line. That value is stored in | ||||||
|  | 	// historyPending. | ||||||
|  | 	historyPending string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is | ||||||
|  | // a local terminal, that terminal must first have been put into raw mode. | ||||||
|  | // prompt is a string that is written at the start of each input line (i.e. | ||||||
|  | // "> "). | ||||||
|  | func NewTerminal(c io.ReadWriter, prompt string) *Terminal { | ||||||
|  | 	return &Terminal{ | ||||||
|  | 		Escape:       &vt100EscapeCodes, | ||||||
|  | 		c:            c, | ||||||
|  | 		prompt:       []rune(prompt), | ||||||
|  | 		termWidth:    80, | ||||||
|  | 		termHeight:   24, | ||||||
|  | 		echo:         true, | ||||||
|  | 		historyIndex: -1, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	keyCtrlD     = 4 | ||||||
|  | 	keyCtrlU     = 21 | ||||||
|  | 	keyEnter     = '\r' | ||||||
|  | 	keyEscape    = 27 | ||||||
|  | 	keyBackspace = 127 | ||||||
|  | 	keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota | ||||||
|  | 	keyUp | ||||||
|  | 	keyDown | ||||||
|  | 	keyLeft | ||||||
|  | 	keyRight | ||||||
|  | 	keyAltLeft | ||||||
|  | 	keyAltRight | ||||||
|  | 	keyHome | ||||||
|  | 	keyEnd | ||||||
|  | 	keyDeleteWord | ||||||
|  | 	keyDeleteLine | ||||||
|  | 	keyClearScreen | ||||||
|  | 	keyPasteStart | ||||||
|  | 	keyPasteEnd | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} | ||||||
|  | var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} | ||||||
|  |  | ||||||
|  | // bytesToKey tries to parse a key sequence from b. If successful, it returns | ||||||
|  | // the key and the remainder of the input. Otherwise it returns utf8.RuneError. | ||||||
|  | func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { | ||||||
|  | 	if len(b) == 0 { | ||||||
|  | 		return utf8.RuneError, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !pasteActive { | ||||||
|  | 		switch b[0] { | ||||||
|  | 		case 1: // ^A | ||||||
|  | 			return keyHome, b[1:] | ||||||
|  | 		case 5: // ^E | ||||||
|  | 			return keyEnd, b[1:] | ||||||
|  | 		case 8: // ^H | ||||||
|  | 			return keyBackspace, b[1:] | ||||||
|  | 		case 11: // ^K | ||||||
|  | 			return keyDeleteLine, b[1:] | ||||||
|  | 		case 12: // ^L | ||||||
|  | 			return keyClearScreen, b[1:] | ||||||
|  | 		case 23: // ^W | ||||||
|  | 			return keyDeleteWord, b[1:] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if b[0] != keyEscape { | ||||||
|  | 		if !utf8.FullRune(b) { | ||||||
|  | 			return utf8.RuneError, b | ||||||
|  | 		} | ||||||
|  | 		r, l := utf8.DecodeRune(b) | ||||||
|  | 		return r, b[l:] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { | ||||||
|  | 		switch b[2] { | ||||||
|  | 		case 'A': | ||||||
|  | 			return keyUp, b[3:] | ||||||
|  | 		case 'B': | ||||||
|  | 			return keyDown, b[3:] | ||||||
|  | 		case 'C': | ||||||
|  | 			return keyRight, b[3:] | ||||||
|  | 		case 'D': | ||||||
|  | 			return keyLeft, b[3:] | ||||||
|  | 		case 'H': | ||||||
|  | 			return keyHome, b[3:] | ||||||
|  | 		case 'F': | ||||||
|  | 			return keyEnd, b[3:] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { | ||||||
|  | 		switch b[5] { | ||||||
|  | 		case 'C': | ||||||
|  | 			return keyAltRight, b[6:] | ||||||
|  | 		case 'D': | ||||||
|  | 			return keyAltLeft, b[6:] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { | ||||||
|  | 		return keyPasteStart, b[6:] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { | ||||||
|  | 		return keyPasteEnd, b[6:] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// If we get here then we have a key that we don't recognise, or a | ||||||
|  | 	// partial sequence. It's not clear how one should find the end of a | ||||||
|  | 	// sequence without knowing them all, but it seems that [a-zA-Z~] only | ||||||
|  | 	// appears at the end of a sequence. | ||||||
|  | 	for i, c := range b[0:] { | ||||||
|  | 		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { | ||||||
|  | 			return keyUnknown, b[i+1:] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return utf8.RuneError, b | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // queue appends data to the end of t.outBuf | ||||||
|  | func (t *Terminal) queue(data []rune) { | ||||||
|  | 	t.outBuf = append(t.outBuf, []byte(string(data))...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} | ||||||
|  | var space = []rune{' '} | ||||||
|  |  | ||||||
|  | func isPrintable(key rune) bool { | ||||||
|  | 	isInSurrogateArea := key >= 0xd800 && key <= 0xdbff | ||||||
|  | 	return key >= 32 && !isInSurrogateArea | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // moveCursorToPos appends data to t.outBuf which will move the cursor to the | ||||||
|  | // given, logical position in the text. | ||||||
|  | func (t *Terminal) moveCursorToPos(pos int) { | ||||||
|  | 	if !t.echo { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	x := visualLength(t.prompt) + pos | ||||||
|  | 	y := x / t.termWidth | ||||||
|  | 	x = x % t.termWidth | ||||||
|  |  | ||||||
|  | 	up := 0 | ||||||
|  | 	if y < t.cursorY { | ||||||
|  | 		up = t.cursorY - y | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	down := 0 | ||||||
|  | 	if y > t.cursorY { | ||||||
|  | 		down = y - t.cursorY | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	left := 0 | ||||||
|  | 	if x < t.cursorX { | ||||||
|  | 		left = t.cursorX - x | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	right := 0 | ||||||
|  | 	if x > t.cursorX { | ||||||
|  | 		right = x - t.cursorX | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	t.cursorX = x | ||||||
|  | 	t.cursorY = y | ||||||
|  | 	t.move(up, down, left, right) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) move(up, down, left, right int) { | ||||||
|  | 	movement := make([]rune, 3*(up+down+left+right)) | ||||||
|  | 	m := movement | ||||||
|  | 	for i := 0; i < up; i++ { | ||||||
|  | 		m[0] = keyEscape | ||||||
|  | 		m[1] = '[' | ||||||
|  | 		m[2] = 'A' | ||||||
|  | 		m = m[3:] | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < down; i++ { | ||||||
|  | 		m[0] = keyEscape | ||||||
|  | 		m[1] = '[' | ||||||
|  | 		m[2] = 'B' | ||||||
|  | 		m = m[3:] | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < left; i++ { | ||||||
|  | 		m[0] = keyEscape | ||||||
|  | 		m[1] = '[' | ||||||
|  | 		m[2] = 'D' | ||||||
|  | 		m = m[3:] | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < right; i++ { | ||||||
|  | 		m[0] = keyEscape | ||||||
|  | 		m[1] = '[' | ||||||
|  | 		m[2] = 'C' | ||||||
|  | 		m = m[3:] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	t.queue(movement) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) clearLineToRight() { | ||||||
|  | 	op := []rune{keyEscape, '[', 'K'} | ||||||
|  | 	t.queue(op) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const maxLineLength = 4096 | ||||||
|  |  | ||||||
|  | func (t *Terminal) setLine(newLine []rune, newPos int) { | ||||||
|  | 	if t.echo { | ||||||
|  | 		t.moveCursorToPos(0) | ||||||
|  | 		t.writeLine(newLine) | ||||||
|  | 		for i := len(newLine); i < len(t.line); i++ { | ||||||
|  | 			t.writeLine(space) | ||||||
|  | 		} | ||||||
|  | 		t.moveCursorToPos(newPos) | ||||||
|  | 	} | ||||||
|  | 	t.line = newLine | ||||||
|  | 	t.pos = newPos | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) advanceCursor(places int) { | ||||||
|  | 	t.cursorX += places | ||||||
|  | 	t.cursorY += t.cursorX / t.termWidth | ||||||
|  | 	if t.cursorY > t.maxLine { | ||||||
|  | 		t.maxLine = t.cursorY | ||||||
|  | 	} | ||||||
|  | 	t.cursorX = t.cursorX % t.termWidth | ||||||
|  |  | ||||||
|  | 	if places > 0 && t.cursorX == 0 { | ||||||
|  | 		// Normally terminals will advance the current position | ||||||
|  | 		// when writing a character. But that doesn't happen | ||||||
|  | 		// for the last character in a line. However, when | ||||||
|  | 		// writing a character (except a new line) that causes | ||||||
|  | 		// a line wrap, the position will be advanced two | ||||||
|  | 		// places. | ||||||
|  | 		// | ||||||
|  | 		// So, if we are stopping at the end of a line, we | ||||||
|  | 		// need to write a newline so that our cursor can be | ||||||
|  | 		// advanced to the next line. | ||||||
|  | 		t.outBuf = append(t.outBuf, '\n') | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) eraseNPreviousChars(n int) { | ||||||
|  | 	if n == 0 { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if t.pos < n { | ||||||
|  | 		n = t.pos | ||||||
|  | 	} | ||||||
|  | 	t.pos -= n | ||||||
|  | 	t.moveCursorToPos(t.pos) | ||||||
|  |  | ||||||
|  | 	copy(t.line[t.pos:], t.line[n+t.pos:]) | ||||||
|  | 	t.line = t.line[:len(t.line)-n] | ||||||
|  | 	if t.echo { | ||||||
|  | 		t.writeLine(t.line[t.pos:]) | ||||||
|  | 		for i := 0; i < n; i++ { | ||||||
|  | 			t.queue(space) | ||||||
|  | 		} | ||||||
|  | 		t.advanceCursor(n) | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // countToLeftWord returns then number of characters from the cursor to the | ||||||
|  | // start of the previous word. | ||||||
|  | func (t *Terminal) countToLeftWord() int { | ||||||
|  | 	if t.pos == 0 { | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pos := t.pos - 1 | ||||||
|  | 	for pos > 0 { | ||||||
|  | 		if t.line[pos] != ' ' { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		pos-- | ||||||
|  | 	} | ||||||
|  | 	for pos > 0 { | ||||||
|  | 		if t.line[pos] == ' ' { | ||||||
|  | 			pos++ | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		pos-- | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return t.pos - pos | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // countToRightWord returns then number of characters from the cursor to the | ||||||
|  | // start of the next word. | ||||||
|  | func (t *Terminal) countToRightWord() int { | ||||||
|  | 	pos := t.pos | ||||||
|  | 	for pos < len(t.line) { | ||||||
|  | 		if t.line[pos] == ' ' { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		pos++ | ||||||
|  | 	} | ||||||
|  | 	for pos < len(t.line) { | ||||||
|  | 		if t.line[pos] != ' ' { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		pos++ | ||||||
|  | 	} | ||||||
|  | 	return pos - t.pos | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // visualLength returns the number of visible glyphs in s. | ||||||
|  | func visualLength(runes []rune) int { | ||||||
|  | 	inEscapeSeq := false | ||||||
|  | 	length := 0 | ||||||
|  |  | ||||||
|  | 	for _, r := range runes { | ||||||
|  | 		switch { | ||||||
|  | 		case inEscapeSeq: | ||||||
|  | 			if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { | ||||||
|  | 				inEscapeSeq = false | ||||||
|  | 			} | ||||||
|  | 		case r == '\x1b': | ||||||
|  | 			inEscapeSeq = true | ||||||
|  | 		default: | ||||||
|  | 			length++ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return length | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // handleKey processes the given key and, optionally, returns a line of text | ||||||
|  | // that the user has entered. | ||||||
|  | func (t *Terminal) handleKey(key rune) (line string, ok bool) { | ||||||
|  | 	if t.pasteActive && key != keyEnter { | ||||||
|  | 		t.addKeyToLine(key) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	switch key { | ||||||
|  | 	case keyBackspace: | ||||||
|  | 		if t.pos == 0 { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		t.eraseNPreviousChars(1) | ||||||
|  | 	case keyAltLeft: | ||||||
|  | 		// move left by a word. | ||||||
|  | 		t.pos -= t.countToLeftWord() | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyAltRight: | ||||||
|  | 		// move right by a word. | ||||||
|  | 		t.pos += t.countToRightWord() | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyLeft: | ||||||
|  | 		if t.pos == 0 { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		t.pos-- | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyRight: | ||||||
|  | 		if t.pos == len(t.line) { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		t.pos++ | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyHome: | ||||||
|  | 		if t.pos == 0 { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		t.pos = 0 | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyEnd: | ||||||
|  | 		if t.pos == len(t.line) { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		t.pos = len(t.line) | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyUp: | ||||||
|  | 		entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) | ||||||
|  | 		if !ok { | ||||||
|  | 			return "", false | ||||||
|  | 		} | ||||||
|  | 		if t.historyIndex == -1 { | ||||||
|  | 			t.historyPending = string(t.line) | ||||||
|  | 		} | ||||||
|  | 		t.historyIndex++ | ||||||
|  | 		runes := []rune(entry) | ||||||
|  | 		t.setLine(runes, len(runes)) | ||||||
|  | 	case keyDown: | ||||||
|  | 		switch t.historyIndex { | ||||||
|  | 		case -1: | ||||||
|  | 			return | ||||||
|  | 		case 0: | ||||||
|  | 			runes := []rune(t.historyPending) | ||||||
|  | 			t.setLine(runes, len(runes)) | ||||||
|  | 			t.historyIndex-- | ||||||
|  | 		default: | ||||||
|  | 			entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) | ||||||
|  | 			if ok { | ||||||
|  | 				t.historyIndex-- | ||||||
|  | 				runes := []rune(entry) | ||||||
|  | 				t.setLine(runes, len(runes)) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	case keyEnter: | ||||||
|  | 		t.moveCursorToPos(len(t.line)) | ||||||
|  | 		t.queue([]rune("\r\n")) | ||||||
|  | 		line = string(t.line) | ||||||
|  | 		ok = true | ||||||
|  | 		t.line = t.line[:0] | ||||||
|  | 		t.pos = 0 | ||||||
|  | 		t.cursorX = 0 | ||||||
|  | 		t.cursorY = 0 | ||||||
|  | 		t.maxLine = 0 | ||||||
|  | 	case keyDeleteWord: | ||||||
|  | 		// Delete zero or more spaces and then one or more characters. | ||||||
|  | 		t.eraseNPreviousChars(t.countToLeftWord()) | ||||||
|  | 	case keyDeleteLine: | ||||||
|  | 		// Delete everything from the current cursor position to the | ||||||
|  | 		// end of line. | ||||||
|  | 		for i := t.pos; i < len(t.line); i++ { | ||||||
|  | 			t.queue(space) | ||||||
|  | 			t.advanceCursor(1) | ||||||
|  | 		} | ||||||
|  | 		t.line = t.line[:t.pos] | ||||||
|  | 		t.moveCursorToPos(t.pos) | ||||||
|  | 	case keyCtrlD: | ||||||
|  | 		// Erase the character under the current position. | ||||||
|  | 		// The EOF case when the line is empty is handled in | ||||||
|  | 		// readLine(). | ||||||
|  | 		if t.pos < len(t.line) { | ||||||
|  | 			t.pos++ | ||||||
|  | 			t.eraseNPreviousChars(1) | ||||||
|  | 		} | ||||||
|  | 	case keyCtrlU: | ||||||
|  | 		t.eraseNPreviousChars(t.pos) | ||||||
|  | 	case keyClearScreen: | ||||||
|  | 		// Erases the screen and moves the cursor to the home position. | ||||||
|  | 		t.queue([]rune("\x1b[2J\x1b[H")) | ||||||
|  | 		t.queue(t.prompt) | ||||||
|  | 		t.cursorX, t.cursorY = 0, 0 | ||||||
|  | 		t.advanceCursor(visualLength(t.prompt)) | ||||||
|  | 		t.setLine(t.line, t.pos) | ||||||
|  | 	default: | ||||||
|  | 		if t.AutoCompleteCallback != nil { | ||||||
|  | 			prefix := string(t.line[:t.pos]) | ||||||
|  | 			suffix := string(t.line[t.pos:]) | ||||||
|  |  | ||||||
|  | 			t.lock.Unlock() | ||||||
|  | 			newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) | ||||||
|  | 			t.lock.Lock() | ||||||
|  |  | ||||||
|  | 			if completeOk { | ||||||
|  | 				t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if !isPrintable(key) { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		if len(t.line) == maxLineLength { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		t.addKeyToLine(key) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // addKeyToLine inserts the given key at the current position in the current | ||||||
|  | // line. | ||||||
|  | func (t *Terminal) addKeyToLine(key rune) { | ||||||
|  | 	if len(t.line) == cap(t.line) { | ||||||
|  | 		newLine := make([]rune, len(t.line), 2*(1+len(t.line))) | ||||||
|  | 		copy(newLine, t.line) | ||||||
|  | 		t.line = newLine | ||||||
|  | 	} | ||||||
|  | 	t.line = t.line[:len(t.line)+1] | ||||||
|  | 	copy(t.line[t.pos+1:], t.line[t.pos:]) | ||||||
|  | 	t.line[t.pos] = key | ||||||
|  | 	if t.echo { | ||||||
|  | 		t.writeLine(t.line[t.pos:]) | ||||||
|  | 	} | ||||||
|  | 	t.pos++ | ||||||
|  | 	t.moveCursorToPos(t.pos) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) writeLine(line []rune) { | ||||||
|  | 	for len(line) != 0 { | ||||||
|  | 		remainingOnLine := t.termWidth - t.cursorX | ||||||
|  | 		todo := len(line) | ||||||
|  | 		if todo > remainingOnLine { | ||||||
|  | 			todo = remainingOnLine | ||||||
|  | 		} | ||||||
|  | 		t.queue(line[:todo]) | ||||||
|  | 		t.advanceCursor(visualLength(line[:todo])) | ||||||
|  | 		line = line[todo:] | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) Write(buf []byte) (n int, err error) { | ||||||
|  | 	t.lock.Lock() | ||||||
|  | 	defer t.lock.Unlock() | ||||||
|  |  | ||||||
|  | 	if t.cursorX == 0 && t.cursorY == 0 { | ||||||
|  | 		// This is the easy case: there's nothing on the screen that we | ||||||
|  | 		// have to move out of the way. | ||||||
|  | 		return t.c.Write(buf) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// We have a prompt and possibly user input on the screen. We | ||||||
|  | 	// have to clear it first. | ||||||
|  | 	t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) | ||||||
|  | 	t.cursorX = 0 | ||||||
|  | 	t.clearLineToRight() | ||||||
|  |  | ||||||
|  | 	for t.cursorY > 0 { | ||||||
|  | 		t.move(1 /* up */, 0, 0, 0) | ||||||
|  | 		t.cursorY-- | ||||||
|  | 		t.clearLineToRight() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err = t.c.Write(t.outBuf); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	t.outBuf = t.outBuf[:0] | ||||||
|  |  | ||||||
|  | 	if n, err = t.c.Write(buf); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	t.writeLine(t.prompt) | ||||||
|  | 	if t.echo { | ||||||
|  | 		t.writeLine(t.line) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	t.moveCursorToPos(t.pos) | ||||||
|  |  | ||||||
|  | 	if _, err = t.c.Write(t.outBuf); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	t.outBuf = t.outBuf[:0] | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ReadPassword temporarily changes the prompt and reads a password, without | ||||||
|  | // echo, from the terminal. | ||||||
|  | func (t *Terminal) ReadPassword(prompt string) (line string, err error) { | ||||||
|  | 	t.lock.Lock() | ||||||
|  | 	defer t.lock.Unlock() | ||||||
|  |  | ||||||
|  | 	oldPrompt := t.prompt | ||||||
|  | 	t.prompt = []rune(prompt) | ||||||
|  | 	t.echo = false | ||||||
|  |  | ||||||
|  | 	line, err = t.readLine() | ||||||
|  |  | ||||||
|  | 	t.prompt = oldPrompt | ||||||
|  | 	t.echo = true | ||||||
|  |  | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ReadLine returns a line of input from the terminal. | ||||||
|  | func (t *Terminal) ReadLine() (line string, err error) { | ||||||
|  | 	t.lock.Lock() | ||||||
|  | 	defer t.lock.Unlock() | ||||||
|  |  | ||||||
|  | 	return t.readLine() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) readLine() (line string, err error) { | ||||||
|  | 	// t.lock must be held at this point | ||||||
|  |  | ||||||
|  | 	if t.cursorX == 0 && t.cursorY == 0 { | ||||||
|  | 		t.writeLine(t.prompt) | ||||||
|  | 		t.c.Write(t.outBuf) | ||||||
|  | 		t.outBuf = t.outBuf[:0] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	lineIsPasted := t.pasteActive | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		rest := t.remainder | ||||||
|  | 		lineOk := false | ||||||
|  | 		for !lineOk { | ||||||
|  | 			var key rune | ||||||
|  | 			key, rest = bytesToKey(rest, t.pasteActive) | ||||||
|  | 			if key == utf8.RuneError { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			if !t.pasteActive { | ||||||
|  | 				if key == keyCtrlD { | ||||||
|  | 					if len(t.line) == 0 { | ||||||
|  | 						return "", io.EOF | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				if key == keyPasteStart { | ||||||
|  | 					t.pasteActive = true | ||||||
|  | 					if len(t.line) == 0 { | ||||||
|  | 						lineIsPasted = true | ||||||
|  | 					} | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 			} else if key == keyPasteEnd { | ||||||
|  | 				t.pasteActive = false | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if !t.pasteActive { | ||||||
|  | 				lineIsPasted = false | ||||||
|  | 			} | ||||||
|  | 			line, lineOk = t.handleKey(key) | ||||||
|  | 		} | ||||||
|  | 		if len(rest) > 0 { | ||||||
|  | 			n := copy(t.inBuf[:], rest) | ||||||
|  | 			t.remainder = t.inBuf[:n] | ||||||
|  | 		} else { | ||||||
|  | 			t.remainder = nil | ||||||
|  | 		} | ||||||
|  | 		t.c.Write(t.outBuf) | ||||||
|  | 		t.outBuf = t.outBuf[:0] | ||||||
|  | 		if lineOk { | ||||||
|  | 			if t.echo { | ||||||
|  | 				t.historyIndex = -1 | ||||||
|  | 				t.history.Add(line) | ||||||
|  | 			} | ||||||
|  | 			if lineIsPasted { | ||||||
|  | 				err = ErrPasteIndicator | ||||||
|  | 			} | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// t.remainder is a slice at the beginning of t.inBuf | ||||||
|  | 		// containing a partial key sequence | ||||||
|  | 		readBuf := t.inBuf[len(t.remainder):] | ||||||
|  | 		var n int | ||||||
|  |  | ||||||
|  | 		t.lock.Unlock() | ||||||
|  | 		n, err = t.c.Read(readBuf) | ||||||
|  | 		t.lock.Lock() | ||||||
|  |  | ||||||
|  | 		if err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		t.remainder = t.inBuf[:n+len(t.remainder)] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	panic("unreachable") // for Go 1.0. | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SetPrompt sets the prompt to be used when reading subsequent lines. | ||||||
|  | func (t *Terminal) SetPrompt(prompt string) { | ||||||
|  | 	t.lock.Lock() | ||||||
|  | 	defer t.lock.Unlock() | ||||||
|  |  | ||||||
|  | 	t.prompt = []rune(prompt) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { | ||||||
|  | 	// Move cursor to column zero at the start of the line. | ||||||
|  | 	t.move(t.cursorY, 0, t.cursorX, 0) | ||||||
|  | 	t.cursorX, t.cursorY = 0, 0 | ||||||
|  | 	t.clearLineToRight() | ||||||
|  | 	for t.cursorY < numPrevLines { | ||||||
|  | 		// Move down a line | ||||||
|  | 		t.move(0, 1, 0, 0) | ||||||
|  | 		t.cursorY++ | ||||||
|  | 		t.clearLineToRight() | ||||||
|  | 	} | ||||||
|  | 	// Move back to beginning. | ||||||
|  | 	t.move(t.cursorY, 0, 0, 0) | ||||||
|  | 	t.cursorX, t.cursorY = 0, 0 | ||||||
|  |  | ||||||
|  | 	t.queue(t.prompt) | ||||||
|  | 	t.advanceCursor(visualLength(t.prompt)) | ||||||
|  | 	t.writeLine(t.line) | ||||||
|  | 	t.moveCursorToPos(t.pos) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (t *Terminal) SetSize(width, height int) error { | ||||||
|  | 	t.lock.Lock() | ||||||
|  | 	defer t.lock.Unlock() | ||||||
|  |  | ||||||
|  | 	if width == 0 { | ||||||
|  | 		width = 1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	oldWidth := t.termWidth | ||||||
|  | 	t.termWidth, t.termHeight = width, height | ||||||
|  |  | ||||||
|  | 	switch { | ||||||
|  | 	case width == oldWidth: | ||||||
|  | 		// If the width didn't change then nothing else needs to be | ||||||
|  | 		// done. | ||||||
|  | 		return nil | ||||||
|  | 	case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: | ||||||
|  | 		// If there is nothing on current line and no prompt printed, | ||||||
|  | 		// just do nothing | ||||||
|  | 		return nil | ||||||
|  | 	case width < oldWidth: | ||||||
|  | 		// Some terminals (e.g. xterm) will truncate lines that were | ||||||
|  | 		// too long when shinking. Others, (e.g. gnome-terminal) will | ||||||
|  | 		// attempt to wrap them. For the former, repainting t.maxLine | ||||||
|  | 		// works great, but that behaviour goes badly wrong in the case | ||||||
|  | 		// of the latter because they have doubled every full line. | ||||||
|  |  | ||||||
|  | 		// We assume that we are working on a terminal that wraps lines | ||||||
|  | 		// and adjust the cursor position based on every previous line | ||||||
|  | 		// wrapping and turning into two. This causes the prompt on | ||||||
|  | 		// xterms to move upwards, which isn't great, but it avoids a | ||||||
|  | 		// huge mess with gnome-terminal. | ||||||
|  | 		if t.cursorX >= t.termWidth { | ||||||
|  | 			t.cursorX = t.termWidth - 1 | ||||||
|  | 		} | ||||||
|  | 		t.cursorY *= 2 | ||||||
|  | 		t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) | ||||||
|  | 	case width > oldWidth: | ||||||
|  | 		// If the terminal expands then our position calculations will | ||||||
|  | 		// be wrong in the future because we think the cursor is | ||||||
|  | 		// |t.pos| chars into the string, but there will be a gap at | ||||||
|  | 		// the end of any wrapped line. | ||||||
|  | 		// | ||||||
|  | 		// But the position will actually be correct until we move, so | ||||||
|  | 		// we can move back to the beginning and repaint everything. | ||||||
|  | 		t.clearAndRepaintLinePlusNPrevious(t.maxLine) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, err := t.c.Write(t.outBuf) | ||||||
|  | 	t.outBuf = t.outBuf[:0] | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type pasteIndicatorError struct{} | ||||||
|  |  | ||||||
|  | func (pasteIndicatorError) Error() string { | ||||||
|  | 	return "terminal: ErrPasteIndicator not correctly handled" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ErrPasteIndicator may be returned from ReadLine as the error, in addition | ||||||
|  | // to valid line data. It indicates that bracketed paste mode is enabled and | ||||||
|  | // that the returned line consists only of pasted data. Programs may wish to | ||||||
|  | // interpret pasted data more literally than typed data. | ||||||
|  | var ErrPasteIndicator = pasteIndicatorError{} | ||||||
|  |  | ||||||
|  | // SetBracketedPasteMode requests that the terminal bracket paste operations | ||||||
|  | // with markers. Not all terminals support this but, if it is supported, then | ||||||
|  | // enabling this mode will stop any autocomplete callback from running due to | ||||||
|  | // pastes. Additionally, any lines that are completely pasted will be returned | ||||||
|  | // from ReadLine with the error set to ErrPasteIndicator. | ||||||
|  | func (t *Terminal) SetBracketedPasteMode(on bool) { | ||||||
|  | 	if on { | ||||||
|  | 		io.WriteString(t.c, "\x1b[?2004h") | ||||||
|  | 	} else { | ||||||
|  | 		io.WriteString(t.c, "\x1b[?2004l") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // stRingBuffer is a ring buffer of strings. | ||||||
|  | type stRingBuffer struct { | ||||||
|  | 	// entries contains max elements. | ||||||
|  | 	entries []string | ||||||
|  | 	max     int | ||||||
|  | 	// head contains the index of the element most recently added to the ring. | ||||||
|  | 	head int | ||||||
|  | 	// size contains the number of elements in the ring. | ||||||
|  | 	size int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *stRingBuffer) Add(a string) { | ||||||
|  | 	if s.entries == nil { | ||||||
|  | 		const defaultNumEntries = 100 | ||||||
|  | 		s.entries = make([]string, defaultNumEntries) | ||||||
|  | 		s.max = defaultNumEntries | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s.head = (s.head + 1) % s.max | ||||||
|  | 	s.entries[s.head] = a | ||||||
|  | 	if s.size < s.max { | ||||||
|  | 		s.size++ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NthPreviousEntry returns the value passed to the nth previous call to Add. | ||||||
|  | // If n is zero then the immediately prior value is returned, if one, then the | ||||||
|  | // next most recent, and so on. If such an element doesn't exist then ok is | ||||||
|  | // false. | ||||||
|  | func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { | ||||||
|  | 	if n >= s.size { | ||||||
|  | 		return "", false | ||||||
|  | 	} | ||||||
|  | 	index := s.head - n | ||||||
|  | 	if index < 0 { | ||||||
|  | 		index += s.max | ||||||
|  | 	} | ||||||
|  | 	return s.entries[index], true | ||||||
|  | } | ||||||
							
								
								
									
										128
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | // Copyright 2011 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 dragonfly freebsd linux,!appengine netbsd openbsd | ||||||
|  |  | ||||||
|  | // Package terminal provides support functions for dealing with terminals, as | ||||||
|  | // commonly found on UNIX systems. | ||||||
|  | // | ||||||
|  | // Putting a terminal into raw mode is the most common requirement: | ||||||
|  | // | ||||||
|  | // 	oldState, err := terminal.MakeRaw(0) | ||||||
|  | // 	if err != nil { | ||||||
|  | // 	        panic(err) | ||||||
|  | // 	} | ||||||
|  | // 	defer terminal.Restore(0, oldState) | ||||||
|  | package terminal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"io" | ||||||
|  | 	"syscall" | ||||||
|  | 	"unsafe" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // State contains the state of a terminal. | ||||||
|  | type State struct { | ||||||
|  | 	termios syscall.Termios | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // IsTerminal returns true if the given file descriptor is a terminal. | ||||||
|  | func IsTerminal(fd int) bool { | ||||||
|  | 	var termios syscall.Termios | ||||||
|  | 	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) | ||||||
|  | 	return err == 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // MakeRaw put 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 int) (*State, error) { | ||||||
|  | 	var oldState State | ||||||
|  | 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	newState := oldState.termios | ||||||
|  | 	newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF | ||||||
|  | 	newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG | ||||||
|  | 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &oldState, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetState returns the current state of a terminal which may be useful to | ||||||
|  | // restore the terminal after a signal. | ||||||
|  | func GetState(fd int) (*State, error) { | ||||||
|  | 	var oldState State | ||||||
|  | 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &oldState, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Restore restores the terminal connected to the given file descriptor to a | ||||||
|  | // previous state. | ||||||
|  | func Restore(fd int, state *State) error { | ||||||
|  | 	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetSize returns the dimensions of the given terminal. | ||||||
|  | func GetSize(fd int) (width, height int, err error) { | ||||||
|  | 	var dimensions [4]uint16 | ||||||
|  |  | ||||||
|  | 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { | ||||||
|  | 		return -1, -1, err | ||||||
|  | 	} | ||||||
|  | 	return int(dimensions[1]), int(dimensions[0]), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ReadPassword reads a line of input from a terminal without local echo.  This | ||||||
|  | // is commonly used for inputting passwords and other sensitive data. The slice | ||||||
|  | // returned does not include the \n. | ||||||
|  | func ReadPassword(fd int) ([]byte, error) { | ||||||
|  | 	var oldState syscall.Termios | ||||||
|  | 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	newState := oldState | ||||||
|  | 	newState.Lflag &^= syscall.ECHO | ||||||
|  | 	newState.Lflag |= syscall.ICANON | syscall.ISIG | ||||||
|  | 	newState.Iflag |= syscall.ICRNL | ||||||
|  | 	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	defer func() { | ||||||
|  | 		syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	var buf [16]byte | ||||||
|  | 	var ret []byte | ||||||
|  | 	for { | ||||||
|  | 		n, err := syscall.Read(fd, buf[:]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		if n == 0 { | ||||||
|  | 			if len(ret) == 0 { | ||||||
|  | 				return nil, io.EOF | ||||||
|  | 			} | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		if buf[n-1] == '\n' { | ||||||
|  | 			n-- | ||||||
|  | 		} | ||||||
|  | 		ret = append(ret, buf[:n]...) | ||||||
|  | 		if n < len(buf) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ret, nil | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | // Copyright 2013 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 dragonfly freebsd netbsd openbsd | ||||||
|  |  | ||||||
|  | package terminal | ||||||
|  |  | ||||||
|  | import "syscall" | ||||||
|  |  | ||||||
|  | const ioctlReadTermios = syscall.TIOCGETA | ||||||
|  | const ioctlWriteTermios = syscall.TIOCSETA | ||||||
							
								
								
									
										11
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | // Copyright 2013 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 terminal | ||||||
|  |  | ||||||
|  | // These constants are declared here, rather than importing | ||||||
|  | // them from the syscall package as some syscall packages, even | ||||||
|  | // on linux, for example gccgo, do not declare them. | ||||||
|  | const ioctlReadTermios = 0x5401  // syscall.TCGETS | ||||||
|  | const ioctlWriteTermios = 0x5402 // syscall.TCSETS | ||||||
							
								
								
									
										174
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | |||||||
|  | // Copyright 2011 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 windows | ||||||
|  |  | ||||||
|  | // Package terminal provides support functions for dealing with terminals, as | ||||||
|  | // commonly found on UNIX systems. | ||||||
|  | // | ||||||
|  | // Putting a terminal into raw mode is the most common requirement: | ||||||
|  | // | ||||||
|  | // 	oldState, err := terminal.MakeRaw(0) | ||||||
|  | // 	if err != nil { | ||||||
|  | // 	        panic(err) | ||||||
|  | // 	} | ||||||
|  | // 	defer terminal.Restore(0, oldState) | ||||||
|  | package terminal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"io" | ||||||
|  | 	"syscall" | ||||||
|  | 	"unsafe" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	enableLineInput       = 2 | ||||||
|  | 	enableEchoInput       = 4 | ||||||
|  | 	enableProcessedInput  = 1 | ||||||
|  | 	enableWindowInput     = 8 | ||||||
|  | 	enableMouseInput      = 16 | ||||||
|  | 	enableInsertMode      = 32 | ||||||
|  | 	enableQuickEditMode   = 64 | ||||||
|  | 	enableExtendedFlags   = 128 | ||||||
|  | 	enableAutoPosition    = 256 | ||||||
|  | 	enableProcessedOutput = 1 | ||||||
|  | 	enableWrapAtEolOutput = 2 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var kernel32 = syscall.NewLazyDLL("kernel32.dll") | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	procGetConsoleMode             = kernel32.NewProc("GetConsoleMode") | ||||||
|  | 	procSetConsoleMode             = kernel32.NewProc("SetConsoleMode") | ||||||
|  | 	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type ( | ||||||
|  | 	short int16 | ||||||
|  | 	word  uint16 | ||||||
|  |  | ||||||
|  | 	coord struct { | ||||||
|  | 		x short | ||||||
|  | 		y short | ||||||
|  | 	} | ||||||
|  | 	smallRect struct { | ||||||
|  | 		left   short | ||||||
|  | 		top    short | ||||||
|  | 		right  short | ||||||
|  | 		bottom short | ||||||
|  | 	} | ||||||
|  | 	consoleScreenBufferInfo struct { | ||||||
|  | 		size              coord | ||||||
|  | 		cursorPosition    coord | ||||||
|  | 		attributes        word | ||||||
|  | 		window            smallRect | ||||||
|  | 		maximumWindowSize coord | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type State struct { | ||||||
|  | 	mode uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // IsTerminal returns true if the given file descriptor is a terminal. | ||||||
|  | func IsTerminal(fd int) bool { | ||||||
|  | 	var st uint32 | ||||||
|  | 	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) | ||||||
|  | 	return r != 0 && e == 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // MakeRaw put 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 int) (*State, error) { | ||||||
|  | 	var st uint32 | ||||||
|  | 	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) | ||||||
|  | 	if e != 0 { | ||||||
|  | 		return nil, error(e) | ||||||
|  | 	} | ||||||
|  | 	st &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) | ||||||
|  | 	_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) | ||||||
|  | 	if e != 0 { | ||||||
|  | 		return nil, error(e) | ||||||
|  | 	} | ||||||
|  | 	return &State{st}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetState returns the current state of a terminal which may be useful to | ||||||
|  | // restore the terminal after a signal. | ||||||
|  | func GetState(fd int) (*State, error) { | ||||||
|  | 	var st uint32 | ||||||
|  | 	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) | ||||||
|  | 	if e != 0 { | ||||||
|  | 		return nil, error(e) | ||||||
|  | 	} | ||||||
|  | 	return &State{st}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Restore restores the terminal connected to the given file descriptor to a | ||||||
|  | // previous state. | ||||||
|  | func Restore(fd int, state *State) error { | ||||||
|  | 	_, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetSize returns the dimensions of the given terminal. | ||||||
|  | func GetSize(fd int) (width, height int, err error) { | ||||||
|  | 	var info consoleScreenBufferInfo | ||||||
|  | 	_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) | ||||||
|  | 	if e != 0 { | ||||||
|  | 		return 0, 0, error(e) | ||||||
|  | 	} | ||||||
|  | 	return int(info.size.x), int(info.size.y), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ReadPassword reads a line of input from a terminal without local echo.  This | ||||||
|  | // is commonly used for inputting passwords and other sensitive data. The slice | ||||||
|  | // returned does not include the \n. | ||||||
|  | func ReadPassword(fd int) ([]byte, error) { | ||||||
|  | 	var st uint32 | ||||||
|  | 	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) | ||||||
|  | 	if e != 0 { | ||||||
|  | 		return nil, error(e) | ||||||
|  | 	} | ||||||
|  | 	old := st | ||||||
|  |  | ||||||
|  | 	st &^= (enableEchoInput) | ||||||
|  | 	st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) | ||||||
|  | 	_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) | ||||||
|  | 	if e != 0 { | ||||||
|  | 		return nil, error(e) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	defer func() { | ||||||
|  | 		syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	var buf [16]byte | ||||||
|  | 	var ret []byte | ||||||
|  | 	for { | ||||||
|  | 		n, err := syscall.Read(syscall.Handle(fd), buf[:]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		if n == 0 { | ||||||
|  | 			if len(ret) == 0 { | ||||||
|  | 				return nil, io.EOF | ||||||
|  | 			} | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		if buf[n-1] == '\n' { | ||||||
|  | 			n-- | ||||||
|  | 		} | ||||||
|  | 		if n > 0 && buf[n-1] == '\r' { | ||||||
|  | 			n-- | ||||||
|  | 		} | ||||||
|  | 		ret = append(ret, buf[:n]...) | ||||||
|  | 		if n < len(buf) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ret, nil | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user