Introduce mc_shell_t type.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2015-11-10 17:23:09 +03:00 committed by Andrew Borodin
parent 81f0b3c6e8
commit 0e79be1b7a
10 changed files with 106 additions and 60 deletions

View File

@ -40,6 +40,7 @@ libmc_la_SOURCES = \
keybind.c keybind.h \ keybind.c keybind.h \
lock.c lock.h \ lock.c lock.h \
serialize.c serialize.h \ serialize.c serialize.h \
shell.h \
timefmt.c timefmt.h \ timefmt.c timefmt.h \
timer.c timer.h timer.c timer.h

View File

@ -79,6 +79,8 @@ mc_global_t mc_global = {
.is_right = FALSE .is_right = FALSE
}, },
.shell = NULL,
.tty = .tty =
{ {
.skin = NULL, .skin = NULL,
@ -96,9 +98,6 @@ mc_global_t mc_global = {
.subshell_pty = 0, .subshell_pty = 0,
#endif /* !ENABLE_SUBSHELL */ #endif /* !ENABLE_SUBSHELL */
.shell = NULL,
.shell_realpath = NULL,
.xterm_flag = FALSE, .xterm_flag = FALSE,
.disable_x11 = FALSE, .disable_x11 = FALSE,
.slow_terminal = FALSE, .slow_terminal = FALSE,

View File

@ -94,6 +94,7 @@
#endif /* !ENABLE_NLS */ #endif /* !ENABLE_NLS */
#include "fs.h" #include "fs.h"
#include "shell.h"
#ifdef USE_MAINTAINER_MODE #ifdef USE_MAINTAINER_MODE
#include "lib/logging.h" #include "lib/logging.h"
@ -231,6 +232,9 @@ typedef struct
gboolean is_right; /* If the selected menu was the right */ gboolean is_right; /* If the selected menu was the right */
} widget; } widget;
/* The user's shell */
mc_shell_t *shell;
struct struct
{ {
/* Use the specified skin */ /* Use the specified skin */
@ -248,15 +252,12 @@ typedef struct
#endif /* !LINUX_CONS_SAVER_C */ #endif /* !LINUX_CONS_SAVER_C */
/* If using a subshell for evaluating commands this is true */ /* If using a subshell for evaluating commands this is true */
gboolean use_subshell; gboolean use_subshell;
#ifdef ENABLE_SUBSHELL #ifdef ENABLE_SUBSHELL
/* File descriptors of the pseudoterminal used by the subshell */ /* File descriptors of the pseudoterminal used by the subshell */
int subshell_pty; int subshell_pty;
#endif /* !ENABLE_SUBSHELL */ #endif /* !ENABLE_SUBSHELL */
/* The user's shell */
char *shell;
char *shell_realpath;
/* This flag is set by xterm detection routine in function main() */ /* This flag is set by xterm detection routine in function main() */
/* It is used by function view_other_cmd() */ /* It is used by function view_other_cmd() */
gboolean xterm_flag; gboolean xterm_flag;

40
lib/shell.h Normal file
View File

@ -0,0 +1,40 @@
/** \file timer.h
* \brief Header: shell structure
*/
#ifndef MC_SHELL_H
#define MC_SHELL_H
/*** typedefs(not structures) and defined constants **********************************************/
/*** enums ***************************************************************************************/
typedef enum
{
BASH,
ASH_BUSYBOX, /* BusyBox default shell (ash) */
DASH, /* Debian variant of ash */
TCSH,
ZSH,
FISH
} shell_type_t;
/*** structures declarations (and typedefs of structures)*****************************************/
typedef struct
{
shell_type_t type;
const char *name;
char *path;
char *real_path;
} mc_shell_t;
/*** global variables defined in .c file *********************************************************/
/*** declarations of public functions ************************************************************/
/*** inline functions **************************************************/
#endif /* MC_SHELL_H */

View File

@ -85,7 +85,7 @@ clipboard_file_to_ext_clip (const gchar * event_group_name, const gchar * event_
cmd = g_strconcat (clipboard_store_path, " ", tmp, " 2>/dev/null", (char *) NULL); cmd = g_strconcat (clipboard_store_path, " ", tmp, " 2>/dev/null", (char *) NULL);
if (cmd != NULL) if (cmd != NULL)
my_system (EXECUTE_AS_SHELL, mc_global.tty.shell, cmd); my_system (EXECUTE_AS_SHELL, mc_global.shell->path, cmd);
g_free (cmd); g_free (cmd);
g_free (tmp); g_free (tmp);

View File

@ -430,12 +430,12 @@ shell_execute (const char *command, int flags)
#ifdef ENABLE_SUBSHELL #ifdef ENABLE_SUBSHELL
if (mc_global.tty.use_subshell) if (mc_global.tty.use_subshell)
if (subshell_state == INACTIVE) if (subshell_state == INACTIVE)
do_execute (mc_global.tty.shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL); do_execute (mc_global.shell->path, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
else else
message (D_ERROR, MSG_ERROR, _("The shell is already running a command")); message (D_ERROR, MSG_ERROR, _("The shell is already running a command"));
else else
#endif /* ENABLE_SUBSHELL */ #endif /* ENABLE_SUBSHELL */
do_execute (mc_global.tty.shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL); do_execute (mc_global.shell->path, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
g_free (cmd); g_free (cmd);
} }
@ -445,7 +445,7 @@ shell_execute (const char *command, int flags)
void void
exec_shell (void) exec_shell (void)
{ {
do_execute (mc_global.tty.shell, 0, 0); do_execute (mc_global.shell->path, 0, 0);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -496,7 +496,7 @@ toggle_panels (void)
fprintf (stderr, _("Type 'exit' to return to the Midnight Commander")); fprintf (stderr, _("Type 'exit' to return to the Midnight Commander"));
fprintf (stderr, "\n\r\n\r"); fprintf (stderr, "\n\r\n\r");
my_system (EXECUTE_INTERNAL, mc_global.tty.shell, NULL); my_system (EXECUTE_INTERNAL, mc_global.shell->path, NULL);
} }
else else
get_key_code (0); get_key_code (0);

View File

@ -168,6 +168,8 @@ OS_Setup (void)
const char *datadir_env; const char *datadir_env;
mc_global.shell = g_new0 (mc_shell_t, 1);
shell_env = getenv ("SHELL"); shell_env = getenv ("SHELL");
if ((shell_env == NULL) || (shell_env[0] == '\0')) if ((shell_env == NULL) || (shell_env[0] == '\0'))
{ {
@ -176,18 +178,18 @@ OS_Setup (void)
pwd = getpwuid (geteuid ()); pwd = getpwuid (geteuid ());
if (pwd != NULL) if (pwd != NULL)
mc_global.tty.shell = g_strdup (pwd->pw_shell); mc_global.shell->path = g_strdup (pwd->pw_shell);
} }
else else
/* 1st choice: SHELL environment variable */ /* 1st choice: SHELL environment variable */
mc_global.tty.shell = g_strdup (shell_env); mc_global.shell->path = g_strdup (shell_env);
if ((mc_global.tty.shell == NULL) || (mc_global.tty.shell[0] == '\0')) if ((mc_global.shell->path == NULL) || (mc_global.shell->path[0] == '\0'))
{ {
g_free (mc_global.tty.shell); g_free (mc_global.shell->path);
mc_global.tty.shell = mc_get_system_shell (); mc_global.shell->path = mc_get_system_shell ();
} }
mc_global.tty.shell_realpath = mc_realpath (mc_global.tty.shell, rp_shell); mc_global.shell->real_path = mc_realpath (mc_global.shell->path, rp_shell);
/* This is the directory, where MC was installed, on Unix this is DATADIR */ /* This is the directory, where MC was installed, on Unix this is DATADIR */
/* and can be overriden by the MC_DATADIR environment variable */ /* and can be overriden by the MC_DATADIR environment variable */
@ -301,7 +303,9 @@ main (int argc, char *argv[])
startup_exit_falure: startup_exit_falure:
fprintf (stderr, _("Failed to run:\n%s\n"), mcerror->message); fprintf (stderr, _("Failed to run:\n%s\n"), mcerror->message);
g_error_free (mcerror); g_error_free (mcerror);
g_free (mc_global.tty.shell);
g_free (mc_global.shell->path);
g_free (mc_global.shell);
startup_exit_ok: startup_exit_ok:
str_uninit_strings (); str_uninit_strings ();
mc_timer_destroy (mc_global.timer); mc_timer_destroy (mc_global.timer);
@ -508,7 +512,8 @@ main (int argc, char *argv[])
} }
g_free (last_wd_string); g_free (last_wd_string);
g_free (mc_global.tty.shell); g_free (mc_global.shell->path);
g_free (mc_global.shell);
done_key (); done_key ();

View File

@ -132,15 +132,15 @@ enum
}; };
/* Subshell type (gleaned from the SHELL environment variable, if available) */ /* Subshell type (gleaned from the SHELL environment variable, if available) */
static enum //static enum
{ //{
BASH, // BASH,
ASH_BUSYBOX, /* BusyBox default shell (ash) */ // ASH_BUSYBOX, /* BusyBox default shell (ash) */
DASH, /* Debian variant of ash */ // DASH, /* Debian variant of ash */
TCSH, // TCSH,
ZSH, // ZSH,
FISH // FISH
} subshell_type; //} subshell_type;
/*** file scope variables ************************************************************************/ /*** file scope variables ************************************************************************/
@ -280,7 +280,7 @@ init_subshell_child (const char *pty_name)
putenv (g_strdup (sid_str)); putenv (g_strdup (sid_str));
} }
switch (subshell_type) switch (mc_global.shell->type)
{ {
case BASH: case BASH:
/* Do we have a custom init file ~/.local/share/mc/bashrc? */ /* Do we have a custom init file ~/.local/share/mc/bashrc? */
@ -338,7 +338,7 @@ init_subshell_child (const char *pty_name)
break; break;
default: default:
fprintf (stderr, __FILE__ ": unimplemented subshell type %d\r\n", subshell_type); fprintf (stderr, __FILE__ ": unimplemented subshell type %d\r\n", mc_global.shell->type);
my_exit (FORK_FAILURE); my_exit (FORK_FAILURE);
} }
@ -363,16 +363,16 @@ init_subshell_child (const char *pty_name)
/* Execute the subshell at last */ /* Execute the subshell at last */
switch (subshell_type) switch (mc_global.shell->type)
{ {
case BASH: case BASH:
execl (mc_global.tty.shell, "bash", "-rcfile", init_file, (char *) NULL); execl (mc_global.shell->path, "bash", "-rcfile", init_file, (char *) NULL);
break; break;
case ZSH: case ZSH:
/* Use -g to exclude cmds beginning with space from history /* Use -g to exclude cmds beginning with space from history
* and -Z to use the line editor on non-interactive term */ * and -Z to use the line editor on non-interactive term */
execl (mc_global.tty.shell, "zsh", "-Z", "-g", (char *) NULL); execl (mc_global.shell->path, "zsh", "-Z", "-g", (char *) NULL);
break; break;
@ -380,7 +380,7 @@ init_subshell_child (const char *pty_name)
case DASH: case DASH:
case TCSH: case TCSH:
case FISH: case FISH:
execl (mc_global.tty.shell, mc_global.tty.shell, (char *) NULL); execl (mc_global.shell->path, mc_global.shell->path, (char *) NULL);
break; break;
default: default:
@ -805,22 +805,22 @@ init_subshell_type (void)
/* Find out what type of shell we have. Also consider real paths (resolved symlinks) /* 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. */ * because e.g. csh might point to tcsh, ash to dash or busybox, sh to anything. */
if (strstr (mc_global.tty.shell, "/zsh") != NULL if (strstr (mc_global.shell->path, "/zsh") != NULL
|| strstr (mc_global.tty.shell_realpath, "/zsh") != NULL || getenv ("ZSH_VERSION") != NULL) || strstr (mc_global.shell->real_path, "/zsh") != NULL || getenv ("ZSH_VERSION") != NULL)
/* Also detects ksh symlinked to zsh */ /* Also detects ksh symlinked to zsh */
subshell_type = ZSH; mc_global.shell->type = ZSH;
else if (strstr (mc_global.tty.shell, "/tcsh") != NULL else if (strstr (mc_global.shell->path, "/tcsh") != NULL
|| strstr (mc_global.tty.shell_realpath, "/tcsh") != NULL) || strstr (mc_global.shell->real_path, "/tcsh") != NULL)
/* Also detects csh symlinked to tcsh */ /* Also detects csh symlinked to tcsh */
subshell_type = TCSH; mc_global.shell->type = TCSH;
else if (strstr (mc_global.tty.shell, "/fish") != NULL else if (strstr (mc_global.shell->path, "/fish") != NULL
|| strstr (mc_global.tty.shell_realpath, "/fish") != NULL) || strstr (mc_global.shell->real_path, "/fish") != NULL)
subshell_type = FISH; mc_global.shell->type = FISH;
else if (strstr (mc_global.tty.shell, "/dash") != NULL else if (strstr (mc_global.shell->path, "/dash") != NULL
|| strstr (mc_global.tty.shell_realpath, "/dash") != NULL) || strstr (mc_global.shell->real_path, "/dash") != NULL)
/* Debian ash (also found if symlinked to by ash/sh) */ /* Debian ash (also found if symlinked to by ash/sh) */
subshell_type = DASH; mc_global.shell->type = DASH;
else if (strstr (mc_global.tty.shell_realpath, "/busybox") != NULL) else if (strstr (mc_global.shell->real_path, "/busybox") != NULL)
{ {
/* If shell is symlinked to busybox, assume it is an ash, even though theoretically /* 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). * it could also be a hush (a mini shell for non-MMU systems deactivated by default).
@ -829,11 +829,11 @@ init_subshell_type (void)
* Sometimes even bash is symlinked to busybox (CONFIG_FEATURE_BASH_IS_ASH option), * 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" * so we need to check busybox symlinks *before* checking for the name "bash"
* in order to avoid that case. */ * in order to avoid that case. */
subshell_type = ASH_BUSYBOX; mc_global.shell->type = ASH_BUSYBOX;
} }
else if (strstr (mc_global.tty.shell, "/bash") != NULL || getenv ("BASH") != NULL) else if (strstr (mc_global.shell->path, "/bash") != NULL || getenv ("BASH") != NULL)
/* If bash is not symlinked to busybox, it is safe to assume it is a real bash */ /* If bash is not symlinked to busybox, it is safe to assume it is a real bash */
subshell_type = BASH; mc_global.shell->type = BASH;
else else
{ {
mc_global.tty.use_subshell = FALSE; mc_global.tty.use_subshell = FALSE;
@ -856,7 +856,7 @@ init_subshell_type (void)
static void static void
init_subshell_precmd (char *precmd, size_t buff_size) init_subshell_precmd (char *precmd, size_t buff_size)
{ {
switch (subshell_type) switch (mc_global.shell->type)
{ {
case BASH: case BASH:
g_snprintf (precmd, buff_size, g_snprintf (precmd, buff_size,
@ -978,7 +978,7 @@ subshell_name_quote (const char *s)
const char *su, *n; const char *su, *n;
const char *quote_cmd_start, *quote_cmd_end; const char *quote_cmd_start, *quote_cmd_end;
if (subshell_type == FISH) if (mc_global.shell->type == FISH)
{ {
quote_cmd_start = "(printf \"%b\" '"; quote_cmd_start = "(printf \"%b\" '";
quote_cmd_end = "')"; quote_cmd_end = "')";
@ -1096,7 +1096,7 @@ init_subshell (void)
/* Create a pipe for receiving the subshell's CWD */ /* Create a pipe for receiving the subshell's CWD */
if (subshell_type == TCSH) if (mc_global.shell->type == TCSH)
{ {
g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d", g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d",
mc_tmpdir (), (int) getpid ()); mc_tmpdir (), (int) getpid ());
@ -1155,7 +1155,7 @@ init_subshell (void)
* shell code. It is vital that each one-liner ends with a line feed character ("\n" ). * shell code. It is vital that each one-liner ends with a line feed character ("\n" ).
*/ */
switch (subshell_type) switch (mc_global.shell->type)
{ {
case BASH: case BASH:
g_snprintf (precmd, sizeof (precmd), g_snprintf (precmd, sizeof (precmd),
@ -1414,7 +1414,7 @@ exit_subshell (void)
if (subshell_quit) if (subshell_quit)
{ {
if (subshell_type == TCSH) if (mc_global.shell->type == TCSH)
{ {
if (unlink (tcsh_fifo) == -1) if (unlink (tcsh_fifo) == -1)
fprintf (stderr, "Cannot remove named pipe %s: %s\r\n", fprintf (stderr, "Cannot remove named pipe %s: %s\r\n",
@ -1488,7 +1488,7 @@ do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt)
bPathNotEq = strcmp (subshell_cwd, pcwd) != 0; bPathNotEq = strcmp (subshell_cwd, pcwd) != 0;
if (bPathNotEq && subshell_type == TCSH) if (bPathNotEq && mc_global.shell->type == TCSH)
{ {
char rp_subshell_cwd[PATH_MAX]; char rp_subshell_cwd[PATH_MAX];
char rp_current_panel_cwd[PATH_MAX]; char rp_current_panel_cwd[PATH_MAX];
@ -1517,7 +1517,7 @@ do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt)
} }
/* Really escape Zsh history */ /* Really escape Zsh history */
if (subshell_type == ZSH) if (mc_global.shell->type == ZSH)
{ {
/* Per Zsh documentation last command prefixed with space lingers in the internal history /* Per Zsh documentation last command prefixed with space lingers in the internal history
* until the next command is entered before it vanishes. To make it vanish right away, * until the next command is entered before it vanishes. To make it vanish right away,

View File

@ -848,7 +848,7 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive,
g_free (quoted_archive_name); g_free (quoted_archive_name);
open_error_pipe (); open_error_pipe ();
retval = my_system (EXECUTE_AS_SHELL, mc_global.tty.shell, cmd); retval = my_system (EXECUTE_AS_SHELL, mc_global.shell->path, cmd);
g_free (cmd); g_free (cmd);
close_error_pipe (D_ERROR, NULL); close_error_pipe (D_ERROR, NULL);
return retval; return retval;

View File

@ -35,7 +35,7 @@
#include "src/filemanager/midnight.h" #include "src/filemanager/midnight.h"
#include "src/filemanager/tree.h" #include "src/filemanager/tree.h"
#ifdef ENABLE_SUBSHELL #ifdef ENABLE_SUBSHELL
#include "src/subshell.h" #include "src/subshell/subshell.h"
#endif /* ENABLE_SUBSHELL */ #endif /* ENABLE_SUBSHELL */
#include "src/filemanager/command.c" #include "src/filemanager/command.c"