Repository navigation
rpi-eeprom-config: Allow arguments in EDITOR for --edit - #908
Conversation
timg236
left a comment
There was a problem hiding this comment.
Thanks, the intent is right and the exit-code reporting is an improvement. Three behaviour changes relative to the current os.system path are noted inline; the first one needs fixing before this can be merged.
| # Like git and crontab, allow $EDITOR to carry arguments, e.g. 'code --wait'. | ||
| cmd = shlex.split(editor) + [tmp_conf] | ||
| try: | ||
| result = subprocess.call(cmd) |
There was a problem hiding this comment.
This regresses Ctrl-C handling inside the editor. system(3) ignores SIGINT and SIGQUIT in the parent for the duration of the call, so only the editor sees the keypress (vim uses Ctrl-C to return to normal mode, nano to show the cursor position). With subprocess.call the terminal delivers SIGINT to the whole foreground group, Python raises KeyboardInterrupt in wait(), subprocess.call kills the child, the handler in main prints Interrupted, and exit_handler removes the temp directory from under the editor. The SIGKILLed editor cannot restore termios, so the terminal is left in raw/no-echo mode.
Please ignore SIGINT and SIGQUIT around the call and restore them afterwards, as git's launch_editor does:
old_int = signal.signal(signal.SIGINT, signal.SIG_IGN)
old_quit = signal.signal(signal.SIGQUIT, signal.SIG_IGN)
try:
result = subprocess.call(cmd)
finally:
signal.signal(signal.SIGINT, old_int)
signal.signal(signal.SIGQUIT, old_quit)| cmd = "\'%s\' \'%s\'" % (editor, tmp_conf) | ||
| result = os.system(cmd) | ||
| # Like git and crontab, allow $EDITOR to carry arguments, e.g. 'code --wait'. | ||
| cmd = shlex.split(editor) + [tmp_conf] |
There was a problem hiding this comment.
shlex.split raises ValueError on an unbalanced quote and nothing catches it, so EDITOR="vim -c 'set" rpi-eeprom-config -e now dies with a Python traceback (ValueError: No closing quotation). Before this change the shell reported a syntax error and the existing non-zero path aborted cleanly. Please catch ValueError here and route it through exit_error.
| try: | ||
| result = subprocess.call(cmd) | ||
| except OSError as e: | ||
| exit_error("Aborting update because \'%s\' could not be started: %s" % (editor, e.strerror)) |
There was a problem hiding this comment.
The paths-with-spaces change is acknowledged in the description and is fine, but this message hides the cause. A user who had EDITOR="/opt/My Editor/ed" working now sees '/opt/My Editor/ed' could not be started: No such file or directory although that path exists, because the argv is actually ['/opt/My', 'Editor/ed', ...]. Printing cmd[0], or the shlex-quoted cmd that the branch below already builds, would make it obvious the value was split. Worth a note in the --edit help text too, which currently only says EDITOR may be overridden.
|
Thanks for the careful review. All three are addressed in c6edcc8:
Tested on a Pi 5 under
|
|
Please could you squash the commits before merging? |
--edit quoted the whole of $EDITOR as one word, so an editor given with arguments, such as EDITOR="code --wait" or "nano -w", failed with "not found". git and crontab -e accept the same value. Split it with shlex and run it without a shell. While the editor runs, ignore SIGINT and SIGQUIT, as system(3) and git's launch_editor do, so Ctrl-C reaches only the editor instead of interrupting rpi-eeprom-config and removing the temp directory. They are ignored after the editor starts so it does not inherit SIG_IGN. The abort message also printed the raw wait status from os.system (32512 for a missing editor, 256 for exit 1). It now reports the editor's exit code, reports an EDITOR with unbalanced quotes through exit_error instead of a ValueError traceback, and names the program that could not be started (cmd[0]), so an unquoted path with spaces shows where it was split. The --edit help text documents the quoting. Signed-off-by: Roy <rongh7426@gmail.com>
c6edcc8 to
b05bd19
Compare
|
Squashed into a single commit (b05bd19). The code is unchanged. Thanks for the review! |
|
Thanks! |
rpi-eeprom-config --editquotes the whole of$EDITORas a single word before passing it toos.system, so an editor given with arguments fails:crontab -eand git accept the same value (EDITOR="code --wait"is the common case). This splits$EDITORwithshlexand runs it withsubprocess.call, without a shell. The abort message also showed the rawos.systemwait status (32512, 256); it now shows the editor's exit code, and says when the editor cannot be started.Tested on a Pi 5 (Debian trixie, rpi-eeprom 28.30-1) with editors that make
--editabort, so nothing was staged (/boot/firmware/pieeprom.updabsent afterwards):EDITORtruncate -s 0''truncate -s 0' '…'' exited with code 32512'…/boot.conf' appears to be emptyfalseexited with code 256exited with code 1no-such-editorexited with code 32512'no-such-editor' could not be started: No such file or directorysh -c "exit 3" shexited with code 32512exited with code 3One behaviour change: an editor path containing spaces now needs quoting inside
EDITOR(e.g.EDITOR='"/opt/My Editor/ed"'), the same as for git and crontab.shlex.joinis avoided so this still runs on Python 3.7.