How to add subshell support for ash
Alexander Kriegisch
kriegaex at freetz.org
Sun Mar 4 14:19:52 UTC 2012
Okay guys, I guess I have a working integration for ash subshell support
(tested with BusyBox ash/sh on mipsel) now. I am offering it to you
developers for inspection and adaption, so it may soon become a part of
the mainstream MC code base. I am aware of a few shortcomings and have
mentioned them as TODO items in code comments.
The first file 040-ash_as_subshell.patch contains the functional part of
the patch, while 040-ash_as_subshell_additional.patch contains some
minor additions to documentation and test code which are not necessary
to run mc + ash. Feel free and encouraged to criticise and improve the
code - as I said, I am not a C programmer and rather got my results by
continuous testing with strace as a debugging tool because I do not know
how to handle gdb.
What I have so far:
- Ash mode will be used if the login shell is /bin/sh (on my
platform it is safe to assume this, for general use this needs to
be adapted to really recognise if /bin/sh is an ash or dash. I know
how to do this via shell script, but not cleanly via C, sorry.
- Ash as a subshell currently displays a fixed PS1 prompt like
"user at host:/my/path/$ " ("user at host:/my/path/# " for root). It
should be easy enough to change this, it just served my purpose
like this. It is just a detail.
- Chdir via subshell "cd" and via MC panel works as expected.
- Analogous to Bash, it is possible to use an init file
~/.local/share/mc/ashrc (with auto-fallback to ~/.profile). This is
not even implemented upstream for Zsh and Tcsh at the moment.
- Plese refer to code comments for how and why I implemented the
precmd via PS1 with two-fold indirection. This was necessary to
enable the start of a sub-subshell (user command "ash" from
subshell) without the sub-shell freezing (kill -STOP) or throwing
an error. This is the trickiest part and I am somewhat proud I got
it resolved with my rudimentary knowledge because it was a pain in
the a**. Maybe there is a much simpler way.
- I added some minimal documentation for Ash subshell mode to the
help file, but only in English (needs translation), also extending
Bash mode by mentioning ~/.bashrc (upstream just mentions
~/.local/share/mc/ashrc).
Remark: In order to get ENV into the environment for the init file, I
had to uncomment "g_free (putenv_str)". Initially I had used g_free
because Bash mode also uses it for INPUTRC. I wonder if the g_free also
needs to be removed in that case. Some MC professional might want to
check this.
I hope you are interested in this feature even though until now nobody
has answered my earlier inquiries. I want to thank Harald (ralda) from
the BusyxBox list though for sharing his thoughts and insights with me.
e.g. he gave me the important hint with (not to use) g_free.
Kind regards
--
Alexander Kriegisch
Alexander Kriegisch, 03.03.2012 18:39:
> Never mind, I am one step further:
>
>> case ASH:
>> /* ash does not support precmd, we need to read cwd from the prompt */
>> g_snprintf (precmd, sizeof (precmd),
>> "PS1='$(pwd>&%d; kill -STOP $$)\\u@\\h:\\w\\$ '\n", subshell_pipe[WRITE]);
>> break;
>
> This works for BusyBox ash (tested on mipsel platform). The command will
> be contained in the shell editing history, but for me this is acceptable.
>
> The next thing I want to do is set ENV so as to enable loading my shell
> profile without having to use a login shell. This would be the
> equivalent to Bash's "-rcfile" parameter. I did this:
>
>> 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 */
>> char *putenv_str = g_strconcat ("ENV=", init_file, NULL);
>> putenv (putenv_str);
>> g_free (putenv_str);
>>
>> break;
>
> And later this:
>
>> /* TODO for upstream patch: Execute correct ash/dash/busybox shell (not necessary for Freetz) */
>> case ASH:
>> execl (shell, "sh", (char *) NULL);
>> break;
>
> The problem is that ENV seems to be unset in my subshell's environment,
> i.e. that ~ /.profile (whiche exists) is not evaluated. Do I need to
> somehow export the ENV variable to make it available to the subshell?
> BTW, I am compiling against uClibc 0.9.29, if this is relevant.
>
>
> Alexander Kriegisch, 03.03.2012 14:41:
>> I am on an embedded environment. Bash is available as a separate
>> package, but huge in comparison with the built-in ash of BusyBox.
>>
>> Disclaimer before I continue: I am *not* a C programmer. I can read
>> a bit of C, but not develop anything meaningful other than copy,
>> paste and modify existing code. So bear with me anyway, if you
>> please.
>>
>> I looked into src/subshell.c and tried to figure out what happens
>> there. I have started to add ash support, but MC seems to depend on
>> PROMPT_COMMAND/precmd/fish_prompt, i.e. on a function or alias which
>> is executed each time just before a prompt is printed. Ash does not
>> have anything like that, AFAIK. If I understand correctly, using
>> those pre-commands are MC's way of determining the cwd. I wonder why
>> you do not just use something like pwd or $PWD, but OTOH I do not
>> understand the difficulties of corresponding with the subshell.
>>
>> Anyway, in my case it would be absolutely fine to set a fixed value
>> of PS1='\w\$ ' for the subshell and read the cwd from the prompt. In
>> any case it would be better than not having the option of using ash
>> as a subshell at all.
>>
>> Could anyone maybe provide me with a code snippet or a patch which
>> shows me how to extract the cwd from the prompt assuming that PS1 has
>> the value '\w\$ '? (BTW, '\$' will be evaluated to '$' or '#' in
>> ash, depending on whether you are root or not.)
>>
>> Thank you so much. If I succeed in adding ash as a subshell, I will
>> provide a (raw) patch for you to inspect and maybe refine and
>> include upstream.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 040-ash_as_subshell.patch
URL: <http://lists.midnight-commander.org/pipermail/mc-devel/attachments/20120304/e7d6fef0/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 040-ash_as_subshell_additional.patch
URL: <http://lists.midnight-commander.org/pipermail/mc-devel/attachments/20120304/e7d6fef0/attachment-0001.ksh>
More information about the mc-devel
mailing list