done_screen() is moved from src/layout.c to src/main.c.
[midnight-commander.git] / src / execute.c
blob85817c065623d22076301e3d5944211243f66585
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. */
18 /** \file execute.c
19 * \brief Source: execution routines
22 #include <config.h>
24 #include <signal.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
28 #include "global.h"
30 #include "../src/tty/tty.h"
31 #include "../src/tty/key.h"
32 #include "../src/tty/win.h"
34 #include "main.h"
35 #include "cons.saver.h"
36 #include "subshell.h"
37 #include "layout.h"
38 #include "dialog.h"
39 #include "wtools.h"
40 #include "execute.h"
41 #include "../vfs/vfs.h"
44 static void
45 edition_post_exec (void)
47 do_enter_ca_mode ();
49 /* FIXME: Missing on slang endwin? */
50 tty_reset_prog_mode ();
51 tty_flush_input ();
53 tty_keypad (TRUE);
54 tty_raw_mode ();
55 channels_up ();
56 enable_mouse ();
57 if (alternate_plus_minus)
58 application_keypad_mode ();
62 static void
63 edition_pre_exec (void)
65 if (clear_before_exec)
66 clr_scr ();
67 else {
68 if (!(console_flag || xterm_flag))
69 printf ("\n\n");
72 channels_down ();
73 disable_mouse ();
75 tty_reset_shell_mode ();
76 tty_keypad (FALSE);
77 tty_reset_screen ();
79 numeric_keypad_mode ();
81 /* on xterms: maybe endwin did not leave the terminal on the shell
82 * screen page: do it now.
84 * Do not move this before endwin: in some systems rmcup includes
85 * a call to clear screen, so it will end up clearing the shell screen.
87 do_exit_ca_mode ();
91 /* Set up the terminal before executing a program */
92 static void
93 pre_exec (void)
95 use_dash (0);
96 edition_pre_exec ();
100 static void
101 do_execute (const char *shell, const char *command, int flags)
103 #ifdef HAVE_SUBSHELL_SUPPORT
104 char *new_dir = NULL;
105 #endif /* HAVE_SUBSHELL_SUPPORT */
107 #ifdef USE_VFS
108 char *old_vfs_dir = 0;
110 if (!vfs_current_is_local ())
111 old_vfs_dir = g_strdup (vfs_get_current_dir ());
112 #endif /* USE_VFS */
114 save_cwds_stat ();
115 pre_exec ();
116 if (console_flag)
117 handle_console (CONSOLE_RESTORE);
119 if (!use_subshell && command && !(flags & EXECUTE_INTERNAL)) {
120 printf ("%s%s\n", prompt, command);
121 fflush (stdout);
123 #ifdef HAVE_SUBSHELL_SUPPORT
124 if (use_subshell && !(flags & EXECUTE_INTERNAL)) {
125 do_update_prompt ();
127 /* We don't care if it died, higher level takes care of this */
128 #ifdef USE_VFS
129 invoke_subshell (command, VISIBLY, old_vfs_dir ? NULL : &new_dir);
130 #else
131 invoke_subshell (command, VISIBLY, &new_dir);
132 #endif /* !USE_VFS */
133 } else
134 #endif /* HAVE_SUBSHELL_SUPPORT */
135 my_system (flags, shell, command);
137 if (!(flags & EXECUTE_INTERNAL)) {
138 if ((pause_after_run == pause_always
139 || (pause_after_run == pause_on_dumb_terminals && !xterm_flag
140 && !console_flag)) && !quit
141 #ifdef HAVE_SUBSHELL_SUPPORT
142 && subshell_state != RUNNING_COMMAND
143 #endif /* HAVE_SUBSHELL_SUPPORT */
145 printf (_("Press any key to continue..."));
146 fflush (stdout);
147 tty_raw_mode ();
148 get_key_code (0);
149 printf ("\r\n");
150 fflush (stdout);
152 if (console_flag) {
153 if (output_lines && keybar_visible) {
154 putchar ('\n');
155 fflush (stdout);
160 if (console_flag)
161 handle_console (CONSOLE_SAVE);
162 edition_post_exec ();
164 #ifdef HAVE_SUBSHELL_SUPPORT
165 if (new_dir)
166 do_possible_cd (new_dir);
168 #endif /* HAVE_SUBSHELL_SUPPORT */
170 #ifdef USE_VFS
171 if (old_vfs_dir) {
172 mc_chdir (old_vfs_dir);
173 g_free (old_vfs_dir);
175 #endif /* USE_VFS */
177 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
178 update_xterm_title_path ();
180 do_refresh ();
181 use_dash (TRUE);
185 /* Executes a command */
186 void
187 shell_execute (const char *command, int flags)
189 char *cmd = NULL;
191 if (flags & EXECUTE_HIDE) {
192 cmd = g_strconcat (" ", command, (char *) NULL);
193 flags ^= EXECUTE_HIDE;
196 #ifdef HAVE_SUBSHELL_SUPPORT
197 if (use_subshell)
198 if (subshell_state == INACTIVE)
199 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
200 else
201 message (D_ERROR, MSG_ERROR,
202 _(" The shell is already running a command "));
203 else
204 #endif /* HAVE_SUBSHELL_SUPPORT */
205 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
207 g_free (cmd);
211 void
212 exec_shell (void)
214 do_execute (shell, 0, 0);
218 void
219 toggle_panels (void)
221 #ifdef HAVE_SUBSHELL_SUPPORT
222 char *new_dir = NULL;
223 char **new_dir_p;
224 #endif /* HAVE_SUBSHELL_SUPPORT */
226 channels_down ();
227 disable_mouse ();
228 if (clear_before_exec)
229 clr_scr ();
230 if (alternate_plus_minus)
231 numeric_keypad_mode ();
232 #ifndef HAVE_SLANG
233 /* With slang we don't want any of this, since there
234 * is no tty_raw_mode supported
236 tty_reset_shell_mode ();
237 #endif /* !HAVE_SLANG */
238 tty_noecho ();
239 tty_keypad (FALSE);
240 tty_reset_screen ();
241 do_exit_ca_mode ();
242 tty_raw_mode ();
243 if (console_flag)
244 handle_console (CONSOLE_RESTORE);
246 #ifdef HAVE_SUBSHELL_SUPPORT
247 if (use_subshell) {
248 new_dir_p = vfs_current_is_local ()? &new_dir : NULL;
249 if (invoke_subshell (NULL, VISIBLY, new_dir_p))
250 quiet_quit_cmd (); /* User did `exit' or `logout': quit MC quietly */
251 } else
252 #endif /* HAVE_SUBSHELL_SUPPORT */
254 if (output_starts_shell) {
255 fprintf (stderr,
256 _("Type `exit' to return to the Midnight Commander"));
257 fprintf (stderr, "\n\r\n\r");
259 my_system (EXECUTE_INTERNAL, shell, NULL);
260 } else
261 get_key_code (0);
263 if (console_flag)
264 handle_console (CONSOLE_SAVE);
266 do_enter_ca_mode ();
268 tty_reset_prog_mode ();
269 tty_keypad (TRUE);
271 /* Prevent screen flash when user did 'exit' or 'logout' within
272 subshell */
273 if (quit)
274 return;
276 enable_mouse ();
277 channels_up ();
278 if (alternate_plus_minus)
279 application_keypad_mode ();
281 #ifdef HAVE_SUBSHELL_SUPPORT
282 if (use_subshell) {
283 load_prompt (0, 0);
284 if (new_dir)
285 do_possible_cd (new_dir);
286 if (console_flag && output_lines)
287 show_console_contents (output_start_y,
288 LINES - keybar_visible - output_lines -
289 1, LINES - keybar_visible - 1);
291 #endif /* HAVE_SUBSHELL_SUPPORT */
293 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
294 update_xterm_title_path ();
295 do_refresh ();
299 static void
300 do_suspend_cmd (void)
302 pre_exec ();
304 if (console_flag && !use_subshell)
305 handle_console (CONSOLE_RESTORE);
307 #ifdef SIGTSTP
309 struct sigaction sigtstp_action;
311 /* Make sure that the SIGTSTP below will suspend us directly,
312 without calling ncurses' SIGTSTP handler; we *don't* want
313 ncurses to redraw the screen immediately after the SIGCONT */
314 sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
316 kill (getpid (), SIGTSTP);
318 /* Restore previous SIGTSTP action */
319 sigaction (SIGTSTP, &sigtstp_action, NULL);
321 #endif /* SIGTSTP */
323 if (console_flag && !use_subshell)
324 handle_console (CONSOLE_SAVE);
326 edition_post_exec ();
330 void
331 suspend_cmd (void)
333 save_cwds_stat ();
334 do_suspend_cmd ();
335 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
336 do_refresh ();
341 * Execute command on a filename that can be on VFS.
342 * Errors are reported to the user.
344 void
345 execute_with_vfs_arg (const char *command, const char *filename)
347 char *localcopy;
348 char *fn;
349 struct stat st;
350 time_t mtime;
352 /* Simplest case, this file is local */
353 if (!filename || vfs_file_is_local (filename)) {
354 fn = vfs_canon_and_translate (filename);
355 do_execute (command, fn, EXECUTE_INTERNAL);
356 g_free (fn);
357 return;
360 /* FIXME: Creation of new files on VFS is not supported */
361 if (!*filename)
362 return;
364 localcopy = mc_getlocalcopy (filename);
365 if (localcopy == NULL) {
366 message (D_ERROR, MSG_ERROR, _(" Cannot fetch a local copy of %s "),
367 filename);
368 return;
372 * filename can be an entry on panel, it can be changed by executing
373 * the command, so make a copy. Smarter VFS code would make the code
374 * below unnecessary.
376 fn = g_strdup (filename);
377 mc_stat (localcopy, &st);
378 mtime = st.st_mtime;
379 do_execute (command, localcopy, EXECUTE_INTERNAL);
380 mc_stat (localcopy, &st);
381 mc_ungetlocalcopy (fn, localcopy, mtime != st.st_mtime);
382 g_free (localcopy);
383 g_free (fn);