I am writing a command line application for OS X in Swift. I need to prompt for a username and password (not the user's account on the computer and not credentials saved in the Keychain). I can prompt for the username just fine:
func getInput() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
let username = getInput()
I would like to prompt for the password as well but it prints the password in the console as the user types it. How can I accept input from STDIN without having it echoed back to the console?
Please note that I need the application to be interactive, the user will never be passing the username and password as command line arguments, so argv is not the correct answer.
For example, when doing this in Ruby, you would enter this:
require 'io/console'
puts "Enter your password"
@password = STDIN.noecho(&:gets).chomp
And then it would display on the screen as this image:
No matter how many letters are entered, it only shows that blue box with the dot in it. It doesn't print the password to the screen and it doesn't show ********* for the password either.
Is it possible to do the same thing with Swift or Objective-C in a command line OS X application?
Just for the sake of completeness: getpass() works great for passwords, but unfortunately this function also has the limitation that it can only read up to 128 characters. If you want to prompt for really long passphrase or private keys, use BSD's readpassphrase() instead.
Swift 2.0 example:
var buf = [Int8](count: 8192, repeatedValue: 0)
let passphrase = readpassphrase("Enter passphrase: ", &buf, buf.count, 0)
if let passphraseStr = String.fromCString(passphrase) {
print(passphraseStr)
}
Swift 3.1 and later:
var buf = [CChar](repeating: 0, count: 8192)
if let passphrase = readpassphrase("Enter passphrase: ", &buf, buf.count, 0),
let passphraseStr = String(validatingUTF8: passphrase) {
print(passphraseStr)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With