From e4f7714ab101bf752f92ff84bff70af12dd4acec Mon Sep 17 00:00:00 2001
From: Pavel Roskin <proski@gnu.org>
Date: Sun, 22 Jun 2003 09:17:46 +0000
Subject: [PATCH] * execute.c: New file with all functions for execution and
 toggling panels not specific to subshell. * execute.h: Corresponding header.
 * Makefile.am: Adjust for the above.

---
 src/ChangeLog   |   5 +
 src/Makefile.am |  10 +-
 src/cmd.c       | 127 +----------------
 src/command.c   |   1 +
 src/dlg.c       |   1 +
 src/execute.c   | 362 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/execute.h   |  22 +++
 src/ext.c       |   1 +
 src/main.c      | 159 +--------------------
 src/main.h      |  15 +-
 src/screen.c    |   1 +
 src/text.c      |  45 ------
 src/user.c      |   1 +
 src/util.h      |   2 -
 src/utilunix.c  |   1 +
 src/view.c      |   1 +
 16 files changed, 410 insertions(+), 344 deletions(-)
 create mode 100644 src/execute.c
 create mode 100644 src/execute.h

diff --git a/src/ChangeLog b/src/ChangeLog
index 35b284b9e..4583d41c7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,10 @@
 2003-06-22  Pavel Roskin  <proski@gnu.org>
 
+	* execute.c: New file with all functions for execution and
+	toggling panels not specific to subshell.
+	* execute.h: Corresponding header.
+	* Makefile.am: Adjust for the above.
+
 	* main.c (execute): Eliminate.  Fix all dependencies.
 	(shell_execute): Constify string argument.
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 1016a8a8e..c3f19af64 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,11 +46,11 @@ SRCS =	achown.c achown.h background.c background.h boxes.c boxes.h	\
 	chmod.c chmod.h chown.c chown.h cmd.c cmd.h color.c color.h	\
 	command.c command.h complete.c complete.h cons.handler.c	\
 	cons.saver.h dialog.c dialog.h dir.c dir.h dlg.c dlg.h		\
-	eregex.h ext.c ext.h file.c filegui.c filegui.h file.h		\
-	filenot.c fileopctx.c fileopctx.h find.c find.h findme.c	\
-	findme.h fs.h fsusage.c fsusage.h global.h help.c help.h	\
-	hotlist.c hotlist.h i18n.h info.c info.h key.c key.h		\
-	keyxdef.c layout.c layout.h learn.c learn.h listmode.c		\
+	eregex.h execute.c execute.h ext.c ext.h file.c filegui.c	\
+	filegui.h file.h filenot.c fileopctx.c fileopctx.h find.c	\
+	find.h findme.c	findme.h fs.h fsusage.c fsusage.h global.h	\
+	help.c help.h hotlist.c hotlist.h i18n.h info.c info.h key.c	\
+	key.h keyxdef.c layout.c layout.h learn.c learn.h listmode.c	\
 	listmode.h main.c main.h menu.c menu.h				\
 	mountlist.c mountlist.h mouse.c mouse.h myslang.h option.c	\
 	option.h panel.h panelize.c panelize.h poptalloca.h popt.c	\
diff --git a/src/cmd.c b/src/cmd.c
index dd875bfc3..a94d61e83 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -65,6 +65,7 @@
 #include "boxes.h"		/* cd_dialog() */
 #include "setup.h"		/* save_setup() */
 #include "profile.h"		/* PROFILE_NAME */
+#include "execute.h"		/* toggle_panels() */
 
 #ifndef MAP_FILE
 #   define MAP_FILE 0
@@ -84,50 +85,6 @@ int source_route = 0;
 int use_internal_edit = 1;
 
 
-/*
- * Execute command on a filename that can be on VFS.
- * Errors are reported to the user.
- */
-static void
-execute_with_vfs_arg (const char *command, const char *filename)
-{
-    char *localcopy;
-    char *fn;
-    struct stat st;
-    time_t mtime;
-
-    /* Simplest case, this file is local */
-    if (!filename || vfs_file_is_local (filename)) {
-	execute_internal (command, filename);
-	return;
-    }
-
-    /* FIXME: Creation of new files on VFS is not supported */
-    if (!*filename)
-	return;
-
-    localcopy = mc_getlocalcopy (filename);
-    if (localcopy == NULL) {
-	message (1, MSG_ERROR, _(" Cannot fetch a local copy of %s "),
-		 filename);
-	return;
-    }
-
-    /*
-     * filename can be an entry on panel, it can be changed by executing
-     * the command, so make a copy.  Smarter VFS code would make the code
-     * below unnecessary.
-     */
-    fn = g_strdup (filename);
-    mc_stat (localcopy, &st);
-    mtime = st.st_mtime;
-    execute_internal (command, localcopy);
-    mc_stat (localcopy, &st);
-    mc_ungetlocalcopy (fn, localcopy, mtime != st.st_mtime);
-    g_free (fn);
-}
-
-
 int
 view_file_at_line (char *filename, int plain_view, int internal,
 		   int start_line)
@@ -964,87 +921,15 @@ void
 view_other_cmd (void)
 {
     static int message_flag = TRUE;
-#ifdef HAVE_SUBSHELL_SUPPORT
-    char *new_dir = NULL;
-    char **new_dir_p;
-#endif /* HAVE_SUBSHELL_SUPPORT */
 
-    if (!xterm_flag && !console_flag && !use_subshell){
+    if (!xterm_flag && !console_flag && !use_subshell) {
 	if (message_flag)
-	    message (1, MSG_ERROR, _(" Not an xterm or Linux console; \n"
-				     " the panels cannot be toggled. "));
+	    message (1, MSG_ERROR,
+		     _(" Not an xterm or Linux console; \n"
+		       " the panels cannot be toggled. "));
 	message_flag = FALSE;
     } else {
-	channels_down ();
-	disable_mouse ();
-	if (clear_before_exec)
-	    clr_scr ();
-        if (alternate_plus_minus)
-            numeric_keypad_mode ();
-#ifndef HAVE_SLANG
-	/* With slang we don't want any of this, since there
-	 * is no mc_raw_mode supported
-	 */
-	reset_shell_mode ();
-	noecho ();
-#endif /* !HAVE_SLANG */
-	keypad(stdscr, FALSE);
-	endwin ();
-	do_exit_ca_mode ();
-	mc_raw_mode ();
-	if (console_flag)
-	    restore_console ();
-
-#ifdef HAVE_SUBSHELL_SUPPORT
-	if (use_subshell){
-	    new_dir_p = vfs_current_is_local () ? &new_dir : NULL;
-	    if (invoke_subshell (NULL, VISIBLY, new_dir_p))
-		quiet_quit_cmd();  /* User did `exit' or `logout': quit MC quietly */
-	} else
-#endif /* HAVE_SUBSHELL_SUPPORT */
-	{
-	    if (output_starts_shell){
-		fprintf (stderr,
-		 _("Type `exit' to return to the Midnight Commander"));
-		fprintf (stderr, "\n\r\n\r");
-			 
-		my_system (EXECUTE_AS_SHELL, shell, NULL);
-	    } else
-		get_key_code (0);
-	}
-	if (console_flag)
-	    handle_console (CONSOLE_SAVE);
-
-	do_enter_ca_mode ();
-
-	reset_prog_mode ();
-	keypad(stdscr, TRUE);
-
-	/* Prevent screen flash when user did 'exit' or 'logout' within
-	   subshell */
-	if (quit)
-	    return;
-
-	enable_mouse ();
-	channels_up ();
-        if (alternate_plus_minus)
-            application_keypad_mode ();
-
-#ifdef HAVE_SUBSHELL_SUPPORT
-	if (use_subshell){
-	    load_prompt (0, 0);
-	    if (new_dir)
-		do_possible_cd (new_dir);
-	    if (console_flag && output_lines)
-		show_console_contents (output_start_y,
-				       LINES-keybar_visible-output_lines-1,
-				       LINES-keybar_visible-1);
-	}
-#endif /* HAVE_SUBSHELL_SUPPORT */
-        touchwin (stdscr);
-	
-	repaint_screen ();
-	update_xterm_title_path ();
+	toggle_panels ();
     }
 }
 
diff --git a/src/command.c b/src/command.c
index 6aa60e1ea..89824e89f 100644
--- a/src/command.c
+++ b/src/command.c
@@ -37,6 +37,7 @@
 #include "subshell.h"		/* SUBSHELL_EXIT */
 #include "tree.h"		/* for tree_chdir */
 #include "color.h"		/* DEFAULT_COLOR */
+#include "execute.h"		/* shell_execute */
 
 /* This holds the command line */
 WInput *cmdline;
diff --git a/src/dlg.c b/src/dlg.c
index 0f70bfd75..ff9186188 100644
--- a/src/dlg.c
+++ b/src/dlg.c
@@ -32,6 +32,7 @@
 #include "dlg.h"
 #include "dialog.h"	/* For push_refresh() and pop_refresh() */
 #include "layout.h"
+#include "execute.h"
 #include "main.h"
 
 #define waddc(w,y1,x1,c) move (w->y+y1, w->x+x1); addch (c)
diff --git a/src/execute.c b/src/execute.c
new file mode 100644
index 000000000..9064f8635
--- /dev/null
+++ b/src/execute.c
@@ -0,0 +1,362 @@
+/* Execution routines for GNU Midnight Commander
+   Copyright (C) 1994-2003 The Free Software Foundation
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <config.h>
+#include "global.h"
+#include "tty.h"
+#include "win.h"
+#include "key.h"
+#include "main.h"
+#include "cons.saver.h"
+#include "subshell.h"
+#include "layout.h"
+#include "dialog.h"
+#include "wtools.h"
+#include "execute.h"
+
+
+/* to show nice prompts */
+static int last_paused = 0;
+
+static void
+edition_post_exec (void)
+{
+    do_enter_ca_mode ();
+
+    /* FIXME: Missing on slang endwin? */
+    reset_prog_mode ();
+    flushinp ();
+
+    keypad (stdscr, TRUE);
+    mc_raw_mode ();
+    channels_up ();
+    enable_mouse ();
+    if (alternate_plus_minus)
+	application_keypad_mode ();
+}
+
+
+static void
+edition_pre_exec (void)
+{
+    if (clear_before_exec)
+	clr_scr ();
+    else {
+	if (!(console_flag || xterm_flag))
+	    printf ("\n\n");
+    }
+
+    channels_down ();
+    disable_mouse ();
+
+    reset_shell_mode ();
+    keypad (stdscr, FALSE);
+    endwin ();
+
+    numeric_keypad_mode ();
+
+    /* on xterms: maybe endwin did not leave the terminal on the shell
+     * screen page: do it now.
+     *
+     * Do not move this before endwin: in some systems rmcup includes
+     * a call to clear screen, so it will end up clearing the shell screen.
+     */
+    do_exit_ca_mode ();
+}
+
+
+/* Set up the terminal before executing a program */
+static void
+pre_exec (void)
+{
+    use_dash (0);
+    edition_pre_exec ();
+}
+
+
+void
+do_execute (const char *shell, const char *command, int flags)
+{
+#ifdef HAVE_SUBSHELL_SUPPORT
+    char *new_dir = NULL;
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+
+#ifdef USE_VFS
+    char *old_vfs_dir = 0;
+
+    if (!vfs_current_is_local ())
+	old_vfs_dir = g_strdup (vfs_get_current_dir ());
+#endif				/* USE_VFS */
+
+    save_cwds_stat ();
+    pre_exec ();
+    if (console_flag)
+	restore_console ();
+
+    if (!use_subshell && !(flags & EXECUTE_INTERNAL && command)) {
+	printf ("%s%s%s\n", last_paused ? "\r\n" : "", prompt, command);
+	last_paused = 0;
+    }
+#ifdef HAVE_SUBSHELL_SUPPORT
+    if (use_subshell && !(flags & EXECUTE_INTERNAL)) {
+	do_update_prompt ();
+
+	/* We don't care if it died, higher level takes care of this */
+#ifdef USE_VFS
+	invoke_subshell (command, VISIBLY, old_vfs_dir ? 0 : &new_dir);
+#else
+	invoke_subshell (command, VISIBLY, &new_dir);
+#endif				/* !USE_VFS */
+    } else
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+	my_system (flags, shell, command);
+
+    if (!(flags & EXECUTE_INTERNAL)) {
+	if ((pause_after_run == pause_always
+	     || (pause_after_run == pause_on_dumb_terminals && !xterm_flag
+		 && !console_flag)) && !quit
+#ifdef HAVE_SUBSHELL_SUPPORT
+	    && subshell_state != RUNNING_COMMAND
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+	    ) {
+	    printf ("%s\r\n", _("Press any key to continue..."));
+	    last_paused = 1;
+	    fflush (stdout);
+	    mc_raw_mode ();
+	    getch ();
+	}
+	if (console_flag) {
+	    if (output_lines && keybar_visible) {
+		putchar ('\n');
+		fflush (stdout);
+	    }
+	}
+    }
+
+    if (console_flag)
+	handle_console (CONSOLE_SAVE);
+    edition_post_exec ();
+
+#ifdef HAVE_SUBSHELL_SUPPORT
+    if (new_dir)
+	do_possible_cd (new_dir);
+
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+
+#ifdef USE_VFS
+    if (old_vfs_dir) {
+	mc_chdir (old_vfs_dir);
+	g_free (old_vfs_dir);
+    }
+#endif				/* USE_VFS */
+
+    update_panels (UP_OPTIMIZE, UP_KEEPSEL);
+    update_xterm_title_path ();
+
+    do_refresh ();
+    use_dash (TRUE);
+}
+
+
+/* Executes a command */
+void
+shell_execute (const char *command, int flags)
+{
+#ifdef HAVE_SUBSHELL_SUPPORT
+    if (use_subshell)
+	if (subshell_state == INACTIVE)
+	    do_execute (shell, command, flags | EXECUTE_AS_SHELL);
+	else
+	    message (1, MSG_ERROR,
+		     _(" The shell is already running a command "));
+    else
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+	do_execute (shell, command, flags | EXECUTE_AS_SHELL);
+}
+
+
+void
+exec_shell (void)
+{
+    do_execute (shell, 0, 0);
+}
+
+
+void
+toggle_panels (void)
+{
+#ifdef HAVE_SUBSHELL_SUPPORT
+    char *new_dir = NULL;
+    char **new_dir_p;
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+
+    channels_down ();
+    disable_mouse ();
+    if (clear_before_exec)
+	clr_scr ();
+    if (alternate_plus_minus)
+	numeric_keypad_mode ();
+#ifndef HAVE_SLANG
+    /* With slang we don't want any of this, since there
+     * is no mc_raw_mode supported
+     */
+    reset_shell_mode ();
+    noecho ();
+#endif				/* !HAVE_SLANG */
+    keypad (stdscr, FALSE);
+    endwin ();
+    do_exit_ca_mode ();
+    mc_raw_mode ();
+    if (console_flag)
+	restore_console ();
+
+#ifdef HAVE_SUBSHELL_SUPPORT
+    if (use_subshell) {
+	new_dir_p = vfs_current_is_local ()? &new_dir : NULL;
+	if (invoke_subshell (NULL, VISIBLY, new_dir_p))
+	    quiet_quit_cmd ();	/* User did `exit' or `logout': quit MC quietly */
+    } else
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+    {
+	if (output_starts_shell) {
+	    fprintf (stderr,
+		     _("Type `exit' to return to the Midnight Commander"));
+	    fprintf (stderr, "\n\r\n\r");
+
+	    my_system (EXECUTE_AS_SHELL, shell, NULL);
+	} else
+	    get_key_code (0);
+    }
+    if (console_flag)
+	handle_console (CONSOLE_SAVE);
+
+    do_enter_ca_mode ();
+
+    reset_prog_mode ();
+    keypad (stdscr, TRUE);
+
+    /* Prevent screen flash when user did 'exit' or 'logout' within
+       subshell */
+    if (quit)
+	return;
+
+    enable_mouse ();
+    channels_up ();
+    if (alternate_plus_minus)
+	application_keypad_mode ();
+
+#ifdef HAVE_SUBSHELL_SUPPORT
+    if (use_subshell) {
+	load_prompt (0, 0);
+	if (new_dir)
+	    do_possible_cd (new_dir);
+	if (console_flag && output_lines)
+	    show_console_contents (output_start_y,
+				   LINES - keybar_visible - output_lines -
+				   1, LINES - keybar_visible - 1);
+    }
+#endif				/* HAVE_SUBSHELL_SUPPORT */
+    touchwin (stdscr);
+
+    repaint_screen ();
+    update_xterm_title_path ();
+}
+
+
+static void
+do_suspend_cmd (void)
+{
+    pre_exec ();
+
+    if (console_flag && !use_subshell)
+	restore_console ();
+
+#ifdef SIGTSTP
+    {
+	struct sigaction sigtstp_action;
+
+	/* Make sure that the SIGTSTP below will suspend us directly,
+	   without calling ncurses' SIGTSTP handler; we *don't* want
+	   ncurses to redraw the screen immediately after the SIGCONT */
+	sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
+
+	kill (getpid (), SIGTSTP);
+
+	/* Restore previous SIGTSTP action */
+	sigaction (SIGTSTP, &sigtstp_action, NULL);
+    }
+#endif				/* SIGTSTP */
+
+    if (console_flag && !use_subshell)
+	handle_console (CONSOLE_SAVE);
+
+    edition_post_exec ();
+}
+
+
+void
+suspend_cmd (void)
+{
+    save_cwds_stat ();
+    do_suspend_cmd ();
+    update_panels (UP_OPTIMIZE, UP_KEEPSEL);
+    do_refresh ();
+}
+
+
+/*
+ * Execute command on a filename that can be on VFS.
+ * Errors are reported to the user.
+ */
+void
+execute_with_vfs_arg (const char *command, const char *filename)
+{
+    char *localcopy;
+    char *fn;
+    struct stat st;
+    time_t mtime;
+
+    /* Simplest case, this file is local */
+    if (!filename || vfs_file_is_local (filename)) {
+	do_execute (command, filename, EXECUTE_INTERNAL);
+	return;
+    }
+
+    /* FIXME: Creation of new files on VFS is not supported */
+    if (!*filename)
+	return;
+
+    localcopy = mc_getlocalcopy (filename);
+    if (localcopy == NULL) {
+	message (1, MSG_ERROR, _(" Cannot fetch a local copy of %s "),
+		 filename);
+	return;
+    }
+
+    /*
+     * filename can be an entry on panel, it can be changed by executing
+     * the command, so make a copy.  Smarter VFS code would make the code
+     * below unnecessary.
+     */
+    fn = g_strdup (filename);
+    mc_stat (localcopy, &st);
+    mtime = st.st_mtime;
+    do_execute (command, localcopy, EXECUTE_INTERNAL);
+    mc_stat (localcopy, &st);
+    mc_ungetlocalcopy (fn, localcopy, mtime != st.st_mtime);
+    g_free (fn);
+}
diff --git a/src/execute.h b/src/execute.h
new file mode 100644
index 000000000..52261da78
--- /dev/null
+++ b/src/execute.h
@@ -0,0 +1,22 @@
+#ifndef MC_EXECUTE_H
+#define MC_EXECUTE_H
+
+#define EXECUTE_INTERNAL   1
+#define EXECUTE_AS_SHELL   4
+
+/* Execute functions that use the shell to execute */
+void shell_execute (const char *command, int flags);
+
+/* This one executes a shell */
+void exec_shell (void);
+
+/* Handle toggling panels by Ctrl-O */
+void toggle_panels (void);
+
+/* Handle toggling panels by Ctrl-Z */
+void suspend_cmd (void);
+
+/* Execute command on a filename that can be on VFS */
+void execute_with_vfs_arg (const char *command, const char *filename);
+
+#endif /* !MC_EXECUTE_H */
diff --git a/src/ext.c b/src/ext.c
index 5544d9389..b1c0ecd5a 100644
--- a/src/ext.c
+++ b/src/ext.c
@@ -35,6 +35,7 @@
 #include "wtools.h"
 #include "ext.h"
 #include "view.h"
+#include "execute.h"
 
 #include "cons.saver.h"
 #include "layout.h"
diff --git a/src/main.c b/src/main.c
index 564737cf2..df33ead36 100644
--- a/src/main.c
+++ b/src/main.c
@@ -67,6 +67,7 @@
 #include "learn.h"		/* learn_keys() */
 #include "listmode.h"
 #include "background.h"
+#include "execute.h"
 #include "ext.h"		/* For flush_extension_file() */
 
 /* Listbox for the command history feature */
@@ -145,9 +146,6 @@ int alternate_plus_minus = 0;
  */
 int only_leading_plus_minus = 1;
 
-/* If true, after executing a command, wait for a keystroke */
-enum { pause_never, pause_on_dumb_terminals, pause_always };
-
 int pause_after_run = pause_on_dumb_terminals;
 
 /* It true saves the setup when quitting */
@@ -281,9 +279,6 @@ static int edit_one_file_start_line = 0;
    shut down */
 int midnight_shutdown = 0;
 
-/* to show nice prompts */
-static int last_paused = 0;
-
 /* Used for keeping track of the original stdout */
 int stdout_fd = 0;
 
@@ -435,14 +430,6 @@ update_panels (int force_update, char *current_file)
     mc_chdir (panel->cwd);
 }
 
-/* Sets up the terminal before executing a program */
-static void
-pre_exec (void)
-{
-    use_dash (0);
-    edition_pre_exec ();
-}
-
 /* Save current stat of directories to avoid reloading the panels */
 /* when no modifications have taken place */
 void
@@ -484,111 +471,6 @@ restore_console (void)
     handle_console (CONSOLE_RESTORE);
 }
 
-void
-exec_shell (void)
-{
-    do_execute (shell, 0, 0);
-}
-
-void
-do_execute (const char *shell, const char *command, int flags)
-{
-#ifdef HAVE_SUBSHELL_SUPPORT
-    char *new_dir = NULL;
-#endif				/* HAVE_SUBSHELL_SUPPORT */
-
-#ifdef USE_VFS
-    char *old_vfs_dir = 0;
-
-    if (!vfs_current_is_local ())
-	old_vfs_dir = g_strdup (vfs_get_current_dir ());
-#endif				/* USE_VFS */
-
-    save_cwds_stat ();
-    pre_exec ();
-    if (console_flag)
-	restore_console ();
-
-    if (!use_subshell && !(flags & EXECUTE_INTERNAL && command)) {
-	printf ("%s%s%s\n", last_paused ? "\r\n" : "", prompt, command);
-	last_paused = 0;
-    }
-#ifdef HAVE_SUBSHELL_SUPPORT
-    if (use_subshell && !(flags & EXECUTE_INTERNAL)) {
-	do_update_prompt ();
-
-	/* We don't care if it died, higher level takes care of this */
-#ifdef USE_VFS
-	invoke_subshell (command, VISIBLY, old_vfs_dir ? 0 : &new_dir);
-#else
-	invoke_subshell (command, VISIBLY, &new_dir);
-#endif				/* !USE_VFS */
-    } else
-#endif				/* HAVE_SUBSHELL_SUPPORT */
-	my_system (flags, shell, command);
-
-    if (!(flags & EXECUTE_INTERNAL)) {
-	if ((pause_after_run == pause_always
-	     || (pause_after_run == pause_on_dumb_terminals && !xterm_flag
-		 && !console_flag)) && !quit
-#ifdef HAVE_SUBSHELL_SUPPORT
-	    && subshell_state != RUNNING_COMMAND
-#endif				/* HAVE_SUBSHELL_SUPPORT */
-	    ) {
-	    printf ("%s\r\n", _("Press any key to continue..."));
-	    last_paused = 1;
-	    fflush (stdout);
-	    mc_raw_mode ();
-	    getch ();
-	}
-	if (console_flag) {
-	    if (output_lines && keybar_visible) {
-		putchar ('\n');
-		fflush (stdout);
-	    }
-	}
-    }
-
-    if (console_flag)
-	handle_console (CONSOLE_SAVE);
-    edition_post_exec ();
-
-#ifdef HAVE_SUBSHELL_SUPPORT
-    if (new_dir)
-	do_possible_cd (new_dir);
-
-#endif				/* HAVE_SUBSHELL_SUPPORT */
-
-#ifdef USE_VFS
-    if (old_vfs_dir) {
-	mc_chdir (old_vfs_dir);
-	g_free (old_vfs_dir);
-    }
-#endif				/* USE_VFS */
-
-    update_panels (UP_OPTIMIZE, UP_KEEPSEL);
-    update_xterm_title_path ();
-
-    do_refresh ();
-    use_dash (TRUE);
-}
-
-/* Executes a command */
-void
-shell_execute (const char *command, int flags)
-{
-#ifdef HAVE_SUBSHELL_SUPPORT
-    if (use_subshell)
-	if (subshell_state == INACTIVE)
-	    do_execute (shell, command, flags | EXECUTE_AS_SHELL);
-	else
-	    message (1, MSG_ERROR,
-		     _(" The shell is already running a command "));
-    else
-#endif				/* HAVE_SUBSHELL_SUPPORT */
-	do_execute (shell, command, flags | EXECUTE_AS_SHELL);
-}
-
 void
 change_panel (void)
 {
@@ -1365,45 +1247,6 @@ copy_other_tagged (void)
     copy_tagged (opanel);
 }
 
-static void
-do_suspend_cmd (void)
-{
-    pre_exec ();
-
-    if (console_flag && !use_subshell)
-	restore_console ();
-
-#ifdef SIGTSTP
-    {
-	struct sigaction sigtstp_action;
-
-	/* Make sure that the SIGTSTP below will suspend us directly,
-	   without calling ncurses' SIGTSTP handler; we *don't* want
-	   ncurses to redraw the screen immediately after the SIGCONT */
-	sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
-
-	kill (getpid (), SIGTSTP);
-
-	/* Restore previous SIGTSTP action */
-	sigaction (SIGTSTP, &sigtstp_action, NULL);
-    }
-#endif				/* SIGTSTP */
-
-    if (console_flag && !use_subshell)
-	handle_console (CONSOLE_SAVE);
-
-    edition_post_exec ();
-}
-
-void
-suspend_cmd (void)
-{
-    save_cwds_stat ();
-    do_suspend_cmd ();
-    update_panels (UP_OPTIMIZE, UP_KEEPSEL);
-    do_refresh ();
-}
-
 static void
 init_labels (void)
 {
diff --git a/src/main.h b/src/main.h
index edcdb7dad..b6748652f 100644
--- a/src/main.h
+++ b/src/main.h
@@ -20,15 +20,8 @@ enum {
 extern int quote;
 extern volatile int quit;
 
-/* Execute functions: the base and the routines that use it */
-void do_execute (const char *shell, const char *command, int internal_command);
-#define execute_internal(command,args) do_execute (command, args, 1)
-
-/* Execute functions that use the shell to execute */
-void shell_execute (const char *command, int flags);
-
-/* This one executes a shell */
-void exec_shell (void);
+/* If true, after executing a command, wait for a keystroke */
+enum { pause_never, pause_on_dumb_terminals, pause_always };
 
 void subshell_chdir (char *command);
 
@@ -104,7 +97,6 @@ void update_panels (int force_update, char *current_file);
 void create_panels (void);
 void repaint_screen (void);
 void outrefresh_screen (void);
-void suspend_cmd (void);
 void do_update_prompt (void);
 
 extern char *shell;
@@ -154,9 +146,6 @@ struct WMenu;
 extern struct WMenu *the_menubar;
 #endif /* WANT_WIDGETS */
 
-void edition_pre_exec (void);
-void edition_post_exec (void);
-
 void done_menu (void);
 void init_menu (void);
 
diff --git a/src/screen.c b/src/screen.c
index 153a4e348..a2352a727 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -43,6 +43,7 @@
 #include "setup.h"		/* For loading/saving panel options */
 #include "user.h"
 #include "profile.h"
+#include "execute.h"
 #include "widget.h"
 
 #ifdef NATIVE_WIN32
diff --git a/src/text.c b/src/text.c
index 957386d83..833727dce 100644
--- a/src/text.c
+++ b/src/text.c
@@ -64,51 +64,6 @@ char *default_edition_colors =
 "editbold=yellow,blue:"
 "editmarked=black,cyan";
 
-void
-edition_post_exec (void)
-{
-    do_enter_ca_mode ();
-
-    /* FIXME: Missing on slang endwin? */
-    reset_prog_mode ();
-    flushinp ();
-    
-    keypad (stdscr, TRUE);
-    mc_raw_mode ();
-    channels_up ();
-    enable_mouse ();
-    if (alternate_plus_minus)
-        application_keypad_mode ();
-}
-
-void
-edition_pre_exec (void)
-{
-    if (clear_before_exec)
-	clr_scr ();
-    else {
-	if (!(console_flag || xterm_flag))
-	    printf ("\n\n");
-    }
-
-    channels_down ();
-    disable_mouse ();
-    
-    reset_shell_mode ();
-    keypad (stdscr, FALSE);
-    endwin ();
-    
-    numeric_keypad_mode ();
-    
-    /* on xterms: maybe endwin did not leave the terminal on the shell
-     * screen page: do it now.
-     *
-     * Do not move this before endwin: in some systems rmcup includes
-     * a call to clear screen, so it will end up clearing the shell screen.
-     */
-    do_exit_ca_mode ();
-}
-
 void
 clr_scr (void)
 {
diff --git a/src/user.c b/src/user.c
index 4855d841e..61a53ba73 100644
--- a/src/user.c
+++ b/src/user.c
@@ -31,6 +31,7 @@
 #include "subshell.h" 		/* for subshell_pty */
 #include "user.h"
 #include "layout.h"
+#include "execute.h"
 #include "setup.h"
 
 #include "edit/edit.h"		/* BLOCK_FILE */
diff --git a/src/util.h b/src/util.h
index 6f40c6ea3..4309f758c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -78,8 +78,6 @@ void check_error_pipe (void);
 int close_error_pipe (int error, char *text);
 
 /* Process spawning */
-#define EXECUTE_INTERNAL   1
-#define EXECUTE_AS_SHELL   4
 int my_system (int flags, const char *shell, const char *command);
 void save_stop_handler (void);
 extern struct sigaction startup_handler;
diff --git a/src/utilunix.c b/src/utilunix.c
index 49bdcae32..fd5b5ea2f 100644
--- a/src/utilunix.c
+++ b/src/utilunix.c
@@ -38,6 +38,7 @@
 #include "global.h"
 #include "fsusage.h"
 #include "mountlist.h"
+#include "execute.h"
 #include "wtools.h"		/* message() */
 
 struct sigaction startup_handler;
diff --git a/src/view.c b/src/view.c
index 2b85d0883..d02ced873 100644
--- a/src/view.c
+++ b/src/view.c
@@ -53,6 +53,7 @@
 #include "dir.h"
 #include "panel.h"		/* Needed for current_panel and other_panel */
 #include "win.h"
+#include "execute.h"
 #include "main.h"		/* For the externs */
 #define WANT_WIDGETS
 #include "view.h"