mc: update to 4.8.16 2503/head
authorDirk Brenken <dirk@brenken.org>
Mon, 14 Mar 2016 14:04:39 +0000 (15:04 +0100)
committerDirk Brenken <dirk@brenken.org>
Mon, 14 Mar 2016 14:13:31 +0000 (15:13 +0100)
* update midnight commander to latest stable release
* refresh subshell patch to support minimal openwrt environment
* switch to sha256 based package fingerprint
* compile & functional tested with ar71xx and x86

Signed-off-by: Dirk Brenken <openwrt@brenken.org>
utils/mc/Makefile
utils/mc/patches/010-subshell.patch

index 7c0b3dbef4c2f7d857c173756045613493f68694..f712c99e8767abc437d9efdb987453483872ed54 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2006-2015 OpenWrt.org
+# Copyright (C) 2006-2016 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -8,14 +8,14 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=mc
-PKG_VERSION:=4.8.15
-PKG_RELEASE:=2
-PKG_MAINTAINER:=Dirk Brenken <dirk@brenken.org>
+PKG_VERSION:=4.8.16
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Dirk Brenken <openwrt@brenken.org>
 PKG_LICENSE:=GPL-3.0+
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=http://ftp.midnight-commander.org/
-PKG_MD5SUM:=7c1935433866fdf59a3c2d9b7dae81ad
+PKG_SHA256SUM:=bbbcbe3097d3160f865d24aa38ff122f1c59752b5ef153ca4ade5ac0f82b7020
 PKG_BUILD_PARALLEL:=1
 PKG_FIXUP:=autoreconf
 
index 12067f1c915521bf0dcb91becc2de859f522659e..bd7ee35e90f54a254f1c5dbd7518a159882b9428 100644 (file)
---- a/lib/global.c
-+++ b/lib/global.c
-@@ -97,6 +97,7 @@ mc_global_t mc_global = {
- #endif /* !ENABLE_SUBSHELL */
-         .shell = NULL,
-+        .shell_realpath = NULL,
-         .xterm_flag = FALSE,
-         .disable_x11 = FALSE,
---- a/lib/global.h
-+++ b/lib/global.h
-@@ -255,6 +255,7 @@ typedef struct
-         /* The user's shell */
-         char *shell;
-+        char *shell_realpath;
-         /* This flag is set by xterm detection routine in function main() */
-         /* It is used by function view_other_cmd() */
---- a/lib/mcconfig/paths.c
-+++ b/lib/mcconfig/paths.c
-@@ -84,6 +84,7 @@ static const struct
-     /* data */
-     { "skins",                                 &mc_data_str, MC_SKINS_SUBDIR},
-     { "fish",                                  &mc_data_str, FISH_PREFIX},
-+    { "ashrc",                                 &mc_data_str, "ashrc"},
-     { "bashrc",                                &mc_data_str, "bashrc"},
-     { "inputrc",                               &mc_data_str, "inputrc"},
-     { "extfs.d",                               &mc_data_str, MC_EXTFS_DIR},
---- a/src/main.c
-+++ b/src/main.c
-@@ -87,6 +87,9 @@
- /*** file scope variables ************************************************************************/
- /*** file scope functions ************************************************************************/
-+
-+static char rp_shell[PATH_MAX];
-+
- /* --------------------------------------------------------------------------------------------- */
- static void
-@@ -118,6 +121,44 @@ check_codeset (void)
- }
- /* --------------------------------------------------------------------------------------------- */
-+/**
-+ * Get a system shell.
-+ *
-+ * @return newly allocated string with shell name
-+ */
-+
-+static char *
-+mc_get_system_shell (void)
-+{
-+    char *sh_str;
-+    /* 3rd choice: look for existing shells supported as MC subshells.  */
-+    if (access ("/bin/bash", X_OK) == 0)
-+        sh_str = g_strdup ("/bin/bash");
-+    else if (access ("/bin/ash", X_OK) == 0)
-+        sh_str = g_strdup ("/bin/ash");
-+    else if (access ("/bin/dash", X_OK) == 0)
-+        sh_str = g_strdup ("/bin/dash");
-+    else if (access ("/bin/busybox", X_OK) == 0)
-+        sh_str = g_strdup ("/bin/busybox");
-+    else if (access ("/bin/zsh", X_OK) == 0)
-+        sh_str = g_strdup ("/bin/zsh");
-+    else if (access ("/bin/tcsh", X_OK) == 0)
-+        sh_str = g_strdup ("/bin/tcsh");
-+    /* 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
-+     * will not use a subshell but just a command line.
-+     * else if (access("/bin/fish", X_OK) == 0)
-+     *     mc_global.tty.shell = g_strdup ("/bin/fish");
-+     */
-+    else
-+        /* Fallback and last resort: system default shell */
-+        sh_str = g_strdup ("/bin/sh");
-+
-+    return sh_str;
-+}
-+
-+/* --------------------------------------------------------------------------------------------- */
- /** POSIX version.  The only version we support.  */
- static void
-@@ -126,9 +167,11 @@ OS_Setup (void)
-     const char *shell_env;
-     const char *datadir_env;
-+
-     shell_env = getenv ("SHELL");
-     if ((shell_env == NULL) || (shell_env[0] == '\0'))
-     {
-+        /* 2nd choice: user login shell */
-         struct passwd *pwd;
-         pwd = getpwuid (geteuid ());
-@@ -136,13 +179,15 @@ OS_Setup (void)
-             mc_global.tty.shell = g_strdup (pwd->pw_shell);
-     }
-     else
-+        /* 1st choice: SHELL environment variable */
-         mc_global.tty.shell = g_strdup (shell_env);
-     if ((mc_global.tty.shell == NULL) || (mc_global.tty.shell[0] == '\0'))
-     {
-         g_free (mc_global.tty.shell);
--        mc_global.tty.shell = g_strdup ("/bin/sh");
-+        mc_global.tty.shell = mc_get_system_shell ();
-     }
-+    mc_global.tty.shell_realpath = mc_realpath (mc_global.tty.shell, rp_shell);
-     /* This is the directory, where MC was installed, on Unix this is DATADIR */
-     /* and can be overriden by the MC_DATADIR environment variable */
---- a/src/subshell.c
-+++ b/src/subshell.c
-@@ -114,6 +114,8 @@ enum
- static enum
- {
-     BASH,
-+    ASH_BUSYBOX,                /* BusyBox default shell (ash) */
-+    DASH,                       /* Debian variant of ash */
-     TCSH,
-     ZSH,
-     FISH
-@@ -209,6 +211,7 @@ static void
- init_subshell_child (const char *pty_name)
- {
-     char *init_file = NULL;
-+    char *putenv_str = NULL;
-     pid_t mc_sid;
-     (void) pty_name;
-@@ -257,32 +260,53 @@ init_subshell_child (const char *pty_nam
-     switch (subshell_type)
-     {
-     case BASH:
-+        /* Do we have a custom init file ~/.local/share/mc/bashrc? */
-         init_file = mc_config_get_full_path ("bashrc");
-+        /* Otherwise use ~/.bashrc */
-         if (access (init_file, R_OK) == -1)
-         {
-             g_free (init_file);
-             init_file = g_strdup (".bashrc");
-         }
--        /* Make MC's special commands not show up in bash's history */
--        putenv ((char *) "HISTCONTROL=ignorespace");
-+        /* Make MC's special commands not show up in bash's history and also suppress
-+         * consecutive identical commands*/
-+        putenv ((char *) "HISTCONTROL=ignoreboth");
-         /* Allow alternative readline settings for MC */
-         {
-             char *input_file = mc_config_get_full_path ("inputrc");
-             if (access (input_file, R_OK) == 0)
-             {
--                char *putenv_str = g_strconcat ("INPUTRC=", input_file, NULL);
-+                putenv_str = g_strconcat ("INPUTRC=", input_file, NULL);
-                 putenv (putenv_str);
--                g_free (putenv_str);
-             }
-             g_free (input_file);
-         }
-         break;
--        /* TODO: Find a way to pass initfile to TCSH and ZSH */
-+    case ASH_BUSYBOX:
-+    case DASH:
-+        /* Do we have a custom init file ~/.local/share/mc/ashrc? */
-+        init_file = mc_config_get_full_path ("ashrc");
-+
-+        /* Otherwise use ~/.profile */
-+        if (access (init_file, R_OK) == -1)
-+        {
-+            g_free (init_file);
-+            init_file = g_strdup (".profile");
-+        }
-+
-+        /* Put init file to ENV variable used by ash */
-+        putenv_str = g_strconcat ("ENV=", init_file, NULL);
-+        putenv (putenv_str);
-+        /* Do not use "g_free (putenv_str)" here, otherwise ENV will be undefined! */
-+
-+        break;
-+
-+        /* TODO: Find a way to pass initfile to TCSH, ZSH and FISH */
-     case TCSH:
-     case ZSH:
-     case FISH:
-@@ -320,10 +344,6 @@ init_subshell_child (const char *pty_nam
-         execl (mc_global.tty.shell, "bash", "-rcfile", init_file, (char *) NULL);
-         break;
--    case TCSH:
--        execl (mc_global.tty.shell, "tcsh", (char *) NULL);
--        break;
--
-     case ZSH:
-         /* Use -g to exclude cmds beginning with space from history
-          * and -Z to use the line editor on non-interactive term */
-@@ -331,8 +351,11 @@ init_subshell_child (const char *pty_nam
-         break;
-+    case ASH_BUSYBOX:
-+    case DASH:
-+    case TCSH:
-     case FISH:
--        execl (mc_global.tty.shell, "fish", (char *) NULL);
-+        execl (mc_global.tty.shell, mc_global.tty.shell, (char *) NULL);
-         break;
-     default:
-@@ -341,6 +364,7 @@ init_subshell_child (const char *pty_nam
-     /* If we get this far, everything failed miserably */
-     g_free (init_file);
-+    g_free (putenv_str);
-     my_exit (FORK_FAILURE);
- }
-@@ -742,6 +766,171 @@ pty_open_slave (const char *pty_name)
- }
- #endif /* !HAVE_GRANTPT */
-+
-+/* --------------------------------------------------------------------------------------------- */
-+/**
-+ * Get a subshell type and store in subshell_type variable
-+ *
-+ * @return TRUE if subtype was gotten, FALSE otherwise
-+ */
-+
-+static gboolean
-+init_subshell_type (void)
-+{
-+    gboolean result = TRUE;
-+
-+    /* Find out what type of shell we have. Also consider real paths (resolved symlinks)
-+     * because e.g. csh might point to tcsh, ash to dash or busybox, sh to anything. */
-+
-+    if (strstr (mc_global.tty.shell, "/zsh") || strstr (mc_global.tty.shell_realpath, "/zsh")
-+        || getenv ("ZSH_VERSION"))
-+        /* Also detects ksh symlinked to zsh */
-+        subshell_type = ZSH;
-+    else if (strstr (mc_global.tty.shell, "/tcsh")
-+             || strstr (mc_global.tty.shell_realpath, "/tcsh"))
-+        /* Also detects csh symlinked to tcsh */
-+        subshell_type = TCSH;
-+    else if (strstr (mc_global.tty.shell, "/fish")
-+             || strstr (mc_global.tty.shell_realpath, "/fish"))
-+        subshell_type = FISH;
-+    else if (strstr (mc_global.tty.shell, "/dash")
-+             || strstr (mc_global.tty.shell_realpath, "/dash"))
-+        /* Debian ash (also found if symlinked to by ash/sh) */
-+        subshell_type = DASH;
-+    else if (strstr (mc_global.tty.shell_realpath, "/busybox"))
-+    {
-+        /* If shell is symlinked to busybox, assume it is an ash, even though theoretically
-+         * it could also be a hush (a mini shell for non-MMU systems deactivated by default).
-+         * For simplicity's sake we assume that busybox always contains an ash, not a hush.
-+         * On embedded platforms or on server systems, /bin/sh often points to busybox.
-+         * Sometimes even bash is symlinked to busybox (CONFIG_FEATURE_BASH_IS_ASH option),
-+         * so we need to check busybox symlinks *before* checking for the name "bash"
-+         * in order to avoid that case. */
-+        subshell_type = ASH_BUSYBOX;
-+    }
-+    else if (strstr (mc_global.tty.shell, "/bash") || getenv ("BASH"))
-+        /* If bash is not symlinked to busybox, it is safe to assume it is a real bash */
-+        subshell_type = BASH;
-+    else
-+    {
-+        mc_global.tty.use_subshell = FALSE;
-+        result = FALSE;
-+    }
-+    return result;
-+}
-+
-+/* --------------------------------------------------------------------------------------------- */
-+/**
-+ * Set up `precmd' or equivalent for reading the subshell's CWD.
-+ *
-+ * Attention! Never forget that these are *one-liners* even though the concatenated
-+ * substrings contain line breaks and indentation for better understanding of the
-+ * shell code. It is vital that each one-liner ends with a line feed character ("\n" ).
-+ *
-+ * @return initialized pre-command string
-+ */
-+
-+static void
-+init_subshell_precmd (char *precmd, size_t buff_size)
-+{
-+
-+    switch (subshell_type)
-+    {
-+    case BASH:
-+        g_snprintf (precmd, buff_size,
-+                    " PROMPT_COMMAND='pwd>&%d; kill -STOP $$';\n", subshell_pipe[WRITE]);
-+        break;
-+
-+    case ASH_BUSYBOX:
-+        /* BusyBox ash needs a somewhat complicated precmd emulation via PS1, and it is vital
-+         * that BB be built with active CONFIG_ASH_EXPAND_PRMT, but this is the default anyway.
-+         *
-+         * A: This leads to a stopped subshell (=frozen mc) if user calls "ash" command
-+         *    "PS1='$(pwd>&%d; kill -STOP $$)\\u@\\h:\\w\\$ '\n",
-+         *
-+         * B: This leads to "sh: precmd: not found" in sub-subshell if user calls "ash" command
-+         *    "precmd() { pwd>&%d; kill -STOP $$; }; "
-+         *    "PS1='$(precmd)\\u@\\h:\\w\\$ '\n",
-+         *
-+         * C: This works if user calls "ash" command because in sub-subshell
-+         *    PRECMD is unfedined, thus evaluated to empty string - no damage done.
-+         *    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",
-+         */
-+    case 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@openwrt:$MC_PWD\"; "
-+                    "pwd>&%d; "
-+                    "kill -STOP $$; "
-+                    "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]);
-+        break;
-+
-+    case ZSH:
-+        g_snprintf (precmd, buff_size,
-+                    " precmd() { pwd>&%d; kill -STOP $$; }; "
-+                    "PS1='%%n@%%m:%%~%%# '\n", subshell_pipe[WRITE]);
-+        break;
-+
-+    case TCSH:
-+        g_snprintf (precmd, buff_size,
-+                    "set echo_style=both; "
-+                    "set prompt='%%n@%%m:%%~%%# '; "
-+                    "alias precmd 'echo $cwd:q >>%s; kill -STOP $$'\n", tcsh_fifo);
-+        break;
-+
-+    case FISH:
-+        /* We also want a fancy user@host:cwd prompt here, but fish makes it very easy to also
-+         * use colours, which is what we will do. But first here is a simpler, uncoloured version:
-+         * "function fish_prompt; "
-+         *     "echo (whoami)@(hostname -s):(pwd)\\$\\ ; "
-+         *     "echo \"$PWD\">&%d; "
-+         *     "kill -STOP %%self; "
-+         * "end\n",
-+         *
-+         * TODO: fish prompt is shown when panel is hidden (Ctrl-O), but not when it is visible.
-+         * Find out how to fix this.
-+         */
-+        g_snprintf (precmd, buff_size,
-+                    "function fish_prompt; "
-+                    "echo (whoami)@(hostname -s):(set_color $fish_color_cwd)(pwd)(set_color normal)\\$\\ ; "
-+                    "echo \"$PWD\">&%d; " "kill -STOP %%self; " "end\n", subshell_pipe[WRITE]);
-+        break;
-+
-+    default:
-+        break;
-+    }
-+}
-+
- /* --------------------------------------------------------------------------------------------- */
- /*** public functions ****************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
-@@ -761,6 +950,7 @@ init_subshell (void)
- {
-     /* This must be remembered across calls to init_subshell() */
-     static char pty_name[BUF_SMALL];
-+    /* Must be considerably longer than BUF_SMALL (128) to support fancy shell prompts */
-     char precmd[BUF_MEDIUM];
-     switch (check_sid ())
-@@ -782,23 +972,8 @@ init_subshell (void)
-     if (mc_global.tty.subshell_pty == 0)
-     {                           /* First time through */
--        /* Find out what type of shell we have */
--
--        if (strstr (mc_global.tty.shell, "/zsh") || getenv ("ZSH_VERSION"))
--            subshell_type = ZSH;
--        else if (strstr (mc_global.tty.shell, "/tcsh"))
--            subshell_type = TCSH;
--        else if (strstr (mc_global.tty.shell, "/csh"))
--            subshell_type = TCSH;
--        else if (strstr (mc_global.tty.shell, "/bash") || getenv ("BASH"))
--            subshell_type = BASH;
--        else if (strstr (mc_global.tty.shell, "/fish"))
--            subshell_type = FISH;
--        else
--        {
--            mc_global.tty.use_subshell = FALSE;
-+        if (!init_subshell_type ())
-             return;
--        }
-         /* Open a pty for talking to the subshell */
-@@ -844,7 +1019,7 @@ init_subshell (void)
-                 return;
-             }
-         }
--        else /* subshell_type is BASH or ZSH */ if (pipe (subshell_pipe))
-+        else if (pipe (subshell_pipe))  /* subshell_type is BASH, ASH_BUSYBOX, DASH or ZSH */
-         {
-             perror (__FILE__ ": couldn't create pipe");
-             mc_global.tty.use_subshell = FALSE;
-@@ -872,39 +1047,116 @@ init_subshell (void)
-         init_subshell_child (pty_name);
-     }
--    /* Set up 'precmd' or equivalent for reading the subshell's CWD */
-+    init_subshell_precmd (precmd, BUF_MEDIUM);
-+
-+    /* Set up `precmd' or equivalent for reading the subshell's CWD
-+     *
-+     * Attention! Never forget that these are *one-liners* even though the concatenated
-+     * substrings contain line breaks and indentation for better understanding of the
-+     * shell code. It is vital that each one-liner ends with a line feed character ("\n" ).
-+     */
-     switch (subshell_type)
-     {
-     case BASH:
-         g_snprintf (precmd, sizeof (precmd),
--                    " PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND\n}'pwd>&%d;kill -STOP $$'\n",
--                    subshell_pipe[WRITE]);
-+                    " PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND\n}'pwd>&%d;kill -STOP $$'\n"
-+                    "PS1='\\u@\\h:\\w\\$ '\n", subshell_pipe[WRITE]);
-+        break;
-+
-+    case ASH_BUSYBOX:
-+        /* BusyBox ash needs a somewhat complicated precmd emulation via PS1, and it is vital
-+         * that BB be built with active CONFIG_ASH_EXPAND_PRMT, but this is the default anyway.
-+         *
-+         * A: This leads to a stopped subshell (=frozen mc) if user calls "ash" command
-+         *    "PS1='$(pwd>&%d; kill -STOP $$)\\u@\\h:\\w\\$ '\n",
-+         *
-+         * B: This leads to "sh: precmd: not found" in sub-subshell if user calls "ash" command
-+         *    "precmd() { pwd>&%d; kill -STOP $$; }; "
-+         *    "PS1='$(precmd)\\u@\\h:\\w\\$ '\n",
-+         *
-+         * C: This works if user calls "ash" command because in sub-subshell
-+         *    PRECMD is unfedined, thus evaluated to empty string - no damage done.
-+         *    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",
-+         */
-+    case 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, sizeof (precmd),
-+                    "precmd() { "
-+                    "if [ ! \"${PWD##$HOME}\" ]; then "
-+                    "MC_PWD=\"~\"; "
-+                    "else "
-+                    "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; "
-+                    "fi; "
-+                    "echo \"$USER@openwrt:$MC_PWD\"; "
-+                    "pwd>&%d; "
-+                    "kill -STOP $$; "
-+                    "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]);
-         break;
-     case ZSH:
-         g_snprintf (precmd, sizeof (precmd),
--                    " _mc_precmd(){ pwd>&%d;kill -STOP $$ }; precmd_functions+=(_mc_precmd)\n",
--                    subshell_pipe[WRITE]);
-+                    " _mc_precmd(){ pwd>&%d;kill -STOP $$ }; precmd_functions+=(_mc_precmd)\n"
-+                    "PS1='%%n@%%m:%%~%%# '\n", subshell_pipe[WRITE]);
-         break;
-     case TCSH:
-         g_snprintf (precmd, sizeof (precmd),
--                    "set echo_style=both;"
--                    "alias precmd 'echo $cwd:q >>%s;kill -STOP $$'\n", tcsh_fifo);
-+                    "set echo_style=both; "
-+                    "set prompt='%%n@%%m:%%~%%# '; "
-+                    "alias precmd 'echo $cwd:q >>%s; kill -STOP $$'\n", tcsh_fifo);
-         break;
-+
-     case FISH:
-         /* Use fish_prompt_mc function for prompt, if not present then copy fish_prompt to it. */
-+        /* We also want a fancy user@host:cwd prompt here, but fish makes it very easy to also
-+         * use colours, which is what we will do. But first here is a simpler, uncoloured version:
-+         * "function fish_prompt; "
-+         *     "echo (whoami)@(hostname -s):(pwd)\\$\\ ; "
-+         *     "echo \"$PWD\">&%d; "
-+         *     "kill -STOP %%self; "
-+         * "end\n",
-+         *
-+         * TODO: fish prompt is shown when panel is hidden (Ctrl-O), but not when it is visible.
-+         * Find out how to fix this.
-+         */
-         g_snprintf (precmd, sizeof (precmd),
-                     "if not functions -q fish_prompt_mc;"
-                     "functions -c fish_prompt fish_prompt_mc; end;"
--                    "function fish_prompt; echo $PWD>&%d; fish_prompt_mc; kill -STOP %%self; end\n",
-+                    "function fish_prompt;"
-+                    "echo (whoami)@(hostname -s):(set_color $fish_color_cwd)(pwd)(set_color normal)\\$\\ ; "
-+                    "echo \"$PWD\">&%d; fish_prompt_mc; kill -STOP %%self; end\n",
-                     subshell_pipe[WRITE]);
-         break;
-     default:
-         break;
-     }
-+
-     write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd));
-     /* Wait until the subshell has started up and processed the command */
-@@ -1108,6 +1360,13 @@ subshell_name_quote (const char *s)
-         quote_cmd_start = "(printf \"%b\" '";
-         quote_cmd_end = "')";
-     }
-+    /* TODO: When BusyBox printf is fixed, get rid of this "else if", see
-+       http://lists.busybox.net/pipermail/busybox/2012-March/077460.html */
-+    /* else if (subshell_type == ASH_BUSYBOX)
-+       {
-+       quote_cmd_start = "\"`echo -en '";
-+       quote_cmd_end = "'`\"";
-+       } */
-     else
-     {
-         quote_cmd_start = "\"`printf \"%b\" '";
+--- a/src/subshell/common.c
++++ b/src/subshell/common.c
+@@ -849,7 +849,7 @@ init_subshell_precmd (char *precmd, size
+                     "else "
+                     "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; "
+                     "fi; "
+-                    "echo \"$USER@$(hostname -s):$MC_PWD\"; "
++                    "echo \"$USER@$HOSTNAME:$MC_PWD\"; "
+                     "pwd>&%d; "
+                     "kill -STOP $$; "
+                     "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]);