1 /* Execution routines for GNU Midnight Commander
2 Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 * \brief Source: execution routines
28 #include "lib/global.h"
30 #include "lib/tty/tty.h"
31 #include "lib/tty/key.h"
32 #include "lib/tty/win.h"
35 #include "consaver/cons.saver.h"
40 #include "panel.h" /* update_panels() */
42 #include "lib/vfs/mc-vfs/vfs.h"
46 edition_post_exec (void)
50 /* FIXME: Missing on slang endwin? */
51 tty_reset_prog_mode ();
58 if (alternate_plus_minus
)
59 application_keypad_mode ();
64 edition_pre_exec (void)
66 if (clear_before_exec
)
70 if (!(console_flag
|| xterm_flag
))
77 tty_reset_shell_mode ();
81 numeric_keypad_mode ();
83 /* on xterms: maybe endwin did not leave the terminal on the shell
84 * screen page: do it now.
86 * Do not move this before endwin: in some systems rmcup includes
87 * a call to clear screen, so it will end up clearing the shell screen.
93 /* Set up the terminal before executing a program */
102 #ifdef HAVE_SUBSHELL_SUPPORT
104 do_possible_cd (const char *new_dir
)
106 if (!do_cd (new_dir
, cd_exact
))
107 message (D_ERROR
, _("Warning"),
108 _("The Commander can't change to the directory that\n"
109 "the subshell claims you are in. Perhaps you have\n"
110 "deleted your working directory, or given yourself\n"
111 "extra access permissions with the \"su\" command?"));
113 #endif /* HAVE_SUBSHELL_SUPPORT */
116 do_execute (const char *lc_shell
, const char *command
, int flags
)
118 #ifdef HAVE_SUBSHELL_SUPPORT
119 char *new_dir
= NULL
;
120 #endif /* HAVE_SUBSHELL_SUPPORT */
123 char *old_vfs_dir
= 0;
125 if (!vfs_current_is_local ())
126 old_vfs_dir
= g_strdup (vfs_get_current_dir ());
127 #endif /* ENABLE_VFS */
129 if (mc_run_mode
== MC_RUN_FULL
)
133 handle_console (CONSOLE_RESTORE
);
135 if (!use_subshell
&& command
&& !(flags
& EXECUTE_INTERNAL
))
137 printf ("%s%s\n", mc_prompt
, command
);
140 #ifdef HAVE_SUBSHELL_SUPPORT
141 if (use_subshell
&& !(flags
& EXECUTE_INTERNAL
))
145 /* We don't care if it died, higher level takes care of this */
147 invoke_subshell (command
, VISIBLY
, old_vfs_dir
? NULL
: &new_dir
);
149 invoke_subshell (command
, VISIBLY
, &new_dir
);
150 #endif /* !ENABLE_VFS */
153 #endif /* HAVE_SUBSHELL_SUPPORT */
154 my_system (flags
, lc_shell
, command
);
156 if (!(flags
& EXECUTE_INTERNAL
))
158 if ((pause_after_run
== pause_always
159 || (pause_after_run
== pause_on_dumb_terminals
&& !xterm_flag
160 && !console_flag
)) && !quit
161 #ifdef HAVE_SUBSHELL_SUPPORT
162 && subshell_state
!= RUNNING_COMMAND
163 #endif /* HAVE_SUBSHELL_SUPPORT */
166 printf (_("Press any key to continue..."));
175 if (output_lines
&& keybar_visible
)
184 handle_console (CONSOLE_SAVE
);
185 edition_post_exec ();
187 #ifdef HAVE_SUBSHELL_SUPPORT
189 do_possible_cd (new_dir
);
191 #endif /* HAVE_SUBSHELL_SUPPORT */
196 mc_chdir (old_vfs_dir
);
197 g_free (old_vfs_dir
);
199 #endif /* ENABLE_VFS */
201 if (mc_run_mode
== MC_RUN_FULL
)
203 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
204 update_xterm_title_path ();
212 /* Executes a command */
214 shell_execute (const char *command
, int flags
)
218 if (flags
& EXECUTE_HIDE
)
220 cmd
= g_strconcat (" ", command
, (char *) NULL
);
221 flags
^= EXECUTE_HIDE
;
224 #ifdef HAVE_SUBSHELL_SUPPORT
226 if (subshell_state
== INACTIVE
)
227 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
229 message (D_ERROR
, MSG_ERROR
, _("The shell is already running a command"));
231 #endif /* HAVE_SUBSHELL_SUPPORT */
232 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
241 do_execute (shell
, 0, 0);
248 #ifdef HAVE_SUBSHELL_SUPPORT
249 char *new_dir
= NULL
;
251 #endif /* HAVE_SUBSHELL_SUPPORT */
255 if (clear_before_exec
)
257 if (alternate_plus_minus
)
258 numeric_keypad_mode ();
260 /* With slang we don't want any of this, since there
261 * is no raw_mode supported
263 tty_reset_shell_mode ();
264 #endif /* !HAVE_SLANG */
271 handle_console (CONSOLE_RESTORE
);
273 #ifdef HAVE_SUBSHELL_SUPPORT
276 new_dir_p
= vfs_current_is_local () ? &new_dir
: NULL
;
277 invoke_subshell (NULL
, VISIBLY
, new_dir_p
);
280 #endif /* HAVE_SUBSHELL_SUPPORT */
282 if (output_starts_shell
)
284 fprintf (stderr
, _("Type `exit' to return to the Midnight Commander"));
285 fprintf (stderr
, "\n\r\n\r");
287 my_system (EXECUTE_INTERNAL
, shell
, NULL
);
294 handle_console (CONSOLE_SAVE
);
298 tty_reset_prog_mode ();
301 /* Prevent screen flash when user did 'exit' or 'logout' within
303 if ((quit
& SUBSHELL_EXIT
) != 0)
305 /* User did `exit' or `logout': quit MC */
306 if (quiet_quit_cmd ())
310 #ifdef HAVE_SUBSHELL_SUPPORT
311 /* restart subshell */
314 #endif /* HAVE_SUBSHELL_SUPPORT */
319 if (alternate_plus_minus
)
320 application_keypad_mode ();
322 #ifdef HAVE_SUBSHELL_SUPPORT
327 do_possible_cd (new_dir
);
328 if (console_flag
&& output_lines
)
329 show_console_contents (output_start_y
,
330 LINES
- keybar_visible
- output_lines
-
331 1, LINES
- keybar_visible
- 1);
333 #endif /* HAVE_SUBSHELL_SUPPORT */
335 if (mc_run_mode
== MC_RUN_FULL
)
337 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
338 update_xterm_title_path ();
345 do_suspend_cmd (void)
349 if (console_flag
&& !use_subshell
)
350 handle_console (CONSOLE_RESTORE
);
354 struct sigaction sigtstp_action
;
356 /* Make sure that the SIGTSTP below will suspend us directly,
357 without calling ncurses' SIGTSTP handler; we *don't* want
358 ncurses to redraw the screen immediately after the SIGCONT */
359 sigaction (SIGTSTP
, &startup_handler
, &sigtstp_action
);
361 kill (getpid (), SIGTSTP
);
363 /* Restore previous SIGTSTP action */
364 sigaction (SIGTSTP
, &sigtstp_action
, NULL
);
368 if (console_flag
&& !use_subshell
)
369 handle_console (CONSOLE_SAVE
);
371 edition_post_exec ();
378 if (mc_run_mode
== MC_RUN_FULL
)
381 if (mc_run_mode
== MC_RUN_FULL
)
382 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
388 * Execute command on a filename that can be on VFS.
389 * Errors are reported to the user.
392 execute_with_vfs_arg (const char *command
, const char *filename
)
399 /* Simplest case, this file is local */
400 if (!filename
|| vfs_file_is_local (filename
))
402 fn
= vfs_canon_and_translate (filename
);
403 do_execute (command
, fn
, EXECUTE_INTERNAL
);
408 /* FIXME: Creation of new files on VFS is not supported */
412 localcopy
= mc_getlocalcopy (filename
);
413 if (localcopy
== NULL
)
415 message (D_ERROR
, MSG_ERROR
, _("Cannot fetch a local copy of %s"), filename
);
420 * filename can be an entry on panel, it can be changed by executing
421 * the command, so make a copy. Smarter VFS code would make the code
424 fn
= g_strdup (filename
);
425 mc_stat (localcopy
, &st
);
427 do_execute (command
, localcopy
, EXECUTE_INTERNAL
);
428 mc_stat (localcopy
, &st
);
429 mc_ungetlocalcopy (fn
, localcopy
, mtime
!= st
.st_mtime
);