How to get command-line password input in Racket - racket

I am trying to get password input on the command-line without showing the password when it is typed. This code below is not suitable, because it shows the password when the user types it on the command line:
(display "Password: ")
(define password (read-line))
How can I input password on the command-line using Racket?

This is not really a Racket question, but more of terminal's capability. Here's one solution using stty. There are other solutions too depending on how sophisticated you want the program to be.
#lang racket
(define (read-password)
(system "stty -echo")
(begin0 (read-line)
(system "stty echo")
(newline)))
(display "Password: ")
(define password (read-password))
(display "Username: ")
(define user (read-line))
(printf "User ~a's secret is: ~a\n" user password)
Password:
Username: Randall
User Randall's secret is: correcthorsebatterystaple
ADDENDUM: there's also a package https://pkgs.racket-lang.org/package/get-pass that provides this functionality, Install it with raco pkg install get-pass.

Related

display executing name of the current running script

I have tried a few methods, one of them being:
(define (program) (find-system-path 'pref-file))
I have read from the documentation (after attempting the above code) and have noticed it is not what i'd need to use, obviously :) Any ideas?
Would also like to save this information to a variables. VBS example:
script = WScript.ScriptFullName
#lang racket
(display "Program name: ")
(displayln (find-system-path 'run-file))
Output (if saved as "test.rkt" and run with the command racket test.rkt):
Program name: test.rkt
From the racket console REPL, (find-system-path 'run-file) will return #<path:racket>. I didn't try it in DrRacket.

emacs function to send password to minibuffer when asked for

I usually connect to a machine through SSH and using ssh.el. I defined a command so I can do this quickly:
(defun ssh-me()
(interactive)
(ssh "myuser#myhost"))
After that, the mini-buffer asks me for the password and everything works fine. I am wondering if there is a way to set my password in my function so I don't have to write it every time I want to connect to that machine, so I would have something like:
(defun ssh-me()
(interactive)
(ssh "myuser#myhost")
(send-password-to-minibuffer "mypasswd"))
Is that possible?
Here is an example using a small custom file that is not encrypted. In this example, the filename is .authinfo_iphone and it contains just one line -- I use it to connect to my jailbroken iphone via ssh:
machine localhost login root password alpine port ssh
Then, I use a small function to connect:
(defun lawlist-remote-iphone-data ()
(interactive)
(let ((auth-sources '("/Users/HOME/.0.data/.0.emacs/.authinfo_iphone")))
(find-file "/ssh:root#localhost#2222:/private/var/mobile/.0.data/")))
You could also use an external utility such as sshpass and then write-up a function -- the command-line looks like:
/usr/bin/sshpass -p 'my-password' ssh my-username#12.34.56.789
And here is an example function that incorporates that command line to log-in to the iPhone over ssh. It contemplates there is already an open shell-mode buffer with the process named *shell*.
(defun shell-iphone ()
"From an existing shell buffer with a process named `*shell*`,
log-in to the iPhone using sshpass."
(interactive)
(let* (
(password "alpine")
(port "2222")
(username "root")
(host "localhost")
(sshpass "/Users/HOME/.0.data/.0.emacs/bin/sshpass")
(ssh "/usr/bin/ssh")
(dir "/private/var/mobile/.0.data"))
(comint-send-string "*shell*"
(mapconcat 'identity `(
,sshpass
"-p"
,password
,ssh
"-p"
,port
"-l"
,username
,host
"-t"
"\"cd " ,dir " && bash --login\"") " "))
(comint-send-input)))

How to execute sudo command with filter in elisp

I would like to use elisp to execute a privileged command, then use a filter to do further processing when certain output is seen.
It's my understanding, after exhaustive RTFM'ing, that I can:
Set default-directory to a path that begins with "/sudo::/".
Call start-file-process to start a process that will be run under sudo.
Here is a function I wrote that tries to do this:
(defun start-vpn (config-file password-file callback)
"Starts the VPN connection, waits for a DHCP address,
then invokes callback with the address it got."
(let* ((default-directory "/sudo::/tmp")
(buff (get-buffer-create "*openvpn*"))
(proc (start-file-process "openvpn" "*openvpn*"
"/usr/local/sbin/openvpn"
(concat "--config " config-file)
(concat "--auth-user-pass " password-file))))
(set-process-filter proc
(lambda (proc output)
(message "Got output: " output)
(let ((ip (get-vpn-ip-address output)))
(when ip
(callback ip)))))))
When I run this, I see the following output in the *Messages* buffer:
start-vpn
Tramp: Opening connection for root#localhost using sudo...
Tramp: Sending command `exec sudo -u root -s -H -p Password:'
Tramp: Waiting for prompts from remote shell
Tramp: Sending command `exec sudo -u root -s -H -p Password:'
Tramp: Found remote shell prompt on `localhost'
Tramp: Opening connection for root#localhost using sudo...done
(lambda (proc output) (message "Got output: " output) (let ((ip ...)) (if ip (progn ...))))
Got output:
...and no output in the *openvpn* buffer the function creates.
I am not an expert at elisp, so I suspect there is some stupid mistake I am making. I am also really curious about the "(lambda (proc ..." in the *Messages* buffer.
Any advice, criticism, or tips appreciated. Thanks!
First of all, the reason for seeing (lambda ... in the message buffer is that set-process-filter returns the filter function, so therefore start-vpn does too.
Your message call needs to contain a format specifier to actually show the output:
(message "Got output: %s" output)
And (callback ip) won't work for two reasons:
Emacs Lisp has separate namespaces for functions and variables, so (callback ip) will call the function callback (which doesn't exist), while you need (funcall callback ip) to call the function stored in the variable callback.
Once you're past that, since Emacs Lisp uses dynamic scope by default, by the time your lambda function gets called the binding for callback is already gone.
In Emacs 24, you can set lexical-binding to t, and the code above should work. In any case, you can explicitly use the lexical-let macro:
(lexical-let ((callback callback))
(lambda (proc output)
(message "Got output: " output)
(let ((ip (get-vpn-ip-address output)))
(when ip
(funcall callback ip))))
This macro uses black magic to preserve the value of callback inside the lambda function.

mit-scheme vim slimv: " read-error: no dispatch function defined for #\F"

It's a very easy scheme function
(define member?
(lambda (a lat)
(cond
((null? lat) #f)
(else (or (eq? (car lat) a)
(member? a (cdr lat))
))
)
)
)
However, when I pressed ,d or ,F in vim to run this function, there is an error
/home/oo/tmp/t.scm:64 read-error: no dispatch function defined for
#\F
Line: 4, Column: 21, File-Position: 64
Stream: #<SB-SYS:FD-STREAM for "file /home/oo/tmp/t.scm" {AC84DA9}>
Chris already pointed out that you tried to use Scheme code with a Common Lisp swank server.
You need to run a Scheme swank server (e.g. swank-mit-scheme.scm, also included in Slimv).
Normally Slimv should autodetect MIT scheme on Linux without any tweaking in the .vimrc. For the autodetection to work properly you need MIT Scheme installed and the scheme command be available.
I suggest that you remove any Slimv related settings from your .vimrc. Then load the .scm in Vim and type this command:
:echo SlimvSwankCommand()
If Scheme was autodetected then this should print the command that runs the Scheme swank server (search for swank-mit-scheme.scm in the output). If the autodetection was unsuccessful then either you don't have the scheme command or Slimv did not find swank-mit-scheme.scm. In this case you need to tell Slimv the command to run the Scheme swank server. You can do in by adding a similar command to your .vimrc:
let g:slimv_swank_cmd = '! xterm -e scheme --load /your-path-to/slime/contrib/swank-mit-scheme.scm &'
But do this only if autodetection fails. If you need some more assistance, please feel free to contact me, I'm the author of Slimv.

Replace isql with sqsh in emacs (Ubuntu)

Using emacs on Ubuntu 11.10. I want to connect to a SQL Server database using sqsh instead of isql. I added the following to my initi.el
(set 'sql-sybase-program "sqsh")
(set 'sql-ms-program "sqsh")
It recompiles and loads successfully. However, when I use sql-ms and try to connect to the database, I am getting errors because emacs is using lower-case command parameters when it should be using upper-case command parameters. Furthermore, I can successfully connect to the database server using sqsh from the command line. When I try to run things within emacs, I get the following error:
sqsh: -d: Invalid integer expression
Process SQL exited abnormally with code 255
I did a pretty extensive Google search and I can't find much on how to do this (which makes me think it may not be possible). Obviously, I can run sqsh from within a shell, but then I lose the SQL mode integration. I'm not sure what I can / need to do to my init.el file to make this possible.
I think all I really need to do is figure out how to get emacs to send a -D not a -d to sqsh. Apparently isql doesn't care, but sqsh cares deeply about the difference.
As you say, the real answer is to get Emacs to use -D instead of -d. However, as a workaround, running sql-sybase instead of sql-ms seems to work fine for me.
Update: Try this code, it removes the -n option from sql-ms-options and redefines sql-ms-options to use -D instead of -d as the option to select the database:
(setq sql-ms-options (remove "-n" sql-ms-options))
(defun sql-comint-ms (product options)
"Create comint buffer and connect to Microsoft SQL Server."
;; Put all parameters to the program (if defined) in a list and call
;; make-comint.
(let ((params options))
(if (not (string= "" sql-server))
(setq params (append (list "-S" sql-server) params)))
(if (not (string= "" sql-database))
(setq params (append (list "-D" sql-database) params)))
(if (not (string= "" sql-user))
(setq params (append (list "-U" sql-user) params)))
(if (not (string= "" sql-password))
(setq params (append (list "-P" sql-password) params))
(if (string= "" sql-user)
;; if neither user nor password is provided, use system
;; credentials.
(setq params (append (list "-E") params))
;; If -P is passed to ISQL as the last argument without a
;; password, it's considered null.
(setq params (append params (list "-P")))))
(sql-comint product params)))