Hi!
I'd like to run a "sudo" command from Common Lisp. The following works:
--8<---------------cut here---------------start------------->8--- (uiop:launch-program '("sudo" "-S" "ls" "/root") :input :stream :output *standard-output*) (format (uiop:process-info-input #v1) "MY-PASSWORD~%") (finish-output (uiop:process-info-input #v1)) --8<---------------cut here---------------end--------------->8---
Note that I'm using the "-S" parameter of sudo. From the man page:
Write the prompt to the standard error and read the password from the standard input instead of using the terminal device.
Without it, "sudo" terminate immediately.
Somehow, Emacs _does_ support calling the sudo process without the "-S" flag. Try this:
--8<---------------cut here---------------start------------->8--- (make-process :name "dummy" :command '("sudo" "ls" "/root")) --8<---------------cut here---------------end--------------->8---
and the "sudo" process is kindly waiting for input in the background.
Any idea why that is? Is it be possible to do the same in Common Lisp?
Cheers!
Emacs by default allocates a pty for subprocesses. There’s no way to do this portably, as many Lisps don’t support it, so UIOP won’t help you here. If you’re on SBCL and portability is not a concern, you can use sb-ext:run-program with a :pty keyword argument, as described in section 7.7.3 of the SBCL manual. Failing that, it’s probably best to use sudo -S.
phoebe
On Jan 12, 2021, at 10:01 AM, Pierre Neidhardt mail@ambrevar.xyz wrote:
Hi!
I'd like to run a "sudo" command from Common Lisp. The following works:
--8<---------------cut here---------------start------------->8--- (uiop:launch-program '("sudo" "-S" "ls" "/root") :input :stream :output *standard-output*) (format (uiop:process-info-input #v1) "MY-PASSWORD~%") (finish-output (uiop:process-info-input #v1)) --8<---------------cut here---------------end--------------->8---
Note that I'm using the "-S" parameter of sudo. From the man page:
Write the prompt to the standard error and read the password from the standard input instead of using the terminal device.
Without it, "sudo" terminate immediately.
Somehow, Emacs _does_ support calling the sudo process without the "-S" flag. Try this:
--8<---------------cut here---------------start------------->8--- (make-process :name "dummy" :command '("sudo" "ls" "/root")) --8<---------------cut here---------------end--------------->8---
and the "sudo" process is kindly waiting for input in the background.
Any idea why that is? Is it be possible to do the same in Common Lisp?
Cheers!
-- Pierre Neidhardt https://ambrevar.xyz/
Thanks for the details, this makes sense! :)
The problem with -S is that I need to pass it systematically. Worse: I cannot invoke shell scripts that call `sudo' without -S.
So instead I ended up adding this to my ~/.slynk.lisp:
--8<---------------cut here---------------start------------->8--- (let ((askpass (format nil "~a/.guix-extra-profiles/common-lisp/common-lisp/bin/lxqt-openssh-askpass" (uiop:getenv "HOME")) )) (when (uiop:file-exists-p askpass) (setf (uiop:getenv "SUDO_ASKPASS") askpass))) --8<---------------cut here---------------end--------------->8---
Works perfectly for me now! :)
Thanks!
On Tue, 2021-01-12 at 10:15 -0600, Phoebe Goldman wrote:
Emacs by default allocates a pty for subprocesses. There’s no way to do this portably, as many Lisps don’t support it, so UIOP won’t help you here. If you’re on SBCL and portability is not a concern, you can use sb-ext:run-program with a :pty keyword argument, as described in section 7.7.3 of the SBCL manual. Failing that, it’s probably best to use sudo -S.
While it looks like Pierre has his own solution, I thought I would mention this for posterity on the list: "script" is a relatively portable unix command that will allocate a pty for running. If you need a pty on a unix then it's probably your best-bet if you don't want to be tied to sb-ext:run-program.
Thanks for sharing, this could be interesting indeed. How would you run it in SLY or SLIME then? Do you have an example recipe?
On Tue, 12 Jan 2021 19:14:15 +0100 Pierre Neidhardt mail@ambrevar.xyz wrote:
Thanks for sharing, this could be interesting indeed. How would you run it in SLY or SLIME then? Do you have an example recipe?
Oh, I missed this e-mail somehow. Here's an example:
(with-input-from-string (s (format nil "mypassword~%")) (uiop:run-program '("script" "-c" "sudo ls") :input s :output :string))
Notes:
1. sudo does have "-S" to prevent it from requiring a pty, but this was the original question, so it's what I used.
2. The parameter to "-c" ("sudo ls" above) will be interpreted by the shell.
Thanks for the example!
This would work, but as opposed to setting SUDO_ASKPASS as mentioned before, this approach has the drawback that you cannot pass an input to the subcommand.
Anyways, one way or another, problem solved! Thanks!