* Control of fan-speed on Lenovo Thinkpads @ 2021-03-29 20:36 Jean Louis 2021-03-30 8:12 ` Michael Albinus 0 siblings, 1 reply; 21+ messages in thread From: Jean Louis @ 2021-03-29 20:36 UTC (permalink / raw) To: Help GNU Emacs Here is how I control Lenovo Thinkpad T410 (and others) fan speed. I remember controlling it on different notebooks, I just forgot which. You may find that you need to change variable `my-fan-proc-file' to something else. Most of people do not need this, it will be automatically controlled. But I need it sometimes to cool down my fan and my palms. (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)) (defvar my-fan-proc-file "/proc/acpi/ibm/fan") (defun fan-speed (arg) "Controls fan speed provided user has superuser rights and system command `sudo' works without password. Function will mostly work on Lenovo Thinkpad notebooks. Prefix argument ARG shall be numbers from 1 to 9. Numbers from 1 to 7 determine the fan speed level, number 8 represents auto fan speed level and number 9 represents full fan speed. Activate with `C-u NUMBER M-x fan-speed'. If invoked without arguments it will show the contents of the fan control file." (interactive "P") (when (and (file-exists-p my-fan-proc-file) (rcd-which "sudo")) (if arg (cond ((= arg 7) (sudo (format "echo level %s >> %s" arg my-fan-proc-file))) ((= arg 8) (sudo (format "echo level auto >> %s" my-fan-proc-file))) ((= arg 9) (sudo (format "echo level full-speed >> %s" my-fan-proc-file))) ((and (< arg 7) (> arg 0)) (if (y-or-n-p (format "Really set fan speed to %s?" arg)) (sudo (format "echo level %s >> %s" 7 my-fan-proc-file)))) (t (message "Supply better numeric argument to this function from 1 to 9."))) (message (file-to-string my-fan-proc-file))))) Thanks, Jean Louis Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 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:42 ` Jean Louis ` (2 more replies) 0 siblings, 3 replies; 21+ messages in thread From: Michael Albinus @ 2021-03-30 8:12 UTC (permalink / raw) To: Jean Louis; +Cc: Help GNU Emacs Jean Louis <bugs@gnu.support> writes: Hi, > (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)) This could be (defun sudo (&rest arguments) "Executes list ARGUMENTS with system command `sudo'." (let ((default-directory "/sudo::")) (shell-command-to-string (string-join arguments " ")))) > Thanks, > Jean Louis Best regards, Michael. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-30 8:12 ` Michael Albinus @ 2021-03-30 9:42 ` Jean Louis 2021-03-30 9:44 ` Jean Louis 2021-03-30 15:01 ` Control of fan-speed on Lenovo Thinkpads Stefan Monnier 2 siblings, 0 replies; 21+ messages in thread From: Jean Louis @ 2021-03-30 9:42 UTC (permalink / raw) To: Michael Albinus; +Cc: Help GNU Emacs * Michael Albinus <michael.albinus@gmx.de> [2021-03-30 11:13]: > Jean Louis <bugs@gnu.support> writes: > > Hi, > > > (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)) > > This could be > (defun sudo (&rest arguments) "Executes list ARGUMENTS with system command `sudo'." (let ((default-directory "/sudo::")) (shell-command-to-string (string-join arguments " ")))) thank you. I will keep it for future considerations. I think it works slower as it invokes tramp and many other functions in background. Is there any practical benefit? I have tried using that function with (sudo "ls") and first I got the ~/tmp directory listing, then in second invokation, I got only "bin" listing, as it changed to default directory to be /root where I have "bin" only. My function would not change default-directory to /root -- maybe that is result of using default-directory, and it remains so maybe for the rest of tramp session. Try it out, it makes no sense to be changed. Your function that involves Tramp processes: (sudo "ls") → "admin_Leo babel-6KitXT babel-cyz28q babel-YJWc0L babel-ZlWVex" this is because I invoked editing of email message file in ~/tmp but on second invokation, without changing anything, few seconds thereafter: (sudo "ls") → "bin " (sudo "pwd") → "/root " This could be a bug, I do not know why should default directory be changed to "/root" if I am not root, but used /sudo:: (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)) (sudo "ls") → " 0install-ea1f1e-download 847cf980479cf1dd15482464efa8620ca98c1c93c5a3ac1e2a1dd24918b9cd46.html adb.1001.log ... and others in ~/tmp " Repeated (sudo "ls") shows same thing, without tramp. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-30 8:12 ` Michael Albinus 2021-03-30 9:42 ` Jean Louis @ 2021-03-30 9:44 ` Jean Louis 2021-03-30 10:13 ` Michael Albinus 2021-03-30 15:01 ` Control of fan-speed on Lenovo Thinkpads Stefan Monnier 2 siblings, 1 reply; 21+ messages in thread From: Jean Louis @ 2021-03-30 9:44 UTC (permalink / raw) To: Michael Albinus; +Cc: Help GNU Emacs * Michael Albinus <michael.albinus@gmx.de> [2021-03-30 11:14]: > This could be > > (defun sudo (&rest arguments) > "Executes list ARGUMENTS with system command `sudo'." > (let ((default-directory "/sudo::")) > (shell-command-to-string (string-join arguments " ")))) (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)) This way it works better. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 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 0 siblings, 1 reply; 21+ messages in thread From: Michael Albinus @ 2021-03-30 10:13 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 ((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. And setting default-directory doesn't do anything, you would need let* in your approach. 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 " ")))) Best regards, Michael. ^ permalink raw reply [flat|nested] 21+ messages in thread
* 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-30 8:12 ` Michael Albinus 2021-03-30 9:42 ` Jean Louis 2021-03-30 9:44 ` Jean Louis @ 2021-03-30 15:01 ` Stefan Monnier 2021-03-30 20:06 ` Jean Louis 2 siblings, 1 reply; 21+ messages in thread From: Stefan Monnier @ 2021-03-30 15:01 UTC (permalink / raw) To: help-gnu-emacs > (defun sudo (&rest arguments) > "Executes list ARGUMENTS with system command `sudo'." > (let ((default-directory "/sudo::")) > (shell-command-to-string (string-join arguments " ")))) Please don't `string-join` arguments and please don't use a shell when it's not necessary: they're recipes for quoting bugs. Better use something like `file-process` here. Stefan ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-30 15:01 ` Control of fan-speed on Lenovo Thinkpads Stefan Monnier @ 2021-03-30 20:06 ` Jean Louis 2021-03-31 1:23 ` Stefan Monnier 0 siblings, 1 reply; 21+ messages in thread From: Jean Louis @ 2021-03-30 20:06 UTC (permalink / raw) To: Stefan Monnier; +Cc: help-gnu-emacs * Stefan Monnier <monnier@iro.umontreal.ca> [2021-03-30 18:03]: > > (defun sudo (&rest arguments) > > "Executes list ARGUMENTS with system command `sudo'." > > (let ((default-directory "/sudo::")) > > (shell-command-to-string (string-join arguments " ")))) > > Please don't `string-join` arguments and please don't use a shell when > it's not necessary: they're recipes for quoting bugs. > Better use something like `file-process` here. Yes, you are right, that it works well is coincidence. I think that string-join came from earlier command which used call-process or similar where arguments are separate. I have improved my command, and it still works well. (defun sudo (command) "Execute COMMAND 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\"" command)) (return (shell-command-to-string command))) return) (message "This `sudo' does not work on remote directory: %s" default-directory)))) You probably mean process-file? There is no file-process. There is practical burden to use call-process, and it is with &rest ARGS, as those have to be given all separately. One echo to file and command with sudo becomes very complex, and it does not work: (call-process "/usr/bin/sudo" nil (get-buffer-create "sudo") nil "su" "-c" "--" "root" "-c" "echo" "level" "full-speed" ">" "/proc/acpi/ibm/fan") (call-process "/usr/bin/sudo" nil (get-buffer-create "sudo") nil "su" "-c" "--" "root" "-c" "echo" "hello" ">" "/tmp/text.txt") → 0 -- but does not produce /tmp/text.txt, so I do not know how to use it. Then again I would like to pass a command, and not quote each part of command as arguments. I would like something like (sudo "echo hello > /proc/file") that it works. But for that to work, how I understand, I need to split string with spaces, remove empty strings maybe, and then pass it as list as ARGS to call-process. (setq args '("su" "-c" "--" "root" "-c" "echo" "level" "full-speed" ">" "/proc/acpi/ibm/fan")) (call-process "sudo" nil t t args) -> this will not work, so to pass it as a list there, I would need to make a macro expansion? `(call-process "sudo" nil (get-buffer-create "sudo") nil ,@args) → (call-process "sudo" nil (get-buffer-create "sudo") nil "su" "-c" "--" "root" "-c" "echo" "level" "full-speed" ">" "/proc/acpi/ibm/fan") (defun sudo (command) "Execute COMMAND with system command `sudo'." (let ((not-remote (not (file-remote-p default-directory)))) (if not-remote (let* ((sudo "sudo") (args (append '("su" "-c" "--" "root" "-c") (split-string command))) (status `(call-process ,sudo nil (get-buffer-create "*sudo*") t ,@args))) (message "%s" status) (eval status))))) By using that above function, this will work: (sudo "ls") but this will not work: (sudo "ls /boot /var") -- so I do not know how to expand the list properly in the function. I would like to get following to work in simpler way by providing string: (sudo "echo level full-speed > /proc/acpi/ibm/fan") -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-30 20:06 ` Jean Louis @ 2021-03-31 1:23 ` Stefan Monnier 2021-03-31 5:35 ` Jean Louis 0 siblings, 1 reply; 21+ messages in thread From: Stefan Monnier @ 2021-03-31 1:23 UTC (permalink / raw) To: help-gnu-emacs > You probably mean process-file? There is no file-process. Indeed, sorry. > There is practical burden to use call-process, and it is with &rest > ARGS, as those have to be given all separately. There is no such extra burden. Arguments always have to be given separately. If you forget about that, you get bugs and associated security holes. Executing a process is not the same as executing an `shell` command. The first is a fairly simple and safe operation (assuming you trust the executable you're launching), whereas the second is tricky and risky unless you're extra careful to quote everything just right and you're sure the shell is really the one you expect, etc... And if you really indeed get a shell command as input instead of an executable along with its list of arguments, then it's trivial to turn from `command` to `&rest args` by simply doing (list shell-file-name shell-command-switch command). Stefan ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-31 1:23 ` Stefan Monnier @ 2021-03-31 5:35 ` Jean Louis 2021-03-31 14:23 ` Stefan Monnier 0 siblings, 1 reply; 21+ messages in thread From: Jean Louis @ 2021-03-31 5:35 UTC (permalink / raw) To: Stefan Monnier; +Cc: help-gnu-emacs * Stefan Monnier <monnier@iro.umontreal.ca> [2021-03-31 04:24]: > > You probably mean process-file? There is no file-process. > > Indeed, sorry. > > > There is practical burden to use call-process, and it is with &rest > > ARGS, as those have to be given all separately. > > There is no such extra burden. Arguments always have to be given > separately. If you forget about that, you get bugs and associated > security holes. Executing a process is not the same as executing an > `shell` command. The first is a fairly simple and safe operation > (assuming you trust the executable you're launching), whereas the second > is tricky and risky unless you're extra careful to quote everything just > right and you're sure the shell is really the one you expect, etc... Yes, and I follow the advise. This works well: (shell-command "sudo su -c -- root -c \"echo level full-speed > /proc/acpi/ibm/fan\"") While the argument after last "-c" has to be full line, which again defeats the principle of being extra carefull and quoting everything in this "sudo" example. Other commands are fine. Following line works. (call-process "sudo" nil (get-buffer-create "*sudo*") t "su" "-c" "--" "root" "-c" "echo level auto > /proc/acpi/ibm/fan") Thus based on that line, it become clear that "sudo" command that shall be able to redirect output must be made in such way to defeat the purpose of quoting and being careful. Thus the following line works with the function below without problems. I have now implemented your advise but probably not in the spirit how it was meant. but I do not know how to add the command to below call-process line without making macro and using eval. (sudo "echo level full-speed > /proc/acpi/ibm/fan") (defun sudo (command) "Execute COMMAND with system command `sudo'." (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* ((sudo `(call-process "sudo" nil ,sudo-buffer t "su" "-c" "--" "root" "-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 "%sStatus: %s" output status)) (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] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-31 5:35 ` Jean Louis @ 2021-03-31 14:23 ` Stefan Monnier 2021-03-31 20:02 ` Jean Louis 0 siblings, 1 reply; 21+ messages in thread From: Stefan Monnier @ 2021-03-31 14:23 UTC (permalink / raw) To: help-gnu-emacs > (let* ((sudo `(call-process "sudo" nil ,sudo-buffer t "su" "-c" "--" "root" "-c" ,command)) > (status (eval sudo)) Why? No kitten needs to suffer here: (let* ((status (call-process "sudo" nil sudo-buffer t "su" "-c" "--" "root" "-c" command)) -- Stefan ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-31 14:23 ` Stefan Monnier @ 2021-03-31 20:02 ` Jean Louis 2021-03-31 20:19 ` Stefan Monnier 0 siblings, 1 reply; 21+ messages in thread From: Jean Louis @ 2021-03-31 20:02 UTC (permalink / raw) To: Stefan Monnier; +Cc: help-gnu-emacs * Stefan Monnier <monnier@iro.umontreal.ca> [2021-03-31 17:24]: > > (let* ((sudo `(call-process "sudo" nil ,sudo-buffer t "su" "-c" "--" "root" "-c" ,command)) > > (status (eval sudo)) > > Why? No kitten needs to suffer here: > > (let* ((status (call-process "sudo" nil sudo-buffer t "su" "-c" "--" "root" "-c" command)) In that specific case yes. It works, I changed it. But it defeats itself in purpose, do you see? That COMMAND is parameter to `su' which invokes default user's shell. I don't find it bad, it just defeats the purpose of `call-process'. On the other hand, something like this would not work: (call-process "dmesg" nil (get-buffer-create "*out*") t "-l info") → 1 with message "dmesg: unknown level ' info'" but this works: (call-process "dmesg" nil (get-buffer-create "*out*") t "-l" "info") → 0 Maybe `call-process' is not that much safer than `shell-command', as with some dangerous arguments it could execute wrongly. I find it beneficial that one can forget about quoting. (call-process "echo" nil (get-buffer-create "*out*") t "-n" "Hello there") → 0 -- works well even with new line. (call-process "echo" nil (get-buffer-create "*out*") t "-n" "Hello \"there\" 'Somebody here' and ''' more than that.") → 0 with message: Hello "there" 'Somebody here' and ''' more than that. For me it brings main benefit that I can forget about problems of quoting. I will be replacing `shell-command' in those functions where quoting is possible problem. Example would be here, where `figlet' accepts strings but then with `shell-command' I would need to take care of proper quoting. (defvar figlet-history nil) (defvar figlet-font-history nil) (defun figlet () (interactive) (let* ((fonts '("banner" "big" "block" "bubble" "digital" "ivrit" "lean" "mini" "mnemonic" "script" "shadow" "slant" "small" "smscript" "smshadow" "smslant" "standard" "term")) (font (completing-read "Font: " fonts nil t (car figlet-font-history) 'figlet-font-history)) (text (read-from-minibuffer "Text: " (car figlet-history) nil nil 'figlet-history)) (command (format "figlet -f %s \"%s\"" font text)) (figlet (shell-command-to-string command))) (if buffer-read-only (message figlet) (insert figlet)))) Then such can be improved so that programmer does not think of quoting: (defun figlet () (interactive) (let* ((fonts '("banner" "big" "block" "bubble" "digital" "ivrit" "lean" "mini" "mnemonic" "script" "shadow" "slant" "small" "smscript" "smshadow" "smslant" "standard" "term")) (font (completing-read "Font: " fonts nil t (car figlet-font-history) 'figlet-font-history)) (text (read-from-minibuffer "Text: " (car figlet-history) nil nil 'figlet-history))) (call-process "figlet" nil t nil "-f" font text))) Where one can insert any kind of quotes in the string: +-+-+-+-+-+-+-+ +-+-+-+-+-+ |"|t|h|a|n|k|"| |"|y|o|u|"| +-+-+-+-+-+-+-+ +-+-+-+-+-+ or +-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+ +-+-+ +-+-+ +-+-+-+-+-+ +-+-+-+ +-+ |'|'|T|h|i|s| |i|s| |'|'|F|u|n|n|y|'| |\|'| |i|t| |w|o|r|k|s| |a|l|l| |-| +-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+ +-+-+ +-+-+ +-+-+-+-+-+ +-+-+-+ +-+ +-+-+-+-+-+-+-+-+-+-+ |||@|\|"|n|i|c|e|\|"| +-+-+-+-+-+-+-+-+-+-+ -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns Sign an open letter in support of Richard M. Stallman https://rms-support-letter.github.io/ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-31 20:02 ` Jean Louis @ 2021-03-31 20:19 ` Stefan Monnier 2021-04-01 9:46 ` Jean Louis 0 siblings, 1 reply; 21+ messages in thread From: Stefan Monnier @ 2021-03-31 20:19 UTC (permalink / raw) To: help-gnu-emacs > * Stefan Monnier <monnier@iro.umontreal.ca> [2021-03-31 17:24]: >> > (let* ((sudo `(call-process "sudo" nil ,sudo-buffer t "su" "-c" "--" "root" "-c" ,command)) >> > (status (eval sudo)) >> >> Why? No kitten needs to suffer here: >> >> (let* ((status (call-process "sudo" nil sudo-buffer t "su" "-c" "--" "root" "-c" command)) > > In that specific case yes. It works, I changed it. But it defeats > itself in purpose, do you see? That COMMAND is parameter to `su' which > invokes default user's shell. I don't find it bad, it just defeats the > purpose of `call-process'. You still have the risk of "command" being incorrect because of messed up quoting, but not because of the shell you yourself invoke: just because of the shell invoked by `su`. And since "command" is what you receive you can't do much better than that anyway. Stefan ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Control of fan-speed on Lenovo Thinkpads 2021-03-31 20:19 ` Stefan Monnier @ 2021-04-01 9:46 ` Jean Louis 0 siblings, 0 replies; 21+ messages in thread From: Jean Louis @ 2021-04-01 9:46 UTC (permalink / raw) To: Stefan Monnier; +Cc: help-gnu-emacs * Stefan Monnier <monnier@iro.umontreal.ca> [2021-03-31 23:20]: > > * Stefan Monnier <monnier@iro.umontreal.ca> [2021-03-31 17:24]: > >> > (let* ((sudo `(call-process "sudo" nil ,sudo-buffer t "su" "-c" "--" "root" "-c" ,command)) > >> > (status (eval sudo)) > >> > >> Why? No kitten needs to suffer here: > >> > >> (let* ((status (call-process "sudo" nil sudo-buffer t "su" "-c" "--" "root" "-c" command)) > > > > In that specific case yes. It works, I changed it. But it defeats > > itself in purpose, do you see? That COMMAND is parameter to `su' which > > invokes default user's shell. I don't find it bad, it just defeats the > > purpose of `call-process'. > > You still have the risk of "command" being incorrect because of > messed up quoting, but not because of the shell you yourself invoke: just > because of the shell invoked by `su`. And since "command" is what you > receive you can't do much better than that anyway. Thank you. The lesson is more important than this particular `sudo' function. As now I have to improve other 158 functions with `shell-command' for safety of quoting. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns Sign an open letter in support of Richard M. Stallman https://rms-support-letter.github.io/ ^ permalink raw reply [flat|nested] 21+ messages in thread
[parent not found: <8735wcogti.fsf@gmail.com>]
[parent not found: <YGNq8IGh12I+QL9I@protected.localdomain>]
* 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; 21+ 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] 21+ messages in thread
* Re: Finding simpler better sudo for Emacs 2021-03-31 5:49 ` Utkarsh Singh @ 2021-03-31 6:27 ` Jean Louis 0 siblings, 0 replies; 21+ 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] 21+ messages in thread
end of thread, other threads:[~2021-04-01 9:46 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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:42 ` Jean Louis 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 2021-03-30 15:01 ` Control of fan-speed on Lenovo Thinkpads Stefan Monnier 2021-03-30 20:06 ` Jean Louis 2021-03-31 1:23 ` Stefan Monnier 2021-03-31 5:35 ` Jean Louis 2021-03-31 14:23 ` Stefan Monnier 2021-03-31 20:02 ` Jean Louis 2021-03-31 20:19 ` Stefan Monnier 2021-04-01 9:46 ` Jean Louis [not found] <8735wcogti.fsf@gmail.com> [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
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).