2003-06-22 13:17:46 +04:00
|
|
|
/* Execution routines for GNU Midnight Commander
|
2007-09-25 19:33:35 +04:00
|
|
|
Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
|
2003-06-22 13:17:46 +04:00
|
|
|
|
|
|
|
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
|
2005-05-27 07:35:10 +04:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
2003-06-22 13:17:46 +04:00
|
|
|
|
2009-02-05 21:28:18 +03:00
|
|
|
/** \file execute.c
|
|
|
|
* \brief Source: execution routines
|
|
|
|
*/
|
|
|
|
|
2003-06-22 13:17:46 +04:00
|
|
|
#include <config.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
|
2009-08-12 15:37:22 +04:00
|
|
|
#include <signal.h>
|
2009-03-07 15:23:15 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/time.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
|
2003-06-22 13:17:46 +04:00
|
|
|
#include "global.h"
|
2009-05-09 19:17:57 +04:00
|
|
|
|
2009-05-08 14:01:05 +04:00
|
|
|
#include "../src/tty/tty.h"
|
|
|
|
#include "../src/tty/key.h"
|
2009-05-09 19:17:57 +04:00
|
|
|
#include "../src/tty/win.h"
|
|
|
|
|
2003-06-22 13:17:46 +04:00
|
|
|
#include "main.h"
|
|
|
|
#include "cons.saver.h"
|
|
|
|
#include "subshell.h"
|
|
|
|
#include "layout.h"
|
|
|
|
#include "dialog.h"
|
|
|
|
#include "wtools.h"
|
|
|
|
#include "execute.h"
|
2008-12-29 02:54:37 +03:00
|
|
|
#include "../vfs/vfs.h"
|
2003-06-22 13:17:46 +04:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
edition_post_exec (void)
|
|
|
|
{
|
|
|
|
do_enter_ca_mode ();
|
|
|
|
|
|
|
|
/* FIXME: Missing on slang endwin? */
|
|
|
|
reset_prog_mode ();
|
|
|
|
flushinp ();
|
|
|
|
|
|
|
|
keypad (stdscr, TRUE);
|
2009-05-19 20:12:29 +04:00
|
|
|
tty_raw_mode ();
|
2003-06-22 13:17:46 +04:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-22 14:15:04 +04:00
|
|
|
static void
|
2003-06-22 13:17:46 +04:00
|
|
|
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 ())
|
2009-02-06 01:40:32 +03:00
|
|
|
old_vfs_dir = g_strdup (vfs_get_current_dir ());
|
2003-06-22 13:17:46 +04:00
|
|
|
#endif /* USE_VFS */
|
|
|
|
|
|
|
|
save_cwds_stat ();
|
|
|
|
pre_exec ();
|
|
|
|
if (console_flag)
|
2003-06-22 13:32:52 +04:00
|
|
|
handle_console (CONSOLE_RESTORE);
|
2003-06-22 13:17:46 +04:00
|
|
|
|
2003-06-22 14:15:04 +04:00
|
|
|
if (!use_subshell && command && !(flags & EXECUTE_INTERNAL)) {
|
|
|
|
printf ("%s%s\n", prompt, command);
|
2005-09-17 16:08:19 +04:00
|
|
|
fflush (stdout);
|
2003-06-22 13:17:46 +04:00
|
|
|
}
|
|
|
|
#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
|
2009-07-15 22:53:13 +04:00
|
|
|
invoke_subshell (command, VISIBLY, old_vfs_dir ? NULL : &new_dir);
|
2003-06-22 13:17:46 +04:00
|
|
|
#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 */
|
|
|
|
) {
|
2003-06-22 14:15:04 +04:00
|
|
|
printf (_("Press any key to continue..."));
|
2003-06-22 13:17:46 +04:00
|
|
|
fflush (stdout);
|
2009-05-19 20:12:29 +04:00
|
|
|
tty_raw_mode ();
|
2003-11-21 08:31:59 +03:00
|
|
|
get_key_code (0);
|
2003-06-22 14:15:04 +04:00
|
|
|
printf ("\r\n");
|
|
|
|
fflush (stdout);
|
2003-06-22 13:17:46 +04:00
|
|
|
}
|
|
|
|
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);
|
2009-02-06 01:27:37 +03:00
|
|
|
g_free (old_vfs_dir);
|
2003-06-22 13:17:46 +04:00
|
|
|
}
|
|
|
|
#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)
|
|
|
|
{
|
2004-11-26 14:14:07 +03:00
|
|
|
char *cmd = NULL;
|
2004-11-18 20:47:55 +03:00
|
|
|
|
2004-11-26 14:14:07 +03:00
|
|
|
if (flags & EXECUTE_HIDE) {
|
2004-11-18 20:47:55 +03:00
|
|
|
cmd = g_strconcat (" ", command, (char *) NULL);
|
|
|
|
flags ^= EXECUTE_HIDE;
|
2004-11-26 14:14:07 +03:00
|
|
|
}
|
2004-11-18 20:47:55 +03:00
|
|
|
|
2003-06-22 13:17:46 +04:00
|
|
|
#ifdef HAVE_SUBSHELL_SUPPORT
|
|
|
|
if (use_subshell)
|
|
|
|
if (subshell_state == INACTIVE)
|
2004-11-26 14:14:07 +03:00
|
|
|
do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
|
2003-06-22 13:17:46 +04:00
|
|
|
else
|
2009-01-10 16:13:56 +03:00
|
|
|
message (D_ERROR, MSG_ERROR,
|
2003-06-22 13:17:46 +04:00
|
|
|
_(" The shell is already running a command "));
|
|
|
|
else
|
|
|
|
#endif /* HAVE_SUBSHELL_SUPPORT */
|
2004-11-26 14:14:07 +03:00
|
|
|
do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
|
2004-11-18 20:47:55 +03:00
|
|
|
|
2009-02-06 01:27:37 +03:00
|
|
|
g_free (cmd);
|
2003-06-22 13:17:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2009-05-19 20:12:29 +04:00
|
|
|
* is no tty_raw_mode supported
|
2003-06-22 13:17:46 +04:00
|
|
|
*/
|
|
|
|
reset_shell_mode ();
|
|
|
|
noecho ();
|
|
|
|
#endif /* !HAVE_SLANG */
|
|
|
|
keypad (stdscr, FALSE);
|
|
|
|
endwin ();
|
|
|
|
do_exit_ca_mode ();
|
2009-05-19 20:12:29 +04:00
|
|
|
tty_raw_mode ();
|
2003-06-22 13:17:46 +04:00
|
|
|
if (console_flag)
|
2003-06-22 13:32:52 +04:00
|
|
|
handle_console (CONSOLE_RESTORE);
|
2003-06-22 13:17:46 +04:00
|
|
|
|
|
|
|
#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");
|
|
|
|
|
2004-09-12 14:52:17 +04:00
|
|
|
my_system (EXECUTE_INTERNAL, shell, NULL);
|
2003-06-22 13:17:46 +04:00
|
|
|
} 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 */
|
|
|
|
|
2003-11-27 21:19:57 +03:00
|
|
|
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
2003-06-22 13:17:46 +04:00
|
|
|
update_xterm_title_path ();
|
2003-11-27 21:19:57 +03:00
|
|
|
do_refresh ();
|
2003-06-22 13:17:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_suspend_cmd (void)
|
|
|
|
{
|
|
|
|
pre_exec ();
|
|
|
|
|
|
|
|
if (console_flag && !use_subshell)
|
2003-06-22 13:32:52 +04:00
|
|
|
handle_console (CONSOLE_RESTORE);
|
2003-06-22 13:17:46 +04:00
|
|
|
|
|
|
|
#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)) {
|
2008-12-29 02:54:37 +03:00
|
|
|
fn = vfs_canon_and_translate (filename);
|
|
|
|
do_execute (command, fn, EXECUTE_INTERNAL);
|
|
|
|
g_free (fn);
|
2003-06-22 13:17:46 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Creation of new files on VFS is not supported */
|
|
|
|
if (!*filename)
|
|
|
|
return;
|
|
|
|
|
|
|
|
localcopy = mc_getlocalcopy (filename);
|
|
|
|
if (localcopy == NULL) {
|
2009-01-10 16:13:56 +03:00
|
|
|
message (D_ERROR, MSG_ERROR, _(" Cannot fetch a local copy of %s "),
|
2003-06-22 13:17:46 +04:00
|
|
|
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.
|
|
|
|
*/
|
2009-02-06 01:40:32 +03:00
|
|
|
fn = g_strdup (filename);
|
2003-06-22 13:17:46 +04:00
|
|
|
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);
|
2009-02-06 01:27:37 +03:00
|
|
|
g_free (localcopy);
|
|
|
|
g_free (fn);
|
2003-06-22 13:17:46 +04:00
|
|
|
}
|