Update: I have factored out the INPUTRC fix (including two source code comments for the bash case) into a separate 030-bash_inputrc.patch so as to separate it from the ash patches and enable you to easily fix the upstream code issue separately.
Alexander Kriegisch, 05.03.2012 14:25: > Oswald Buddenhagen, 05.03.2012 09:27: >> On Sun, Mar 04, 2012 at 03:19:52PM +0100, Alexander Kriegisch wrote: >>> I know how to do this via shell script, but not cleanly via C, sorry. >>> >> you could start by posting the sh code as text or a comment ... > > I do not really know what the point would be to produce something which > would never be used, but I am thinking about it and might post an update > later. > >>> - Plese refer to code comments for how and why I implemented the >>> precmd via PS1 with two-fold indirection. >>> >> as ash is as close to pure posix as it gets, this pretty much qualifies >> as a generic solution. one could even remove the paths for the other >> bourne-compatible shells (except that they are less hacky) ... > > I am providing my code as-is, so as I said, every core MC developer or > maintainer is welcome to optimise and streamline my patch as well as the > upstream code base. So if my PS1 precmd trick works for other shells, > too, feel free to use it there, too. Maybe if I have time available I > can test that, but my main concern still is ash. > >>> Remark: In order to get ENV into the environment for the init file, I >>> had to uncomment "g_free (putenv_str)". >>> >> that sounds like adding a memory leak. you need to move, not remove the >> free. but then, i don't know that code, maybe there is already a second >> cleanup path. > > I took the chance to just test the INPUTRC case and found out that as I > suspected, it actually does *not* work because the variable is g_free'd > before the subshell is called. The effect is that even though I created > a test file ~/.local/share/mc/inputrc, it was not used by bash and > INPUTRC was undefined in the subshell. > > So I updated my patch: putenv_str is now created before the first switch > statement and g_free(putenv_str) is called at the same place as > g_free(init_file). No matter whether my ash subshell patch is accepted > into the code base or not, the INPUTRC case needs to be fixed upstream. > Probably it never worked unless the g_free'd memory area was not > overwritten yet by the time it was used by the bash subshell. After my > fix, INPUTRC is available and used by the bash subshell. I have tested > it on my mipsel target platform. > >>> + // A: This leads to a stopped subshell (=frozen mc) if >>> user calls "sh" command >>> >> please fix the indentation and avoid c99/c++ comments. > > I must say, I am rather happy that indentation and commenting style is > your major concern about my code and not anything functional. My updated > patch does not use c99 style comments anymore. The second patch file > remains unchanged because I did not add any comments there. As for > indentation, I did not find anything wrong there. I am using four spaces > instead of tabs just like you MC developers, even though I find that > rather strange. The indentation level is in line with the rest of the > switch-case statement, even though I personally do not indent that way, > but indentation is largely a matter of taste anyway and I am merely > trying to adapt to the style I found in your code base. > > > > > _______________________________________________ > mc-devel mailing list > http://mail.gnome.org/mailman/listinfo/mc-devel
--- src/subshell.c 2012-03-02 13:55:52.018954847 +0100 +++ src/subshell.c 2012-03-05 13:59:36.697459979 +0100 @@ -266,11 +266,14 @@ putenv (g_strdup (sid_str)); } + char *putenv_str = NULL; 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); @@ -285,9 +288,9 @@ 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); + /* Do not use "g_free (putenv_str)" here, otherwise INPUTRC will be undefined! */ } g_free (input_file); } @@ -350,6 +353,7 @@ /* If we get this far, everything failed miserably */ g_free (init_file); + g_free (putenv_str); _exit (FORK_FAILURE); }
--- src/subshell.c 2012-03-05 13:59:36.697459979 +0100 +++ src/subshell.c 2012-03-05 13:53:10.765462536 +0100 @@ -126,6 +126,7 @@ static enum { BASH, + ASH, TCSH, ZSH, FISH @@ -297,6 +298,24 @@ break; + case ASH: + /* 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 and ZSH */ case TCSH: case ZSH: @@ -335,6 +354,11 @@ execl (shell, "bash", "-rcfile", init_file, (char *) NULL); break; + /* TODO for upstream patch: Execute correct ash/dash/busybox shell (not necessary for Freetz) */ + case ASH: + execl (shell, "ash", (char *) NULL); + break; + case TCSH: execl (shell, "tcsh", (char *) NULL); break; @@ -800,6 +824,9 @@ subshell_type = BASH; else if (strstr (shell, "/fish")) subshell_type = FISH; + /* TODO for upstream patch: Check if "sh" really points to ash/dash/busybox (not necessary for Freetz) */ + else if (strstr (shell, "/ash") || strstr (shell, "/dash") || strstr (shell, "/sh")) + subshell_type = ASH; else { mc_global.tty.use_subshell = FALSE; @@ -850,7 +877,7 @@ return; } } - else /* subshell_type is BASH or ZSH */ if (pipe (subshell_pipe)) + else /* subshell_type is BASH, ASH or ZSH */ if (pipe (subshell_pipe)) { perror (__FILE__ ": couldn't create pipe"); mc_global.tty.use_subshell = FALSE; @@ -887,6 +914,25 @@ " PROMPT_COMMAND='pwd>&%d;kill -STOP $$'\n", subshell_pipe[WRITE]); break; + case ASH: + /* Ash needs a somewhat complicated precmd emulation via PS1. + BUF_SMALL (defined in lib/global.h) is the length limit for precmd. */ + g_snprintf (precmd, sizeof (precmd), + + /* 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 + */ + "precmd(){ pwd>&%d;kill -STOP $$; }; PRECMD=precmd; PS1='$(eval $PRECMD)\\\\u@\\\\h:\\\\w\\\\$ '\n", + + subshell_pipe[WRITE]); + break; + case ZSH: g_snprintf (precmd, sizeof (precmd), " precmd(){ pwd>&%d;kill -STOP $$ }\n", subshell_pipe[WRITE]); @@ -1107,6 +1153,13 @@ 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) + { + quote_cmd_start = "\"`echo -en '"; + quote_cmd_end = "'`\""; + } else { quote_cmd_start = "\"`printf \"%b\" '";
--- lib/mcconfig/paths.c 2012-03-04 04:28:07.000000000 +0100 +++ lib/mcconfig/paths.c 2012-03-04 04:28:43.000000000 +0100 @@ -82,6 +82,7 @@ /* 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}, --- tests/lib/mcconfig/user_configs_path.c 2012-03-04 04:27:47.000000000 +0100 +++ tests/lib/mcconfig/user_configs_path.c 2012-03-04 05:33:48.418447747 +0100 @@ -96,6 +96,7 @@ path_fail_unless (CONF_DATA, MC_SKINS_SUBDIR); path_fail_unless (CONF_DATA, FISH_PREFIX); + path_fail_unless (CONF_DATA, "ashrc"); path_fail_unless (CONF_DATA, "bashrc"); path_fail_unless (CONF_DATA, "inputrc"); path_fail_unless (CONF_DATA, MC_EXTFS_DIR); --- doc/man/mc.1.in 2012-03-04 05:18:35.970419532 +0100 +++ doc/man/mc.1.in 2012-03-04 05:35:58.262451703 +0100 @@ -2408,7 +2408,7 @@ .\"NODE " The subshell support" .SH " The subshell support" The subshell support is a compile time option, that works with the -shells: bash, tcsh and zsh. +shells: bash, ash, tcsh and zsh. .PP When the subshell code is activated the Midnight Commander will spawn a concurrent copy of your shell (the one defined in the @@ -2423,8 +2423,10 @@ If you are using .B bash you can specify startup -commands for the subshell in your ~/.local/share/mc/bashrc file and +commands for the subshell in your ~/.local/share/mc/bashrc file (fallback ~/.bashrc) and special keyboard maps in the ~/.local/share/mc/inputrc file. +.B ash +users may specify startup commands in ~/.local/share/mc/ashrc (fallback ~/.profile). .B tcsh users may specify startup commands in the ~/.local/share/mc/tcshrc file. .PP
_______________________________________________ mc-devel mailing list http://mail.gnome.org/mailman/listinfo/mc-devel