github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/utils/prompt/stdin.go (about) 1 /* 2 Copyright 2021 Gravitational, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package prompt 18 19 import ( 20 "os" 21 "sync" 22 ) 23 24 var ( 25 stdinMU sync.Mutex 26 stdin StdinReader 27 ) 28 29 // StdinReader contains ContextReader methods applicable to stdin. 30 type StdinReader interface { 31 IsTerminal() bool 32 Reader 33 SecureReader 34 } 35 36 // Stdin returns a singleton ContextReader wrapped around os.Stdin. 37 // 38 // os.Stdin should not be used directly after the first call to this function 39 // to avoid losing data. 40 func Stdin() StdinReader { 41 stdinMU.Lock() 42 defer stdinMU.Unlock() 43 if stdin == nil { 44 cr := NewContextReader(os.Stdin) 45 go cr.handleInterrupt() 46 stdin = cr 47 } 48 return stdin 49 } 50 51 // SetStdin allows callers to change the Stdin reader. 52 // Useful to replace Stdin for tests, but should be avoided in production code. 53 func SetStdin(rd StdinReader) { 54 stdinMU.Lock() 55 defer stdinMU.Unlock() 56 stdin = rd 57 } 58 59 // NotifyExit notifies prompt singletons, such as Stdin, that the program is 60 // about to exit. This allows singletons to perform actions such as restoring 61 // terminal state. 62 // Once NotifyExit is called the singletons will be closed. 63 func NotifyExit() { 64 // Note: don't call methods such as Stdin() here, we don't want to 65 // inadvertently hijack the prompts on exit. 66 stdinMU.Lock() 67 if cr, ok := stdin.(*ContextReader); ok { 68 _ = cr.Close() 69 } 70 stdinMU.Unlock() 71 }