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"
33 #include "lib/vfs/mc-vfs/vfs.h"
35 #include "lib/widget.h"
37 #include "filemanager/midnight.h"
38 #include "filemanager/layout.h" /* use_dash() */
39 #include "consaver/cons.saver.h"
41 #include "setup.h" /* clear_before_exec */
45 /*** global variables ****************************************************************************/
47 int pause_after_run
= pause_on_dumb_terminals
;
49 /*** file scope macro definitions ****************************************************************/
51 /*** file scope type declarations ****************************************************************/
53 /*** file scope variables ************************************************************************/
55 /*** file scope functions ************************************************************************/
56 /* --------------------------------------------------------------------------------------------- */
59 edition_post_exec (void)
63 /* FIXME: Missing on slang endwin? */
64 tty_reset_prog_mode ();
71 if (alternate_plus_minus
)
72 application_keypad_mode ();
75 /* --------------------------------------------------------------------------------------------- */
78 edition_pre_exec (void)
80 if (clear_before_exec
)
84 if (!(console_flag
|| xterm_flag
))
91 tty_reset_shell_mode ();
95 numeric_keypad_mode ();
97 /* on xterms: maybe endwin did not leave the terminal on the shell
98 * screen page: do it now.
100 * Do not move this before endwin: in some systems rmcup includes
101 * a call to clear screen, so it will end up clearing the shell screen.
106 /* --------------------------------------------------------------------------------------------- */
108 #ifdef HAVE_SUBSHELL_SUPPORT
110 do_possible_cd (const char *new_dir
)
112 if (!do_cd (new_dir
, cd_exact
))
113 message (D_ERROR
, _("Warning"),
114 _("The Commander can't change to the directory that\n"
115 "the subshell claims you are in. Perhaps you have\n"
116 "deleted your working directory, or given yourself\n"
117 "extra access permissions with the \"su\" command?"));
119 #endif /* HAVE_SUBSHELL_SUPPORT */
121 /* --------------------------------------------------------------------------------------------- */
124 do_execute (const char *lc_shell
, const char *command
, int flags
)
126 #ifdef HAVE_SUBSHELL_SUPPORT
127 char *new_dir
= NULL
;
128 #endif /* HAVE_SUBSHELL_SUPPORT */
130 char *old_vfs_dir
= 0;
132 if (!vfs_current_is_local ())
133 old_vfs_dir
= g_strdup (vfs_get_current_dir ());
135 if (mc_run_mode
== MC_RUN_FULL
)
139 handle_console (CONSOLE_RESTORE
);
141 if (!use_subshell
&& command
&& !(flags
& EXECUTE_INTERNAL
))
143 printf ("%s%s\n", mc_prompt
, command
);
146 #ifdef HAVE_SUBSHELL_SUPPORT
147 if (use_subshell
&& !(flags
& EXECUTE_INTERNAL
))
151 /* We don't care if it died, higher level takes care of this */
152 invoke_subshell (command
, VISIBLY
, old_vfs_dir
? NULL
: &new_dir
);
155 #endif /* HAVE_SUBSHELL_SUPPORT */
156 my_system (flags
, lc_shell
, command
);
158 if (!(flags
& EXECUTE_INTERNAL
))
160 if ((pause_after_run
== pause_always
161 || (pause_after_run
== pause_on_dumb_terminals
&& !xterm_flag
162 && !console_flag
)) && quit
== 0
163 #ifdef HAVE_SUBSHELL_SUPPORT
164 && subshell_state
!= RUNNING_COMMAND
165 #endif /* HAVE_SUBSHELL_SUPPORT */
168 printf (_("Press any key to continue..."));
177 if (output_lines
&& keybar_visible
)
186 handle_console (CONSOLE_SAVE
);
187 edition_post_exec ();
189 #ifdef HAVE_SUBSHELL_SUPPORT
191 do_possible_cd (new_dir
);
193 #endif /* HAVE_SUBSHELL_SUPPORT */
197 mc_chdir (old_vfs_dir
);
198 g_free (old_vfs_dir
);
201 if (mc_run_mode
== MC_RUN_FULL
)
203 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
204 update_xterm_title_path ();
211 /* --------------------------------------------------------------------------------------------- */
214 do_suspend_cmd (void)
218 if (console_flag
&& !use_subshell
)
219 handle_console (CONSOLE_RESTORE
);
223 struct sigaction sigtstp_action
;
225 /* Make sure that the SIGTSTP below will suspend us directly,
226 without calling ncurses' SIGTSTP handler; we *don't* want
227 ncurses to redraw the screen immediately after the SIGCONT */
228 sigaction (SIGTSTP
, &startup_handler
, &sigtstp_action
);
230 kill (getpid (), SIGTSTP
);
232 /* Restore previous SIGTSTP action */
233 sigaction (SIGTSTP
, &sigtstp_action
, NULL
);
237 if (console_flag
&& !use_subshell
)
238 handle_console (CONSOLE_SAVE
);
240 edition_post_exec ();
243 /* --------------------------------------------------------------------------------------------- */
244 /*** public functions ****************************************************************************/
245 /* --------------------------------------------------------------------------------------------- */
247 /** Set up the terminal before executing a program */
256 /* --------------------------------------------------------------------------------------------- */
257 /** Hide the terminal after executing a program */
261 edition_post_exec ();
265 /* --------------------------------------------------------------------------------------------- */
266 /* Executes a command */
269 shell_execute (const char *command
, int flags
)
273 if (flags
& EXECUTE_HIDE
)
275 cmd
= g_strconcat (" ", command
, (char *) NULL
);
276 flags
^= EXECUTE_HIDE
;
279 #ifdef HAVE_SUBSHELL_SUPPORT
281 if (subshell_state
== INACTIVE
)
282 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
284 message (D_ERROR
, MSG_ERROR
, _("The shell is already running a command"));
286 #endif /* HAVE_SUBSHELL_SUPPORT */
287 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
292 /* --------------------------------------------------------------------------------------------- */
297 do_execute (shell
, 0, 0);
300 /* --------------------------------------------------------------------------------------------- */
305 #ifdef HAVE_SUBSHELL_SUPPORT
306 char *new_dir
= NULL
;
308 #endif /* HAVE_SUBSHELL_SUPPORT */
312 if (clear_before_exec
)
314 if (alternate_plus_minus
)
315 numeric_keypad_mode ();
317 /* With slang we don't want any of this, since there
318 * is no raw_mode supported
320 tty_reset_shell_mode ();
321 #endif /* !HAVE_SLANG */
328 handle_console (CONSOLE_RESTORE
);
330 #ifdef HAVE_SUBSHELL_SUPPORT
333 new_dir_p
= vfs_current_is_local ()? &new_dir
: NULL
;
334 invoke_subshell (NULL
, VISIBLY
, new_dir_p
);
337 #endif /* HAVE_SUBSHELL_SUPPORT */
339 if (output_starts_shell
)
341 fprintf (stderr
, _("Type `exit' to return to the Midnight Commander"));
342 fprintf (stderr
, "\n\r\n\r");
344 my_system (EXECUTE_INTERNAL
, shell
, NULL
);
351 handle_console (CONSOLE_SAVE
);
355 tty_reset_prog_mode ();
358 /* Prevent screen flash when user did 'exit' or 'logout' within
360 if ((quit
& SUBSHELL_EXIT
) != 0)
362 /* User did `exit' or `logout': quit MC */
363 if (quiet_quit_cmd ())
367 #ifdef HAVE_SUBSHELL_SUPPORT
368 /* restart subshell */
371 #endif /* HAVE_SUBSHELL_SUPPORT */
376 if (alternate_plus_minus
)
377 application_keypad_mode ();
379 #ifdef HAVE_SUBSHELL_SUPPORT
382 load_prompt (0, NULL
);
384 do_possible_cd (new_dir
);
385 if (console_flag
&& output_lines
)
386 show_console_contents (output_start_y
,
387 LINES
- keybar_visible
- output_lines
-
388 1, LINES
- keybar_visible
- 1);
390 #endif /* HAVE_SUBSHELL_SUPPORT */
392 if (mc_run_mode
== MC_RUN_FULL
)
394 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
395 update_xterm_title_path ();
400 /* --------------------------------------------------------------------------------------------- */
405 if (mc_run_mode
== MC_RUN_FULL
)
408 if (mc_run_mode
== MC_RUN_FULL
)
409 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
413 /* --------------------------------------------------------------------------------------------- */
415 * Execute command on a filename that can be on VFS.
416 * Errors are reported to the user.
420 execute_with_vfs_arg (const char *command
, const char *filename
)
427 /* Simplest case, this file is local */
428 if (!filename
|| vfs_file_is_local (filename
))
430 fn
= vfs_canon_and_translate (filename
);
431 do_execute (command
, fn
, EXECUTE_INTERNAL
);
436 /* FIXME: Creation of new files on VFS is not supported */
440 localcopy
= mc_getlocalcopy (filename
);
441 if (localcopy
== NULL
)
443 message (D_ERROR
, MSG_ERROR
, _("Cannot fetch a local copy of %s"), filename
);
448 * filename can be an entry on panel, it can be changed by executing
449 * the command, so make a copy. Smarter VFS code would make the code
452 fn
= g_strdup (filename
);
453 mc_stat (localcopy
, &st
);
455 do_execute (command
, localcopy
, EXECUTE_INTERNAL
);
456 mc_stat (localcopy
, &st
);
457 mc_ungetlocalcopy (fn
, localcopy
, mtime
!= st
.st_mtime
);
462 /* --------------------------------------------------------------------------------------------- */