unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Finding simpler better sudo for Emacs
  2021-03-30 10:13     ` Michael Albinus
@ 2021-03-30 10:23       ` Jean Louis
  2021-03-30 10:34         ` Michael Albinus
  0 siblings, 1 reply; 9+ messages in thread
From: Jean Louis @ 2021-03-30 10:23 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Help GNU Emacs

* Michael Albinus <michael.albinus@gmx.de> [2021-03-30 13:14]:
> Jean Louis <bugs@gnu.support> writes:
> 
> Hi Jean,
> 
> > (defun sudo (&rest arguments)
> >   "Executes list ARGUMENTS with system command `sudo'."
> >   (let ((original-directory default-directory)
> > 	(default-directory "/sudo::")
> > 	(return (shell-command-to-string (string-join arguments " "))))
> >     (setq default-directory original-directory)
> >     return))
> 
> There's no need to keep and set original-directory, this is done by the
> let wrapper.

Maybe I know what you mean, as let wrapper should not set globally the
default directory, but practically, I have shown you that it is
changing to /root so that may be something done by tramp in
background, I do not know.

> And setting default-directory doesn't do anything, you would need let* in
> your approach.

Well, the function above did not change the default directoy, I would
not know what you mean. Important in that past moment is that it did
work that way. 

> With my adapted code snippet, you could do the following in order to
> keep the current directory:
> 
(defun sudo (&rest arguments)
  "Executes list ARGUMENTS with system command `sudo'."
  (let ((default-directory
  	  (concat "/sudo::" (file-local-name default-directory))))
    (shell-command-to-string (string-join arguments " "))))

(sudo "ls") → " 0install-ea1f1e-download
 847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html
 adb.1001.log" ;; are files from my tmp

but then if I change to dired buffer ~/tmp and do: M-: -- (sudo "ls")
I get following error:

"sh: cd: /root/tmp/: No such file or directory

So, no, no, it does not work as you and me intended.

This one here still works better as it remembers the current
directory and brings it back, as Tramp probably does some change in
background, don't know why.

(defun sudo (&rest arguments)
  "Executes list ARGUMENTS with system command `sudo'."
  (let ((original-directory default-directory)
	(default-directory "/sudo::")
	(return (shell-command-to-string (string-join arguments " "))))
    (setq default-directory original-directory)
    return))
 
-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-30 10:23       ` Finding simpler better sudo for Emacs Jean Louis
@ 2021-03-30 10:34         ` Michael Albinus
  2021-03-30 10:43           ` Jean Louis
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Albinus @ 2021-03-30 10:34 UTC (permalink / raw)
  To: Help GNU Emacs

Jean Louis <bugs@gnu.support> writes:

Hi Jean,

> (defun sudo (&rest arguments)
>   "Executes list ARGUMENTS with system command `sudo'."
>   (let ((default-directory
>   	  (concat "/sudo::" (file-local-name default-directory))))
>     (shell-command-to-string (string-join arguments " "))))
>
> (sudo "ls") → " 0install-ea1f1e-download
>  847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html
>  adb.1001.log" ;; are files from my tmp
>
> but then if I change to dired buffer ~/tmp and do: M-: -- (sudo "ls")
> I get following error:
>
> "sh: cd: /root/tmp/: No such file or directory

OK, so let's do

(defun sudo (&rest arguments)
  "Executes list ARGUMENTS with system command `sudo'."
  (let ((default-directory
  	  (concat "/sudo::" (file-local-name (expand-file-name default-directory)))))
    (shell-command-to-string (string-join arguments " "))))

Best regards, Michael.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-30 10:34         ` Michael Albinus
@ 2021-03-30 10:43           ` Jean Louis
  2021-03-30 10:52             ` Michael Albinus
  0 siblings, 1 reply; 9+ messages in thread
From: Jean Louis @ 2021-03-30 10:43 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Help GNU Emacs

* Michael Albinus <michael.albinus@gmx.de> [2021-03-30 13:35]:
> Jean Louis <bugs@gnu.support> writes:
> 
> Hi Jean,
> 
> > (defun sudo (&rest arguments)
> >   "Executes list ARGUMENTS with system command `sudo'."
> >   (let ((default-directory
> >   	  (concat "/sudo::" (file-local-name default-directory))))
> >     (shell-command-to-string (string-join arguments " "))))
> >
> > (sudo "ls") → " 0install-ea1f1e-download
> >  847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html
> >  adb.1001.log" ;; are files from my tmp
> >
> > but then if I change to dired buffer ~/tmp and do: M-: -- (sudo "ls")
> > I get following error:
> >
> > "sh: cd: /root/tmp/: No such file or directory
> 
> OK, so let's do
> 
(defun sudo (&rest arguments)
  "Executes list ARGUMENTS with system command `sudo'."
  (let ((default-directory
  	  (concat "/sudo::" (file-local-name (expand-file-name default-directory)))))
    (shell-command-to-string (string-join arguments " "))))

(sudo "ls") → " 0install-ea1f1e-download
 847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html
 adb.1001.log
 ..."

(sudo "ls") → " 0install-ea1f1e-download
 847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html
 adb.1001.log
 ..."

That one works well. I will keep it.

On the other hand, now I have got concern for this command:

(defun sudo (arguments)
  "Executes list ARGUMENTS with system command `sudo'."
  (let* ((command (format "sudo su -c -- root -c \"%s\"" (string-join (list arguments))))
	 (return (shell-command-to-string command)))
    return))

As I would not like, definitely I would not like executing my sudo
commands on remote servers which I use so often with the above sudo
command.

So I would like to make sure I am on the local file system, as if I am
on /sudo:: file system or /ssh: or similar, that is not something I
would like. I have multiple notebooks which I access, imagine I change
default directory to some remote one and I am not visible in the
buffer of Dired. This happens sometimes. Then I wish to execute fan
control, but it would run on remote computer.

How to check if default directory is on local file system?

 
-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-30 10:43           ` Jean Louis
@ 2021-03-30 10:52             ` Michael Albinus
  2021-03-30 11:05               ` Jean Louis
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Albinus @ 2021-03-30 10:52 UTC (permalink / raw)
  To: Help GNU Emacs

Jean Louis <bugs@gnu.support> writes:

> How to check if default directory is on local file system?

(file-remote-p default-directory)

nil if you are on your local host, non-nil otherwise.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-30 10:52             ` Michael Albinus
@ 2021-03-30 11:05               ` Jean Louis
  2021-03-30 11:13                 ` Michael Albinus
  0 siblings, 1 reply; 9+ messages in thread
From: Jean Louis @ 2021-03-30 11:05 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Help GNU Emacs

* Michael Albinus <michael.albinus@gmx.de> [2021-03-30 13:53]:
> Jean Louis <bugs@gnu.support> writes:
> 
> > How to check if default directory is on local file system?
> 
> (file-remote-p default-directory)
> 
> nil if you are on your local host, non-nil otherwise.

Thank you, this time I was M-x apropos-ing but did not find it so
fast.

Side note on tramp, I have filed a bug on Dired/Tramp as if there is
local directory /scp:static: and I try to enter that directory I am
connected with Tramp to my remote static (hostname defined in
/etc/hosts or ~/.authinfo) server. But Dired should recognize that
marked file was on the local directory and should not go into remote
one.

In that sense if there is local directory "/scp:static:" then this
function does not work well:

(file-remote-p "/scp:static:") → "/scp:static:" while you said it
should give nil if it is local directory.

(file-remote-p "/scp:google.com:") → "/scp:google.com:" -- so this
seem that it is checking it by prefix.

That means that users are not supposed to make such local directories,
for example making a local directory /sudo: or /scp:hostname: and
similar would make Tramp fail. Emacs and Tramp rely on improbability
that users would never make such local directories. Copy and rename of
files into such local directories would probably fail, as Tramp would
try to copy it remotely.

Regarding my function, I like it to be executed only locally, and I
will skip Tramp usage for a while.

(defun sudo (arguments)
  "Executes list ARGUMENTS with system command `sudo'."
  (let ((not-remote (not (file-remote-p default-directory))))
    (if not-remote
	(let* ((command (format "sudo su -c -- root -c \"%s\"" (string-join (list arguments))))
	       (return (shell-command-to-string command)))
	  return)
      (message "This `sudo' does not work on remote directory: %s" default-directory))))

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-30 11:05               ` Jean Louis
@ 2021-03-30 11:13                 ` Michael Albinus
  2021-03-30 11:40                   ` Jean Louis
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Albinus @ 2021-03-30 11:13 UTC (permalink / raw)
  To: Help GNU Emacs

Jean Louis <bugs@gnu.support> writes:

Hi Jean,

> Side note on tramp, I have filed a bug on Dired/Tramp as if there is
> local directory /scp:static: and I try to enter that directory I am
> connected with Tramp to my remote static (hostname defined in
> /etc/hosts or ~/.authinfo) server. But Dired should recognize that
> marked file was on the local directory and should not go into remote
> one.

I've closed this, because Tramp handles this case. See my other message.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-30 11:13                 ` Michael Albinus
@ 2021-03-30 11:40                   ` Jean Louis
  0 siblings, 0 replies; 9+ messages in thread
From: Jean Louis @ 2021-03-30 11:40 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Help GNU Emacs

* Michael Albinus <michael.albinus@gmx.de> [2021-03-30 14:14]:
> Jean Louis <bugs@gnu.support> writes:
> 
> Hi Jean,
> 
> > Side note on tramp, I have filed a bug on Dired/Tramp as if there is
> > local directory /scp:static: and I try to enter that directory I am
> > connected with Tramp to my remote static (hostname defined in
> > /etc/hosts or ~/.authinfo) server. But Dired should recognize that
> > marked file was on the local directory and should not go into remote
> > one.
> 
> I've closed this, because Tramp handles this case. See my other message.

I see now, there is variable to exclude some of /root-based
directories. Unlikely, but useful.


-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Control of fan-speed on Lenovo Thinkpads
       [not found] ` <YGNq8IGh12I+QL9I@protected.localdomain>
@ 2021-03-31  5:49   ` Utkarsh Singh
  2021-03-31  6:27     ` Finding simpler better sudo for Emacs Jean Louis
  0 siblings, 1 reply; 9+ messages in thread
From: Utkarsh Singh @ 2021-03-31  5:49 UTC (permalink / raw)
  To: Jean Louis, help-gnu-emacs

Jean Louis <bugs@gnu.support> writes:

> * Utkarsh Singh <utkarsh190601@gmail.com> [2021-03-30 17:28]:
>> Hi Jean,
>> 
>> > (defun sudo (arguments)
>> >   "Executes list ARGUMENTS with system command `sudo'."
>> >   (let* ((command (format "sudo su -c -- root -c \"%s\"" (string-join (list 
>> > arguments))))
>> >          (return (shell-command-to-string command)))
>> >     return))
>> 
>> Why are you using a separate function for using sudo?
>
> That way it is distinguished.
>
>> Why not just have wrapper around call-process function?
>> 
>> Here is my approach (adapted from https://protesilaos.com/dotemacs/):
>> 
> (defun ut-common-shell-command (command &rest args)
>   "Run COMMAND with ARGS.
> Return the exit code and output in a list."
>   (with-temp-buffer
>     (list (apply 'call-process command nil (current-buffer) nil args)
>           (buffer-string))))
>
> (ut-common-shell-command "sudo su -c -- root -c \"echo level full-speed > /proc/acpi/ibm/fan\"")
>
> apply: Searching for program: No such file or directory, sudo su -c --
> root -c "echo level full-speed > /proc/acpi/ibm/fan" [2 times]
>
> Well not working how I would like it, I need to dissect it in each
> separate comand:
>
> (ut-common-shell-command "sudo" "su" "-c" "--" "root" "-c" "ls") → (0 "0install-ea1f1e-download
> 847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html
> adb.1001.log
> ")
You can use something like this if you don't want to separate thing manually:
(let* ((cmd "ls -l -a")
       (cmd-list (split-string cmd " ")))
  (apply 'ut-common-shell-command cmd-list))

>
> and I am getting lists as output.
>
> This does not work as it should:
>
> (ut-common-shell-command "sudo" "su" "-c" "--" "root" "-c" "echo level full-speed > /proc/acpi/ibm/fan\")
>
> So you see the problem?
>
> This works with my function:
>
> (sudo (format "echo level %s > %s" arg my-fan-proc-file)))
>
>> I use this by giving "sudo" as first argument.  Here is a snippet from
>> the library I have written to mount and umount USB and Android devices
>> from emacs.
>> 
>> (defun emount-umount-usb (mount-point)
>>   "Umount usb mounted at MOUNT-POINT."
>>   (interactive (list (emount--select-umount-usb (emount--get-drive-list emount--list-drive))))
>>   (let* ((result (ut-common-shell-command "sudo" "umount" mount-point))
>> 	 (exit-code (nth 0 result))
>> 	 (output (nth 1 result)))
>>     (if (eq exit-code emount--success-code)
>> 	(message "%s umount successful" mount-point)
>>       (user-error output))))
>
> That is good.
>
> You see in this case with redirection of output, it is not so easy to
> provide a command with call-process.
>
Hmm I see the problem with redirection.  Do you know any other standard
Emacs way to work with redirection? Maybe temp buffer?
-- 
Utkarsh Singh
utkarshsingh.xyz



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Finding simpler better sudo for Emacs
  2021-03-31  5:49   ` Control of fan-speed on Lenovo Thinkpads Utkarsh Singh
@ 2021-03-31  6:27     ` Jean Louis
  0 siblings, 0 replies; 9+ messages in thread
From: Jean Louis @ 2021-03-31  6:27 UTC (permalink / raw)
  To: Utkarsh Singh; +Cc: help-gnu-emacs

* Utkarsh Singh <utkarsh190601@gmail.com> [2021-03-31 08:48]:
> > You see in this case with redirection of output, it is not so easy to
> > provide a command with call-process.
> >
> Hmm I see the problem with redirection.  Do you know any other standard
> Emacs way to work with redirection? Maybe temp buffer?

There are redirection functions in Emacs. I just do not know now why
should I do it with "sudo" and I would not know how to do it. I have
no clue where to start.

I use this function to give some input as string and receive output:

(defun rcd-command-output-from-input (program input &rest args)
  "Returns output from PROGRAM INPUT with optional ARGS"
  (let* ((output (with-temp-buffer
		  (insert input)
		  (apply #'call-process-region nil nil program t t nil args)
		  (buffer-string))))
    output))

Which then enables me for example to get HTML from markdown:

(defun rcd-markdown (text)
  "Markdown processing"
  (rcd-command-output-from-input "markdown" text))

And I use the fastest Markdown there is, the Discount Markdown which
also includes the command mkd2html, that can quickly create simple
HTML pages:

(defun rcd-mkd2html (text &optional title author date)
  "Full page Markdown processing"
  (let* ((title (if title
		    (format "%% %s\n" title)
		  "% NO TITLE\n"))
	 (author (if author
		     (format "%% %s\n" author)
		   "% NO AUTHOR\n"))
	 (date  (if date
		    (format "%% %s\n" date)
		  "% NO DATE"))
	 (header (concat title author date))
	 (css-line "<style> body { max-width: 70ch; line-height: 1.5; padding: 2ch; margin: auto; font-family: \"Helvetica\", \"Arial\", sans-serif; } h1,h2,h3,h4,h5,h6 { line-height: 1.2; } pre { width: 100%; margin: 2ch; padding: 1ch; background: #f5deb3; border: 2px solid #777; } pre code { tab-width: 4; color #333; } </style>")
	 (viewport-line "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">")
	 (text (concat header "\n" text)))
    (rcd-command-output-from-input "mkd2html" text "-header" viewport-line "-header" css-line)))

You see, sudo command helps me run some commands without password if I
set sudoers file properly. But then again, to invoke redirection with
sudo it requires more fiddling, so I am spawning command "su" with
"sudo". 

Then "su" is calling shell anyway -- so it is not really process
calling as Stefan pointed out, it defeats itself right there, if I
wish to freely supply command to "sudo", so the default shell is
spawned with different user privileges in the shell.

Now I have improved it that I can use it with different username.

(defun sudo (command &optional username)
  "Execute COMMAND with system command `sudo'.

Optional argument USERNAME executes system command `sudo' with
that USERNAME privileges. 

As this command uses system command `su', it will invoke the
default shall of the USERNAME."
  (let ((not-remote (not (file-remote-p default-directory)))
	(sudo-buffer (get-buffer-create "*sudo*"))
	(current-buffer (current-buffer)))
    (switch-to-buffer sudo-buffer)
    (erase-buffer)
    (switch-to-buffer current-buffer)
    (if not-remote
	(let* ((username (or username "root"))
	       (sudo `(call-process "sudo" nil ,sudo-buffer t "su" "-c" "--" ,username "-c" ,command))
	       (status (eval sudo))
	       (status (if (= 0 status) "Success" status))
	       (current-buffer (current-buffer))
	       (output (progn
			 (switch-to-buffer sudo-buffer)
			 (buffer-string))))
	  (switch-to-buffer current-buffer)
	  (message "%s%s\nStatus: %s" output (prin1-to-string sudo) status))
      (message "This `sudo' does not work on remote directory: %s" default-directory))))

That opens possibility to quickly launch browser from different user
space, similar to how it is recommended on:

How to Run a More Secure Browser
https://www.dragonflybsd.org/docs/handbook/RunSecureBrowser/

In this case I use "iceweasel" browser, one could use something else.

(defun browse-safe-url (url)
  "Browse URL with b"
  (let ((username "louis")) ;; different username than my own
    ;; Insecurity settings for personal DISPLAY only
    (shell-command "xhost +")
    ;; Browse URL with different username
    (sudo (format "iceweasel \"%s\"" url) username)))


-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-03-31  6:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <8735wcogti.fsf@gmail.com>
     [not found] ` <YGNq8IGh12I+QL9I@protected.localdomain>
2021-03-31  5:49   ` Control of fan-speed on Lenovo Thinkpads Utkarsh Singh
2021-03-31  6:27     ` Finding simpler better sudo for Emacs Jean Louis
2021-03-29 20:36 Control of fan-speed on Lenovo Thinkpads Jean Louis
2021-03-30  8:12 ` Michael Albinus
2021-03-30  9:44   ` Jean Louis
2021-03-30 10:13     ` Michael Albinus
2021-03-30 10:23       ` Finding simpler better sudo for Emacs Jean Louis
2021-03-30 10:34         ` Michael Albinus
2021-03-30 10:43           ` Jean Louis
2021-03-30 10:52             ` Michael Albinus
2021-03-30 11:05               ` Jean Louis
2021-03-30 11:13                 ` Michael Albinus
2021-03-30 11:40                   ` Jean Louis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).