2 Execution routines for GNU Midnight Commander
4 Copyright (C) 2003, 2004, 2005, 2007, 2011
5 The Free Software Foundation, Inc.
7 This file is part of the Midnight Commander.
9 The Midnight Commander is free software: you can redistribute it
10 and/or modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation, either version 3 of the License,
12 or (at your option) any later version.
14 The Midnight Commander is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * \brief Source: execution routines
33 #include "lib/global.h"
35 #include "lib/tty/tty.h"
36 #include "lib/tty/key.h"
37 #include "lib/tty/win.h"
38 #include "lib/vfs/vfs.h"
40 #include "lib/widget.h"
42 #include "filemanager/midnight.h"
43 #include "filemanager/layout.h" /* use_dash() */
44 #include "consaver/cons.saver.h"
46 #include "setup.h" /* clear_before_exec */
50 /*** global variables ****************************************************************************/
52 int pause_after_run
= pause_on_dumb_terminals
;
54 /*** file scope macro definitions ****************************************************************/
56 /*** file scope type declarations ****************************************************************/
58 /*** file scope variables ************************************************************************/
60 /*** file scope functions ************************************************************************/
61 /* --------------------------------------------------------------------------------------------- */
64 edition_post_exec (void)
68 /* FIXME: Missing on slang endwin? */
69 tty_reset_prog_mode ();
76 if (mc_global
.tty
.alternate_plus_minus
)
77 application_keypad_mode ();
80 /* --------------------------------------------------------------------------------------------- */
83 edition_pre_exec (void)
85 if (clear_before_exec
)
89 if (!(mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
))
96 tty_reset_shell_mode ();
100 numeric_keypad_mode ();
102 /* on xterms: maybe endwin did not leave the terminal on the shell
103 * screen page: do it now.
105 * Do not move this before endwin: in some systems rmcup includes
106 * a call to clear screen, so it will end up clearing the shell screen.
111 /* --------------------------------------------------------------------------------------------- */
113 #ifdef HAVE_SUBSHELL_SUPPORT
115 do_possible_cd (const char *new_dir
)
117 if (!do_cd (new_dir
, cd_exact
))
118 message (D_ERROR
, _("Warning"),
119 _("The Commander can't change to the directory that\n"
120 "the subshell claims you are in. Perhaps you have\n"
121 "deleted your working directory, or given yourself\n"
122 "extra access permissions with the \"su\" command?"));
124 #endif /* HAVE_SUBSHELL_SUPPORT */
126 /* --------------------------------------------------------------------------------------------- */
129 do_execute (const char *lc_shell
, const char *command
, int flags
)
131 #ifdef HAVE_SUBSHELL_SUPPORT
132 char *new_dir
= NULL
;
133 #endif /* HAVE_SUBSHELL_SUPPORT */
135 char *old_vfs_dir
= 0;
137 if (!vfs_current_is_local ())
138 old_vfs_dir
= vfs_get_current_dir ();
140 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
143 if (mc_global
.tty
.console_flag
!= '\0')
144 handle_console (CONSOLE_RESTORE
);
146 if (!mc_global
.tty
.use_subshell
&& command
&& !(flags
& EXECUTE_INTERNAL
))
148 printf ("%s%s\n", mc_prompt
, command
);
151 #ifdef HAVE_SUBSHELL_SUPPORT
152 if (mc_global
.tty
.use_subshell
&& !(flags
& EXECUTE_INTERNAL
))
156 /* We don't care if it died, higher level takes care of this */
157 invoke_subshell (command
, VISIBLY
, old_vfs_dir
? NULL
: &new_dir
);
160 #endif /* HAVE_SUBSHELL_SUPPORT */
161 my_system (flags
, lc_shell
, command
);
163 if (!(flags
& EXECUTE_INTERNAL
))
165 if ((pause_after_run
== pause_always
166 || (pause_after_run
== pause_on_dumb_terminals
&& !mc_global
.tty
.xterm_flag
167 && mc_global
.tty
.console_flag
== '\0')) && quit
== 0
168 #ifdef HAVE_SUBSHELL_SUPPORT
169 && subshell_state
!= RUNNING_COMMAND
170 #endif /* HAVE_SUBSHELL_SUPPORT */
173 printf (_("Press any key to continue..."));
180 if (mc_global
.tty
.console_flag
!= '\0')
182 if (output_lines
&& mc_global
.keybar_visible
)
190 if (mc_global
.tty
.console_flag
!= '\0')
191 handle_console (CONSOLE_SAVE
);
192 edition_post_exec ();
194 #ifdef HAVE_SUBSHELL_SUPPORT
196 do_possible_cd (new_dir
);
198 #endif /* HAVE_SUBSHELL_SUPPORT */
200 if (old_vfs_dir
!= NULL
)
204 vpath
= vfs_path_from_str (old_vfs_dir
);
206 vfs_path_free (vpath
);
207 g_free (old_vfs_dir
);
210 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
212 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
213 update_xterm_title_path ();
220 /* --------------------------------------------------------------------------------------------- */
223 do_suspend_cmd (void)
227 if (mc_global
.tty
.console_flag
!= '\0' && !mc_global
.tty
.use_subshell
)
228 handle_console (CONSOLE_RESTORE
);
232 struct sigaction sigtstp_action
;
234 /* Make sure that the SIGTSTP below will suspend us directly,
235 without calling ncurses' SIGTSTP handler; we *don't* want
236 ncurses to redraw the screen immediately after the SIGCONT */
237 sigaction (SIGTSTP
, &startup_handler
, &sigtstp_action
);
239 kill (getpid (), SIGTSTP
);
241 /* Restore previous SIGTSTP action */
242 sigaction (SIGTSTP
, &sigtstp_action
, NULL
);
246 if (mc_global
.tty
.console_flag
!= '\0' && !mc_global
.tty
.use_subshell
)
247 handle_console (CONSOLE_SAVE
);
249 edition_post_exec ();
252 /* --------------------------------------------------------------------------------------------- */
253 /*** public functions ****************************************************************************/
254 /* --------------------------------------------------------------------------------------------- */
256 /** Set up the terminal before executing a program */
265 /* --------------------------------------------------------------------------------------------- */
266 /** Hide the terminal after executing a program */
270 edition_post_exec ();
275 /* --------------------------------------------------------------------------------------------- */
276 /* Executes a command */
279 shell_execute (const char *command
, int flags
)
283 if (flags
& EXECUTE_HIDE
)
285 cmd
= g_strconcat (" ", command
, (char *) NULL
);
286 flags
^= EXECUTE_HIDE
;
289 #ifdef HAVE_SUBSHELL_SUPPORT
290 if (mc_global
.tty
.use_subshell
)
291 if (subshell_state
== INACTIVE
)
292 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
294 message (D_ERROR
, MSG_ERROR
, _("The shell is already running a command"));
296 #endif /* HAVE_SUBSHELL_SUPPORT */
297 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
302 /* --------------------------------------------------------------------------------------------- */
307 do_execute (shell
, 0, 0);
310 /* --------------------------------------------------------------------------------------------- */
315 #ifdef HAVE_SUBSHELL_SUPPORT
316 char *new_dir
= NULL
;
318 #endif /* HAVE_SUBSHELL_SUPPORT */
322 if (clear_before_exec
)
324 if (mc_global
.tty
.alternate_plus_minus
)
325 numeric_keypad_mode ();
327 /* With slang we don't want any of this, since there
328 * is no raw_mode supported
330 tty_reset_shell_mode ();
331 #endif /* !HAVE_SLANG */
337 if (mc_global
.tty
.console_flag
!= '\0')
338 handle_console (CONSOLE_RESTORE
);
340 #ifdef HAVE_SUBSHELL_SUPPORT
341 if (mc_global
.tty
.use_subshell
)
343 new_dir_p
= vfs_current_is_local ()? &new_dir
: NULL
;
344 invoke_subshell (NULL
, VISIBLY
, new_dir_p
);
347 #endif /* HAVE_SUBSHELL_SUPPORT */
349 if (output_starts_shell
)
351 fprintf (stderr
, _("Type `exit' to return to the Midnight Commander"));
352 fprintf (stderr
, "\n\r\n\r");
354 my_system (EXECUTE_INTERNAL
, shell
, NULL
);
360 if (mc_global
.tty
.console_flag
!= '\0')
361 handle_console (CONSOLE_SAVE
);
365 tty_reset_prog_mode ();
368 /* Prevent screen flash when user did 'exit' or 'logout' within
370 if ((quit
& SUBSHELL_EXIT
) != 0)
372 /* User did `exit' or `logout': quit MC */
373 if (quiet_quit_cmd ())
377 #ifdef HAVE_SUBSHELL_SUPPORT
378 /* restart subshell */
379 if (mc_global
.tty
.use_subshell
)
381 #endif /* HAVE_SUBSHELL_SUPPORT */
386 if (mc_global
.tty
.alternate_plus_minus
)
387 application_keypad_mode ();
389 #ifdef HAVE_SUBSHELL_SUPPORT
390 if (mc_global
.tty
.use_subshell
)
394 do_possible_cd (new_dir
);
395 if (mc_global
.tty
.console_flag
!= '\0' && output_lines
)
396 show_console_contents (output_start_y
,
397 LINES
- mc_global
.keybar_visible
- output_lines
-
398 1, LINES
- mc_global
.keybar_visible
- 1);
400 #endif /* HAVE_SUBSHELL_SUPPORT */
402 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
404 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
405 update_xterm_title_path ();
410 /* --------------------------------------------------------------------------------------------- */
414 execute_suspend (const gchar
* event_group_name
, const gchar
* event_name
,
415 gpointer init_data
, gpointer data
)
417 (void) event_group_name
;
422 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
425 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
426 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
432 /* --------------------------------------------------------------------------------------------- */
434 * Execute command on a filename that can be on VFS.
435 * Errors are reported to the user.
439 execute_with_vfs_arg (const char *command
, const char *filename
)
443 vfs_path_t
*vpath
= vfs_path_from_str (filename
);
444 vfs_path_t
*localcopy_vpath
;
446 /* Simplest case, this file is local */
447 if (!filename
|| vfs_file_is_local (vpath
))
449 do_execute (command
, vfs_path_get_last_path_str (vpath
), EXECUTE_INTERNAL
);
450 vfs_path_free (vpath
);
454 /* FIXME: Creation of new files on VFS is not supported */
457 vfs_path_free (vpath
);
461 localcopy_vpath
= mc_getlocalcopy (vpath
);
462 if (localcopy_vpath
== NULL
)
464 message (D_ERROR
, MSG_ERROR
, _("Cannot fetch a local copy of %s"), filename
);
465 vfs_path_free (vpath
);
470 * filename can be an entry on panel, it can be changed by executing
471 * the command, so make a copy. Smarter VFS code would make the code
474 mc_stat (localcopy_vpath
, &st
);
476 do_execute (command
, vfs_path_get_last_path_str (localcopy_vpath
), EXECUTE_INTERNAL
);
477 mc_stat (localcopy_vpath
, &st
);
478 mc_ungetlocalcopy (vpath
, localcopy_vpath
, mtime
!= st
.st_mtime
);
479 vfs_path_free (localcopy_vpath
);
480 vfs_path_free (vpath
);
483 /* --------------------------------------------------------------------------------------------- */