Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions called in opposite order in midnight commander subshell #140

Closed
josef-kyrian opened this issue Mar 6, 2023 · 2 comments
Closed

Comments

@josef-kyrian
Copy link

I have defined simple functions for test and added to .bashrc. They print command to run and it's return code

preexec() { echo "RUN: $1"; }
precmd() { echo "EXIT: $?"; }
source ~/.bash-preexec.sh

In bash shell it's working ok:

# ls /
RUN: ls /
bin  boot  cdrom  dev  etc  home  initrd.img  lib  lib32  lib64  lxc  media  mnt  opt  proc  root  run  sbin  snap  srv  sys  tmp  usr  var  vmlinuz  www
EXIT: 0

But in midnight commander subshell functions are called in opposite order

# ls /
bin  boot  cdrom  dev  etc  home  initrd.img  lib  lib32  lib64  lxc  media  mnt  opt  proc  root  run  sbin  snap  srv  sys  tmp  usr  var  vmlinuz  www
EXIT: 0
RUN: ls /

What's wrong? Thanks for help

@akinomyoga
Copy link
Contributor

bash-preexec doesn't support the case where PROMPT_COMMAND is modified after the shell startup and the first prompt. However, Midnight Commander installs its hook by directly inputting PROMPT_COMMAND+=..., etc. as user commands from stdin after starting the shell.

More specifically, bash-preexec requires that all the other PROMPT_COMMAND hooks are enclosed between __bp_precmd_invoke_cmd and __bp_interactive_mode. This is normally achieved through the initial DEBUG trap (__bp_install) installed by bash-preexec. However, Midnight Commander injects codes after the shell startup and modifies PROMPT_COMMAND. This results in the following value of PROMPT_COMMAND:

$ declare -p PROMPT_COMMAND
declare -- PROMPT_COMMAND=$'__bp_precmd_invoke_cmd\n__bp_interactive_mode\npwd>&11;kill -STOP $$'

The substring pwd>&11;kill -STOP $$ is the hook installed by mc. We can see that the mc hook string is not enclosed within __bp_precmd_invoke_cmd and __bp_interactive_mode. Instead, this should look like the following:

PROMPT_COMMAND=$'__bp_precmd_invoke_cmd\npwd>&11;kill -STOP $$\n__bp_interactive_mode'

I'm not sure if there is a solution at the user side.

@josef-kyrian
Copy link
Author

Thanks, this info is enough for me.

After patching subshell/common.c in the mc sources it works like a charm!

--- common.c    2023-03-06 13:14:44.536493089 +0100
+++ common.c.patched    2023-03-06 13:13:51.448906309 +0100
@@ -825,7 +825,7 @@
     {
     case SHELL_BASH:
         g_snprintf (precmd, buff_size,
-                    " PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND\n}'pwd>&%d;kill -STOP $$'\n"
+                    " PROMPT_COMMAND='__bp_precmd_invoke_cmd\npwd>&%d;kill -STOP $$\n__bp_interactive_mode'\n"
                     "PS1='\\u@\\h:\\w\\$ '\n", subshell_pipe[WRITE]);
         break;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants