From b64512b750351d83691c02e5bf118d3e00dae85f Mon Sep 17 00:00:00 2001 From: d3m3t3r <46783027+d3m3t3r@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:42:56 +0000 Subject: [PATCH 1/8] Ticket #3748: add support for ksh in subshell Support Korn shell variants (ksh/oksh/mksh) in the subshell. --- doc/man/mc.1.in | 4 ++++ lib/fileloc.h | 1 + lib/mcconfig/paths.c | 1 + lib/shell.c | 21 +++++++++++++++++++++ lib/shell.h | 3 ++- src/subshell/common.c | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 63 insertions(+), 1 deletion(-) diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in index aebc9ba1f0..e0ac3cfefe 100644 --- a/doc/man/mc.1.in +++ b/doc/man/mc.1.in @@ -2406,6 +2406,10 @@ and special keyboard maps in ~/.local/share/mc/inputrc (fallback ~/.inputrc). .B ash/dash users (BusyBox or Debian) may specify startup commands in ~/.local/share/mc/ashrc (fallback ~/.profile). .PP +.B ksh +users (ksh, oksh or mksh) may specify startup commands in ~/.local/share/mc/kshrc +(fallback $ENV or ~/.profile). +.PP .B zsh users may specify startup commands in ~/.local/share/mc/.zshrc (fallback ~/.zshrc). .PP diff --git a/lib/fileloc.h b/lib/fileloc.h index a075d030f9..fe40a0fdce 100644 --- a/lib/fileloc.h +++ b/lib/fileloc.h @@ -53,6 +53,7 @@ #define MC_BASHRC_FILE "bashrc" #define MC_ZSHRC_FILE ".zshrc" #define MC_ASHRC_FILE "ashrc" +#define MC_KSHRC_FILE "kshrc" #define MC_INPUTRC_FILE "inputrc" #define MC_CONFIG_FILE "ini" #define MC_EXT_FILE "mc.ext.ini" diff --git a/lib/mcconfig/paths.c b/lib/mcconfig/paths.c index 1baca54b8e..79309d0c17 100644 --- a/lib/mcconfig/paths.c +++ b/lib/mcconfig/paths.c @@ -75,6 +75,7 @@ static const struct { &mc_data_str, MC_SKINS_DIR }, { &mc_data_str, VFS_SHELL_PREFIX }, { &mc_data_str, MC_ASHRC_FILE }, + { &mc_data_str, MC_KSHRC_FILE }, { &mc_data_str, MC_BASHRC_FILE }, { &mc_data_str, MC_INPUTRC_FILE }, { &mc_data_str, MC_ZSHRC_FILE }, diff --git a/lib/shell.c b/lib/shell.c index 730ded43ce..e018d17c08 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -80,6 +80,8 @@ mc_shell_get_installed_in_system (void) mc_shell->path = g_strdup ("/bin/tcsh"); else if (access ("/bin/csh", X_OK) == 0) mc_shell->path = g_strdup ("/bin/csh"); + else if (access ("/bin/ksh", X_OK) == 0) + mc_shell->path = g_strdup ("/bin/ksh"); /* No fish as fallback because it is so much different from other shells and * in a way exotic (even though user-friendly by name) that we should not * present it as a subshell without the user's explicit intention. We rather @@ -189,6 +191,17 @@ mc_shell_recognize_real_path (mc_shell_t *mc_shell) mc_shell->type = SHELL_ASH_BUSYBOX; mc_shell->name = mc_shell->path; } + else if (strstr (mc_shell->path, "/ksh") != NULL + || strstr (mc_shell->real_path, "/ksh") != NULL + || strstr (mc_shell->path, "/oksh") != NULL + || strstr (mc_shell->real_path, "/oksh") != NULL + || strstr (mc_shell->path, "/mksh") != NULL + || strstr (mc_shell->real_path, "/mksh") != NULL) + { + /* Korn shell variants */ + mc_shell->type = SHELL_KSH; + mc_shell->name = "ksh"; + } else mc_shell->type = SHELL_NONE; } @@ -214,6 +227,14 @@ mc_shell_recognize_path (mc_shell_t *mc_shell) mc_shell->type = SHELL_ASH_BUSYBOX; mc_shell->name = "ash"; } + else if (strstr (mc_shell->path, "/ksh") != NULL + || strstr (mc_shell->path, "/oksh") != NULL + || strstr (mc_shell->path, "/mksh") != NULL + || getenv ("KSH_VERSION") != NULL) + { + mc_shell->type = SHELL_KSH; + mc_shell->name = "ksh"; + } else mc_shell->type = SHELL_NONE; } diff --git a/lib/shell.h b/lib/shell.h index 7ba82dc078..e2b733b91a 100644 --- a/lib/shell.h +++ b/lib/shell.h @@ -18,7 +18,8 @@ typedef enum SHELL_DASH, /* Debian variant of ash */ SHELL_TCSH, SHELL_ZSH, - SHELL_FISH + SHELL_FISH, + SHELL_KSH } shell_type_t; /*** structures declarations (and typedefs of structures)*****************************************/ diff --git a/src/subshell/common.c b/src/subshell/common.c index 69b1f30e4e..842d16fdef 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -366,6 +366,33 @@ init_subshell_child (const char *pty_name) break; + case SHELL_KSH: + /* Do we have a custom init file ~/.local/share/mc/kshrc? */ + init_file = mc_config_get_full_path (MC_KSHRC_FILE); + + /* Otherwise use ~/.profile if $ENV is not already set */ + if (!exist_file (init_file)) + { + g_free (init_file); + init_file = NULL; + + if (!g_getenv ("ENV")) + { + init_file = g_strdup (".profile"); + } + } + + /* Put init file to ENV variable used by ash */ + if (init_file) + { + g_setenv ("ENV", init_file, TRUE); + } + + /* Make MC's special commands not show up in history */ + putenv ((char *) "HISTCONTROL=ignorespace"); + + break; + case SHELL_ZSH: /* ZDOTDIR environment variable is the only way to point zsh * to an other rc file than the default. */ @@ -439,6 +466,7 @@ init_subshell_child (const char *pty_name) case SHELL_ASH_BUSYBOX: case SHELL_DASH: case SHELL_TCSH: + case SHELL_KSH: execl (mc_global.shell->path, mc_global.shell->path, (char *) NULL); break; @@ -1164,6 +1192,12 @@ init_subshell_precmd (char *precmd, size_t buff_size) "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]); break; + case SHELL_KSH: + g_snprintf (precmd, buff_size, + " PS1='$(pwd>&%d; kill -STOP $$)\\u@\\h:\\w\\$ '\n", + subshell_pipe[WRITE]); + break; + case SHELL_ZSH: g_snprintf (precmd, buff_size, " mc_print_command_buffer () { printf \"%%s\\\\n\" \"$BUFFER\" >&%d; }\n" From bd1e68b66ac19bf8ae77cbe6896a500e5ffc4fed Mon Sep 17 00:00:00 2001 From: d3m3t3r <46783027+d3m3t3r@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:38:23 +0000 Subject: [PATCH 2/8] Simplify setting ENV variable without overriding it --- src/subshell/common.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/subshell/common.c b/src/subshell/common.c index 842d16fdef..5d1dd20df8 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -370,23 +370,16 @@ init_subshell_child (const char *pty_name) /* Do we have a custom init file ~/.local/share/mc/kshrc? */ init_file = mc_config_get_full_path (MC_KSHRC_FILE); - /* Otherwise use ~/.profile if $ENV is not already set */ + /* Otherwise use ~/.profile */ if (!exist_file (init_file)) { g_free (init_file); - init_file = NULL; - - if (!g_getenv ("ENV")) - { - init_file = g_strdup (".profile"); - } + init_file = g_strdup (".profile"); } - /* Put init file to ENV variable used by ash */ - if (init_file) - { - g_setenv ("ENV", init_file, TRUE); - } + /* Put init file to ENV variable used by ksh but only if it + * is not already set. */ + g_setenv ("ENV", init_file, FALSE); /* Make MC's special commands not show up in history */ putenv ((char *) "HISTCONTROL=ignorespace"); From 139917c37ef51f22c4c309d52231e04d773f022f Mon Sep 17 00:00:00 2001 From: d3m3t3r <46783027+d3m3t3r@users.noreply.github.com> Date: Thu, 7 Nov 2024 21:37:24 +0000 Subject: [PATCH 3/8] Fix support for mksh mksh (MirBSD Korn shell) is handled separately as it substantially differs from pdksh (Public Domain Korn shell) based varaints. --- doc/man/mc.1.in | 8 ++++++-- lib/fileloc.h | 1 + lib/mcconfig/paths.c | 1 + lib/shell.c | 26 +++++++++++++++++++------- lib/shell.h | 3 ++- src/subshell/common.c | 24 ++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 10 deletions(-) diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in index e0ac3cfefe..8d8d6c6b69 100644 --- a/doc/man/mc.1.in +++ b/doc/man/mc.1.in @@ -2406,10 +2406,14 @@ and special keyboard maps in ~/.local/share/mc/inputrc (fallback ~/.inputrc). .B ash/dash users (BusyBox or Debian) may specify startup commands in ~/.local/share/mc/ashrc (fallback ~/.profile). .PP -.B ksh -users (ksh, oksh or mksh) may specify startup commands in ~/.local/share/mc/kshrc +.B ksh/oksh +users (PD ksh variants) may specify startup commands in ~/.local/share/mc/kshrc (fallback $ENV or ~/.profile). .PP +.B mksh +users (MirBSD ksh) may specify startup commands in ~/.local/share/mc/mkshrc +(fallback $ENV or ~/.mkshrc). +.PP .B zsh users may specify startup commands in ~/.local/share/mc/.zshrc (fallback ~/.zshrc). .PP diff --git a/lib/fileloc.h b/lib/fileloc.h index fe40a0fdce..fad3181bcb 100644 --- a/lib/fileloc.h +++ b/lib/fileloc.h @@ -54,6 +54,7 @@ #define MC_ZSHRC_FILE ".zshrc" #define MC_ASHRC_FILE "ashrc" #define MC_KSHRC_FILE "kshrc" +#define MC_MKSHRC_FILE "mkshrc" #define MC_INPUTRC_FILE "inputrc" #define MC_CONFIG_FILE "ini" #define MC_EXT_FILE "mc.ext.ini" diff --git a/lib/mcconfig/paths.c b/lib/mcconfig/paths.c index 79309d0c17..f33ea99330 100644 --- a/lib/mcconfig/paths.c +++ b/lib/mcconfig/paths.c @@ -76,6 +76,7 @@ static const struct { &mc_data_str, VFS_SHELL_PREFIX }, { &mc_data_str, MC_ASHRC_FILE }, { &mc_data_str, MC_KSHRC_FILE }, + { &mc_data_str, MC_MKSHRC_FILE }, { &mc_data_str, MC_BASHRC_FILE }, { &mc_data_str, MC_INPUTRC_FILE }, { &mc_data_str, MC_ZSHRC_FILE }, diff --git a/lib/shell.c b/lib/shell.c index e018d17c08..9560684f93 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -82,6 +82,10 @@ mc_shell_get_installed_in_system (void) mc_shell->path = g_strdup ("/bin/csh"); else if (access ("/bin/ksh", X_OK) == 0) mc_shell->path = g_strdup ("/bin/ksh"); + else if (access ("/bin/oksh", X_OK) == 0) + mc_shell->path = g_strdup ("/bin/oksh"); + else if (access ("/bin/mksh", X_OK) == 0) + mc_shell->path = g_strdup ("/bin/mksh"); /* No fish as fallback because it is so much different from other shells and * in a way exotic (even though user-friendly by name) that we should not * present it as a subshell without the user's explicit intention. We rather @@ -194,14 +198,17 @@ mc_shell_recognize_real_path (mc_shell_t *mc_shell) else if (strstr (mc_shell->path, "/ksh") != NULL || strstr (mc_shell->real_path, "/ksh") != NULL || strstr (mc_shell->path, "/oksh") != NULL - || strstr (mc_shell->real_path, "/oksh") != NULL - || strstr (mc_shell->path, "/mksh") != NULL - || strstr (mc_shell->real_path, "/mksh") != NULL) + || strstr (mc_shell->real_path, "/oksh") != NULL) { - /* Korn shell variants */ mc_shell->type = SHELL_KSH; mc_shell->name = "ksh"; } + else if (strstr (mc_shell->path, "/mksh") != NULL + || strstr (mc_shell->real_path, "/mksh") != NULL) + { + mc_shell->type = SHELL_MKSH; + mc_shell->name = "mksh"; + } else mc_shell->type = SHELL_NONE; } @@ -227,14 +234,19 @@ mc_shell_recognize_path (mc_shell_t *mc_shell) mc_shell->type = SHELL_ASH_BUSYBOX; mc_shell->name = "ash"; } - else if (strstr (mc_shell->path, "/ksh") != NULL + else if (strstr (mc_shell->path, "/ksh") != NULL || strstr (mc_shell->path, "/oksh") != NULL - || strstr (mc_shell->path, "/mksh") != NULL - || getenv ("KSH_VERSION") != NULL) + || (getenv ("KSH_VERSION") != NULL && strstr (getenv ("KSH_VERSION"), "PD KSH") != NULL)) { mc_shell->type = SHELL_KSH; mc_shell->name = "ksh"; } + else if (strstr (mc_shell->path, "/mksh") != NULL + || (getenv ("KSH_VERSION") != NULL && strstr (getenv ("KSH_VERSION"), "MIRBSD KSH") != NULL)) + { + mc_shell->type = SHELL_MKSH; + mc_shell->name = "mksh"; + } else mc_shell->type = SHELL_NONE; } diff --git a/lib/shell.h b/lib/shell.h index e2b733b91a..bf5ada3adc 100644 --- a/lib/shell.h +++ b/lib/shell.h @@ -19,7 +19,8 @@ typedef enum SHELL_TCSH, SHELL_ZSH, SHELL_FISH, - SHELL_KSH + SHELL_KSH, /* Public Domain Korn shell (pdksh) and variants */ + SHELL_MKSH /* MirBSD Korn shell (mksh) */ } shell_type_t; /*** structures declarations (and typedefs of structures)*****************************************/ diff --git a/src/subshell/common.c b/src/subshell/common.c index 5d1dd20df8..18d7a0849b 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -386,6 +386,23 @@ init_subshell_child (const char *pty_name) break; + case SHELL_MKSH: + /* Do we have a custom init file ~/.local/share/mc/mkshrc? */ + init_file = mc_config_get_full_path (MC_MKSHRC_FILE); + + /* Otherwise use ~/.mkshrc */ + if (!exist_file (init_file)) + { + g_free (init_file); + init_file = g_strdup (".mkshrc"); + } + + /* Put init file to ENV variable used by mksh but only if it + * is not already set. */ + g_setenv ("ENV", init_file, FALSE); + + break; + case SHELL_ZSH: /* ZDOTDIR environment variable is the only way to point zsh * to an other rc file than the default. */ @@ -460,6 +477,7 @@ init_subshell_child (const char *pty_name) case SHELL_DASH: case SHELL_TCSH: case SHELL_KSH: + case SHELL_MKSH: execl (mc_global.shell->path, mc_global.shell->path, (char *) NULL); break; @@ -1191,6 +1209,12 @@ init_subshell_precmd (char *precmd, size_t buff_size) subshell_pipe[WRITE]); break; + case SHELL_MKSH: + g_snprintf (precmd, buff_size, + " PS1='$(pwd>&%d; kill -STOP $$)${USER:=$(id -un)}@${HOSTNAME:=$(hostname -s)}:$PWD\\$ '\n", + subshell_pipe[WRITE]); + break; + case SHELL_ZSH: g_snprintf (precmd, buff_size, " mc_print_command_buffer () { printf \"%%s\\\\n\" \"$BUFFER\" >&%d; }\n" From 1df53a785ee7997f0467f3d3ca1dc5b90ac3e993 Mon Sep 17 00:00:00 2001 From: d3m3t3r <46783027+d3m3t3r@users.noreply.github.com> Date: Thu, 7 Nov 2024 22:32:58 +0000 Subject: [PATCH 4/8] Add comments explaining pdksh and mksh features --- src/subshell/common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/subshell/common.c b/src/subshell/common.c index 18d7a0849b..857c842f49 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -390,7 +390,7 @@ init_subshell_child (const char *pty_name) /* Do we have a custom init file ~/.local/share/mc/mkshrc? */ init_file = mc_config_get_full_path (MC_MKSHRC_FILE); - /* Otherwise use ~/.mkshrc */ + /* Otherwise use ~/.mkshrc (default behavior of mksh) */ if (!exist_file (init_file)) { g_free (init_file); @@ -401,6 +401,8 @@ init_subshell_child (const char *pty_name) * is not already set. */ g_setenv ("ENV", init_file, FALSE); + /* Note mksh doesn't support HISTCONTROL. */ + break; case SHELL_ZSH: @@ -1204,12 +1206,14 @@ init_subshell_precmd (char *precmd, size_t buff_size) break; case SHELL_KSH: + /* pdksh based variants support \x placeholders but not any "precmd" functionality. */ g_snprintf (precmd, buff_size, " PS1='$(pwd>&%d; kill -STOP $$)\\u@\\h:\\w\\$ '\n", subshell_pipe[WRITE]); break; case SHELL_MKSH: + /* mksh doesn't support \x placeholders neither any "precmd" functionality */ g_snprintf (precmd, buff_size, " PS1='$(pwd>&%d; kill -STOP $$)${USER:=$(id -un)}@${HOSTNAME:=$(hostname -s)}:$PWD\\$ '\n", subshell_pipe[WRITE]); From dcc71b590341059b0d6cc5ed284ca96dc1f7c2a1 Mon Sep 17 00:00:00 2001 From: d3m3t3r <46783027+d3m3t3r@users.noreply.github.com> Date: Wed, 20 Nov 2024 22:43:15 +0000 Subject: [PATCH 5/8] Simplify fallback precmd emulation --- src/subshell/common.c | 87 +++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/src/subshell/common.c b/src/subshell/common.c index 857c842f49..407fa5d9bb 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -1134,6 +1134,38 @@ pty_open_slave (const char *pty_name) static void init_subshell_precmd (char *precmd, size_t buff_size) { + /* Attention! Make sure that the buffer for precmd is big enough. */ + + /* Fallback precmd emulation that should work with virtually any shell. + * No real precmd functionality is required, no support for \x substitutions + * in PS1 is needed. For convenience, $HOME is replaced by ~ in PS1. + * + * The following example is a little less fancy (home directory not replaced) + * and shows the basic workings of our prompt for easier understanding: + * + * "precmd() { " + * "echo \"$USER@$(hostname -s):$PWD\"; " + * "pwd>&%d; " + * "kill -STOP $$; " + * "}; " + * "PRECMD=precmd; " + * "PS1='$($PRECMD)$ '\n", + */ + static const char *precmd_fallback = + " " /* Useful if the shell supports HISTCONTROL=ignorespace like functionality */ + "precmd() { " + "if [ ! \"${PWD##$HOME}\" ]; then " + "MC_PWD=\"~\"; " + "else " + "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; " + "fi; " + "echo \"$USER@$(hostname -s):$MC_PWD\"; " + "pwd>&%d; " + "kill -STOP $$; " + "}; " + "PRECMD=precmd; " + "PS1='$($PRECMD)$ '\n"; + switch (mc_global.shell->type) { case SHELL_BASH: @@ -1167,55 +1199,28 @@ init_subshell_precmd (char *precmd, size_t buff_size) * Attention: BusyBox must be built with FEATURE_EDITING_FANCY_PROMPT to * permit \u, \w, \h, \$ escape sequences. Unfortunately this cannot be guaranteed, * especially on embedded systems where people try to save space, so let's use - * the dash version below. It should work on virtually all systems. - * "precmd() { pwd>&%d; kill -STOP $$; }; " - * "PRECMD=precmd; " - * "PS1='$(eval $PRECMD)\\u@\\h:\\w\\$ '\n", + * the falback version. */ + g_snprintf (precmd, buff_size, precmd_fallback, subshell_pipe[WRITE]); + break; + case SHELL_DASH: /* Debian ash needs a precmd emulation via PS1, similar to BusyBox ash, * but does not support escape sequences for user, host and cwd in prompt. - * Attention! Make sure that the buffer for precmd is big enough. - * - * We want to have a fancy dynamic prompt with user@host:cwd just like in the BusyBox - * examples above, but because replacing the home directory part of the path by "~" is - * complicated, it bloats the precmd to a size > BUF_SMALL (128). - * - * The following example is a little less fancy (home directory not replaced) - * and shows the basic workings of our prompt for easier understanding: - * - * "precmd() { " - * "echo \"$USER@$(hostname -s):$PWD\"; " - * "pwd>&%d; " - * "kill -STOP $$; " - * "}; " - * "PRECMD=precmd; " - * "PS1='$($PRECMD)$ '\n", */ - g_snprintf (precmd, buff_size, - "precmd() { " - "if [ ! \"${PWD##$HOME}\" ]; then " - "MC_PWD=\"~\"; " - "else " - "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; " - "fi; " - "echo \"$USER@$(hostname -s):$MC_PWD\"; " - "pwd>&%d; " - "kill -STOP $$; " - "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]); + g_snprintf (precmd, buff_size, precmd_fallback, subshell_pipe[WRITE]); + break; + + case SHELL_MKSH: + /* mksh doesn't support \x placeholders in PS1 and needs precmd emulation via PS1 */ + g_snprintf (precmd, buff_size, precmd_fallback, subshell_pipe[WRITE]); break; case SHELL_KSH: /* pdksh based variants support \x placeholders but not any "precmd" functionality. */ g_snprintf (precmd, buff_size, - " PS1='$(pwd>&%d; kill -STOP $$)\\u@\\h:\\w\\$ '\n", - subshell_pipe[WRITE]); - break; - - case SHELL_MKSH: - /* mksh doesn't support \x placeholders neither any "precmd" functionality */ - g_snprintf (precmd, buff_size, - " PS1='$(pwd>&%d; kill -STOP $$)${USER:=$(id -un)}@${HOSTNAME:=$(hostname -s)}:$PWD\\$ '\n", + " PS1='$(pwd>&%d; kill -STOP $$)'" + "\"${PS1:-\\u@\\h:\\w\\$ }\"\n", subshell_pipe[WRITE]); break; @@ -1264,11 +1269,11 @@ init_subshell_precmd (char *precmd, size_t buff_size) * Use following technique: * * printf(1) with format string containing a single conversion specifier, - * "b", and an argument which contains a copy of the string passed to + * "b", and an argument which contains a copy of the string passed to * subshell_name_quote() with all characters, except digits and letters, * replaced by the backslash-escape sequence \0nnn, where "nnn" is the * numeric value of the character converted to octal number. - * + * * cd "`printf '%b' 'ABC\0nnnDEF\0nnnXYZ'`" * * N.B.: Use single quotes for conversion specifier to work around From 9d4bbe5ee0b22b80061c27631b4945eb80e2ce61 Mon Sep 17 00:00:00 2001 From: d3m3t3r <46783027+d3m3t3r@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:59:24 +0000 Subject: [PATCH 6/8] Support user prompt in fallback precmd emulation --- src/subshell/common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/subshell/common.c b/src/subshell/common.c index 407fa5d9bb..7beeebc8b3 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -1153,18 +1153,19 @@ init_subshell_precmd (char *precmd, size_t buff_size) */ static const char *precmd_fallback = " " /* Useful if the shell supports HISTCONTROL=ignorespace like functionality */ + "MC_PS1_SAVED=\"$PS1\"; " /* Save custom PS1 */ "precmd() { " "if [ ! \"${PWD##$HOME}\" ]; then " "MC_PWD=\"~\"; " "else " "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; " "fi; " - "echo \"$USER@$(hostname -s):$MC_PWD\"; " + "echo \"${MC_PS1_SAVED:-$USER@$(hostname -s):$MC_PWD\\$ }\"; " "pwd>&%d; " "kill -STOP $$; " "}; " "PRECMD=precmd; " - "PS1='$($PRECMD)$ '\n"; + "PS1='$($PRECMD)'\n"; switch (mc_global.shell->type) { From 8eaa50dd25ec5bb7cc7e2c594356d57306af9601 Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Sun, 12 Jan 2025 19:16:33 +0100 Subject: [PATCH 7/8] fixup! Ticket #3748: add support for ksh in subshell Signed-off-by: Yury V. Zaytsev --- doc/man/mc.1.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in index 8d8d6c6b69..b408b2a26f 100644 --- a/doc/man/mc.1.in +++ b/doc/man/mc.1.in @@ -2408,11 +2408,15 @@ users (BusyBox or Debian) may specify startup commands in ~/.local/share/mc/ashr .PP .B ksh/oksh users (PD ksh variants) may specify startup commands in ~/.local/share/mc/kshrc -(fallback $ENV or ~/.profile). +(fallback +.I ENV +or ~/.profile). .PP .B mksh users (MirBSD ksh) may specify startup commands in ~/.local/share/mc/mkshrc -(fallback $ENV or ~/.mkshrc). +(fallback +.I ENV +or ~/.mkshrc). .PP .B zsh users may specify startup commands in ~/.local/share/mc/.zshrc (fallback ~/.zshrc). From b07a6f24592f38b777ec25cbc5b4f96dcba75bfc Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Sun, 12 Jan 2025 19:49:48 +0100 Subject: [PATCH 8/8] subshell: fix environment variable names in `mc_shell_recognize_path` Signed-off-by: Yury V. Zaytsev --- lib/shell.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/shell.c b/lib/shell.c index 9560684f93..72411c8a58 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -219,17 +219,17 @@ static void mc_shell_recognize_path (mc_shell_t *mc_shell) { /* If shell is not symlinked to busybox, it is safe to assume it is a real shell */ - if (strstr (mc_shell->path, "/bash") != NULL || getenv ("BASH") != NULL) + if (strstr (mc_shell->path, "/bash") != NULL || getenv ("BASH_VERSION") != NULL) { mc_shell->type = SHELL_BASH; mc_shell->name = "bash"; } - else if (strstr (mc_shell->path, "/sh") != NULL || getenv ("SH") != NULL) + else if (strstr (mc_shell->path, "/sh") != NULL) { mc_shell->type = SHELL_SH; mc_shell->name = "sh"; } - else if (strstr (mc_shell->path, "/ash") != NULL || getenv ("ASH") != NULL) + else if (strstr (mc_shell->path, "/ash") != NULL || getenv ("BB_ASH_VERSION") != NULL) { mc_shell->type = SHELL_ASH_BUSYBOX; mc_shell->name = "ash";