Merge branch '2742_ash'

* 2742_ash:
  revert changes related to BASH shell prompt
  Code refactoring
  Improve subshell chapter in online help
  Minor code changes.
  New subshell types Busybox ash + Debian ash (dash) and some more enhancements plus fish chdir bugfix
  Make MC's special commands not show up in bash's history and also suppress consecutive identical commands.
  Ticket #2742: [Subshell] Support for ash + bugfixes for bash, fish
This commit is contained in:
Slava Zanko 2015-11-10 15:58:18 +03:00
commit b5bfa00130
7 changed files with 389 additions and 68 deletions

View File

@ -2457,7 +2457,7 @@ is substituted.
.\"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 (BusyBox and Debian), tcsh, zsh and fish.
.PP
When the subshell code is activated the Midnight Commander will
spawn a concurrent copy of your shell (the one defined in the
@ -2469,20 +2469,27 @@ subshell as if you had typed it. This also allows you to change the
environment variables, use shell functions and define aliases that are
valid until you quit the Midnight Commander.
.PP
If you are using
.B bash
you can specify startup
commands for the subshell in your ~/.local/share/mc/bashrc file and
special keyboard maps in the ~/.local/share/mc/inputrc file.
.B tcsh
users may specify startup commands in the ~/.local/share/mc/tcshrc file.
users may specify startup commands in ~/.local/share/mc/bashrc (fallback ~/.bashrc)
and special keyboard maps in ~/.local/share/mc/inputrc (fallback ~/.inputrc).
.PP
.B ash/dash
users (BusyBox or Debian) may specify startup commands in ~/.local/share/mc/ashrc (fallback ~/.profile).
.PP
.B tcsh, zsh, fish
users cannot specify mc-specific startup commands at present. They have to rely on
shell-specific startup files.
.PP
When the subshell code is used, you can suspend applications at any
time with the sequence C\-o and jump back to the Midnight Commander, if
you interrupt an application, you will not be able to run other
external commands until you quit the application you interrupted.
.PP
An extra added feature of using the subshell is that the prompt
A special subshell feature (except Bash shell) is that Midnight Commander displays a dynamic prompt
like "user@host:current_path> " (with known problems for fish which displays the prompt in
full-screen mode (Ctrl-o), but not when the MC panels are visible).
.PP
An extra added feature for Bash shell of using the subshell is that the prompt
displayed by the Midnight Commander is the same prompt that you are
currently using in your shell.
.PP
@ -2490,7 +2497,10 @@ The
.\"LINK2"
OPTIONS
.\"OPTIONS"
section has more information on how you can control the subshell code.
section has more information on how you can control subshell usage (-U/-u).
Furthermore, to set a specific subshell different from your current SHELL variable or
login shell defined in /etc/passwd, you may call MC like this:
.B SHELL=/bin/myshell mc
.\"NODE "Chmod"
.SH "Chmod"
The Chmod window is used to change the attribute bits in a group of

View File

@ -97,6 +97,7 @@ mc_global_t mc_global = {
#endif /* !ENABLE_SUBSHELL */
.shell = NULL,
.shell_realpath = NULL,
.xterm_flag = FALSE,
.disable_x11 = FALSE,

View File

@ -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() */

View File

@ -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},

View File

@ -87,6 +87,9 @@
/*** file scope variables ************************************************************************/
/*** file scope functions ************************************************************************/
static char rp_shell[PATH_MAX];
/* --------------------------------------------------------------------------------------------- */
static void
@ -117,6 +120,44 @@ check_codeset (void)
mc_global.utf8_display = str_isutf8 (current_system_codepage);
}
/* --------------------------------------------------------------------------------------------- */
/**
* 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. */
@ -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 */

View File

@ -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_name)
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_name)
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_name)
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_name)
/* 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@$(hostname -s):$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@$(hostname -s):$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\" '";

View File

@ -88,95 +88,99 @@ static const struct test_user_config_paths_ds
CONF_MAIN,
MC_CONFIG_FILE
},
{ /* 0. */
{ /* 1. */
CONF_MAIN,
MC_FHL_INI_FILE
},
{ /* 0. */
{ /* 2. */
CONF_MAIN,
MC_HOTLIST_FILE
},
{ /* 0. */
{ /* 3. */
CONF_MAIN,
GLOBAL_KEYMAP_FILE
},
{ /* 0. */
{ /* 4. */
CONF_MAIN,
MC_USERMENU_FILE
},
{ /* 0. */
{ /* 5. */
CONF_MAIN,
EDIT_SYNTAX_FILE
},
{ /* 0. */
{ /* 6. */
CONF_MAIN,
EDIT_HOME_MENU
},
{ /* 0. */
{ /* 7. */
CONF_MAIN,
EDIT_DIR PATH_SEP_STR "edit.indent.rc"
},
{ /* 0. */
{ /* 8. */
CONF_MAIN,
EDIT_DIR PATH_SEP_STR "edit.spell.rc"
},
{ /* 0. */
{ /* 9. */
CONF_MAIN,
MC_PANELS_FILE
},
{ /* 0. */
{ /* 10. */
CONF_MAIN,
MC_FILEBIND_FILE
},
{ /* 0. */
{ /* 11. */
CONF_DATA,
MC_SKINS_SUBDIR
},
{ /* 0. */
{ /* 12. */
CONF_DATA,
FISH_PREFIX
},
{ /* 0. */
{ /* 13. */
CONF_DATA,
"ashrc"
},
{ /* 14. */
CONF_DATA,
"bashrc"
},
{ /* 0. */
{ /* 15. */
CONF_DATA,
"inputrc"
},
{ /* 0. */
{ /* 16. */
CONF_DATA,
MC_EXTFS_DIR
},
{ /* 0. */
{ /* 17. */
CONF_DATA,
MC_HISTORY_FILE
},
{ /* 0. */
{ /* 18. */
CONF_DATA,
MC_FILEPOS_FILE
},
{ /* 0. */
{ /* 19. */
CONF_DATA,
EDIT_CLIP_FILE
},
{ /* 0. */
{ /* 20. */
CONF_DATA,
MC_MACRO_FILE
},
{ /* 0. */
{ /* 21. */
CONF_CACHE,
"mc.log"
},
{ /* 0. */
{ /* 22. */
CONF_CACHE,
MC_TREESTORE_FILE
},
{ /* 0. */
{ /* 23. */
CONF_CACHE,
EDIT_TEMP_FILE
},
{ /* 0. */
{ /* 24. */
CONF_CACHE,
EDIT_BLOCK_FILE
},