c4f08ff870598b62fc3c2a2e5604c2756ea69aa4
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"
39 #include "lib/mcconfig.h"
41 #include "lib/widget.h"
43 #include "filemanager/midnight.h"
44 #include "filemanager/layout.h" /* use_dash() */
45 #include "consaver/cons.saver.h"
46 #ifdef ENABLE_SUBSHELL
49 #include "setup.h" /* clear_before_exec */
53 /*** global variables ****************************************************************************/
55 int pause_after_run
= pause_on_dumb_terminals
;
57 /*** file scope macro definitions ****************************************************************/
59 /*** file scope type declarations ****************************************************************/
61 /*** file scope variables ************************************************************************/
63 /*** file scope functions ************************************************************************/
64 /* --------------------------------------------------------------------------------------------- */
67 edition_post_exec (void)
71 /* FIXME: Missing on slang endwin? */
72 tty_reset_prog_mode ();
79 if (mc_global
.tty
.alternate_plus_minus
)
80 application_keypad_mode ();
83 /* --------------------------------------------------------------------------------------------- */
86 edition_pre_exec (void)
88 if (clear_before_exec
)
92 if (!(mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
))
99 tty_reset_shell_mode ();
103 numeric_keypad_mode ();
105 /* on xterms: maybe endwin did not leave the terminal on the shell
106 * screen page: do it now.
108 * Do not move this before endwin: in some systems rmcup includes
109 * a call to clear screen, so it will end up clearing the shell screen.
114 /* --------------------------------------------------------------------------------------------- */
116 #ifdef ENABLE_SUBSHELL
118 do_possible_cd (const vfs_path_t
* new_dir_vpath
)
120 if (!do_cd (new_dir_vpath
, cd_exact
))
121 message (D_ERROR
, _("Warning"),
122 _("The Commander can't change to the directory that\n"
123 "the subshell claims you are in. Perhaps you have\n"
124 "deleted your working directory, or given yourself\n"
125 "extra access permissions with the \"su\" command?"));
127 #endif /* ENABLE_SUBSHELL */
129 /* --------------------------------------------------------------------------------------------- */
132 do_execute (const char *lc_shell
, const char *command
, int flags
)
134 #ifdef ENABLE_SUBSHELL
135 vfs_path_t
*new_dir_vpath
= NULL
;
136 #endif /* ENABLE_SUBSHELL */
138 vfs_path_t
*old_vfs_dir_vpath
= NULL
;
140 if (!vfs_current_is_local ())
141 old_vfs_dir_vpath
= vfs_path_clone (vfs_get_raw_current_dir ());
143 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
146 if (mc_global
.tty
.console_flag
!= '\0')
147 handle_console (CONSOLE_RESTORE
);
149 if (!mc_global
.tty
.use_subshell
&& command
&& !(flags
& EXECUTE_INTERNAL
))
151 printf ("%s%s\n", mc_prompt
, command
);
154 #ifdef ENABLE_SUBSHELL
155 if (mc_global
.tty
.use_subshell
&& !(flags
& EXECUTE_INTERNAL
))
159 /* We don't care if it died, higher level takes care of this */
160 invoke_subshell (command
, VISIBLY
, old_vfs_dir_vpath
!= NULL
? NULL
: &new_dir_vpath
);
163 #endif /* ENABLE_SUBSHELL */
164 my_system (flags
, lc_shell
, command
);
166 if (!(flags
& EXECUTE_INTERNAL
))
168 if ((pause_after_run
== pause_always
169 || (pause_after_run
== pause_on_dumb_terminals
&& !mc_global
.tty
.xterm_flag
170 && mc_global
.tty
.console_flag
== '\0')) && quit
== 0
171 #ifdef ENABLE_SUBSHELL
172 && subshell_state
!= RUNNING_COMMAND
173 #endif /* ENABLE_SUBSHELL */
176 printf (_("Press any key to continue..."));
183 if (mc_global
.tty
.console_flag
!= '\0')
185 if (output_lines
&& mc_global
.keybar_visible
)
193 if (mc_global
.tty
.console_flag
!= '\0')
194 handle_console (CONSOLE_SAVE
);
195 edition_post_exec ();
197 #ifdef ENABLE_SUBSHELL
198 if (new_dir_vpath
!= NULL
)
200 do_possible_cd (new_dir_vpath
);
201 vfs_path_free (new_dir_vpath
);
204 #endif /* ENABLE_SUBSHELL */
206 if (old_vfs_dir_vpath
!= NULL
)
208 mc_chdir (old_vfs_dir_vpath
);
209 vfs_path_free (old_vfs_dir_vpath
);
212 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
214 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
215 update_xterm_title_path ();
222 /* --------------------------------------------------------------------------------------------- */
225 do_suspend_cmd (void)
229 if (mc_global
.tty
.console_flag
!= '\0' && !mc_global
.tty
.use_subshell
)
230 handle_console (CONSOLE_RESTORE
);
234 struct sigaction sigtstp_action
;
236 /* Make sure that the SIGTSTP below will suspend us directly,
237 without calling ncurses' SIGTSTP handler; we *don't* want
238 ncurses to redraw the screen immediately after the SIGCONT */
239 sigaction (SIGTSTP
, &startup_handler
, &sigtstp_action
);
241 kill (getpid (), SIGTSTP
);
243 /* Restore previous SIGTSTP action */
244 sigaction (SIGTSTP
, &sigtstp_action
, NULL
);
248 if (mc_global
.tty
.console_flag
!= '\0' && !mc_global
.tty
.use_subshell
)
249 handle_console (CONSOLE_SAVE
);
251 edition_post_exec ();
254 /* --------------------------------------------------------------------------------------------- */
255 /*** public functions ****************************************************************************/
256 /* --------------------------------------------------------------------------------------------- */
258 /** Set up the terminal before executing a program */
267 /* --------------------------------------------------------------------------------------------- */
268 /** Hide the terminal after executing a program */
272 edition_post_exec ();
277 /* --------------------------------------------------------------------------------------------- */
278 /* Executes a command */
281 shell_execute (const char *command
, int flags
)
285 if (flags
& EXECUTE_HIDE
)
287 cmd
= g_strconcat (" ", command
, (char *) NULL
);
288 flags
^= EXECUTE_HIDE
;
291 #ifdef ENABLE_SUBSHELL
292 if (mc_global
.tty
.use_subshell
)
293 if (subshell_state
== INACTIVE
)
294 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
296 message (D_ERROR
, MSG_ERROR
, _("The shell is already running a command"));
298 #endif /* ENABLE_SUBSHELL */
299 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
304 /* --------------------------------------------------------------------------------------------- */
309 do_execute (shell
, 0, 0);
312 /* --------------------------------------------------------------------------------------------- */
317 #ifdef ENABLE_SUBSHELL
318 vfs_path_t
*new_dir_vpath
= NULL
;
319 vfs_path_t
**new_dir_p
;
320 #endif /* ENABLE_SUBSHELL */
324 if (clear_before_exec
)
326 if (mc_global
.tty
.alternate_plus_minus
)
327 numeric_keypad_mode ();
329 /* With slang we don't want any of this, since there
330 * is no raw_mode supported
332 tty_reset_shell_mode ();
333 #endif /* !HAVE_SLANG */
339 if (mc_global
.tty
.console_flag
!= '\0')
340 handle_console (CONSOLE_RESTORE
);
342 #ifdef ENABLE_SUBSHELL
343 if (mc_global
.tty
.use_subshell
)
345 new_dir_p
= vfs_current_is_local ()? &new_dir_vpath
: NULL
;
346 invoke_subshell (NULL
, VISIBLY
, new_dir_p
);
349 #endif /* ENABLE_SUBSHELL */
351 if (output_starts_shell
)
353 fprintf (stderr
, _("Type `exit' to return to the Midnight Commander"));
354 fprintf (stderr
, "\n\r\n\r");
356 my_system (EXECUTE_INTERNAL
, shell
, NULL
);
362 if (mc_global
.tty
.console_flag
!= '\0')
363 handle_console (CONSOLE_SAVE
);
367 tty_reset_prog_mode ();
370 /* Prevent screen flash when user did 'exit' or 'logout' within
372 if ((quit
& SUBSHELL_EXIT
) != 0)
374 /* User did `exit' or `logout': quit MC */
375 if (quiet_quit_cmd ())
379 #ifdef ENABLE_SUBSHELL
380 /* restart subshell */
381 if (mc_global
.tty
.use_subshell
)
383 #endif /* ENABLE_SUBSHELL */
388 if (mc_global
.tty
.alternate_plus_minus
)
389 application_keypad_mode ();
391 #ifdef ENABLE_SUBSHELL
392 if (mc_global
.tty
.use_subshell
)
395 if (new_dir_vpath
!= NULL
)
396 do_possible_cd (new_dir_vpath
);
397 if (mc_global
.tty
.console_flag
!= '\0' && output_lines
)
398 show_console_contents (output_start_y
,
399 LINES
- mc_global
.keybar_visible
- output_lines
-
400 1, LINES
- mc_global
.keybar_visible
- 1);
403 vfs_path_free (new_dir_vpath
);
404 #endif /* ENABLE_SUBSHELL */
406 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
408 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
409 update_xterm_title_path ();
414 /* --------------------------------------------------------------------------------------------- */
418 execute_suspend (const gchar
* event_group_name
, const gchar
* event_name
,
419 gpointer init_data
, gpointer data
)
421 (void) event_group_name
;
426 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
429 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
430 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
436 /* --------------------------------------------------------------------------------------------- */
438 * Execute command on a filename that can be on VFS.
439 * Errors are reported to the user.
443 execute_with_vfs_arg (const char *command
, const vfs_path_t
* filename_vpath
)
447 vfs_path_t
*localcopy_vpath
;
449 /* Simplest case, this file is local */
450 if (filename_vpath
== NULL
|| vfs_file_is_local (filename_vpath
))
452 do_execute (command
, vfs_path_get_last_path_str (filename_vpath
), EXECUTE_INTERNAL
);
456 /* FIXME: Creation of new files on VFS is not supported */
457 if (vfs_path_len (filename_vpath
) == 0)
460 localcopy_vpath
= mc_getlocalcopy (filename_vpath
);
461 if (localcopy_vpath
== NULL
)
465 filename
= vfs_path_to_str (filename_vpath
);
466 message (D_ERROR
, MSG_ERROR
, _("Cannot fetch a local copy of %s"), filename
);
472 * filename can be an entry on panel, it can be changed by executing
473 * the command, so make a copy. Smarter VFS code would make the code
476 mc_stat (localcopy_vpath
, &st
);
478 do_execute (command
, vfs_path_get_last_path_str (localcopy_vpath
), EXECUTE_INTERNAL
);
479 mc_stat (localcopy_vpath
, &st
);
480 mc_ungetlocalcopy (filename_vpath
, localcopy_vpath
, mtime
!= st
.st_mtime
);
481 vfs_path_free (localcopy_vpath
);
484 /* --------------------------------------------------------------------------------------------- */