Original patch as attached on the bugreport
[midnight-commander.git] / src / execute.c
blobeb31cacd8715e16bba4396391f5a4c766672bccc
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 #include <config.h>
20 #include <signal.h>
22 #include "global.h"
23 #include "tty.h"
24 #include "win.h"
25 #include "key.h"
26 #include "main.h"
27 #include "cons.saver.h"
28 #include "subshell.h"
29 #include "layout.h"
30 #include "dialog.h"
31 #include "wtools.h"
32 #include "execute.h"
35 static void
36 edition_post_exec (void)
38 do_enter_ca_mode ();
40 /* FIXME: Missing on slang endwin? */
41 reset_prog_mode ();
42 flushinp ();
44 keypad (stdscr, TRUE);
45 mc_raw_mode ();
46 channels_up ();
47 enable_mouse ();
48 if (alternate_plus_minus)
49 application_keypad_mode ();
53 static void
54 edition_pre_exec (void)
56 if (clear_before_exec)
57 clr_scr ();
58 else {
59 if (!(console_flag || xterm_flag))
60 printf ("\n\n");
63 channels_down ();
64 disable_mouse ();
66 reset_shell_mode ();
67 keypad (stdscr, FALSE);
68 endwin ();
70 numeric_keypad_mode ();
72 /* on xterms: maybe endwin did not leave the terminal on the shell
73 * screen page: do it now.
75 * Do not move this before endwin: in some systems rmcup includes
76 * a call to clear screen, so it will end up clearing the shell screen.
78 do_exit_ca_mode ();
82 /* Set up the terminal before executing a program */
83 static void
84 pre_exec (void)
86 use_dash (0);
87 edition_pre_exec ();
91 static void
92 do_execute (const char *shell, const char *command, int flags)
94 #ifdef HAVE_SUBSHELL_SUPPORT
95 char *new_dir = NULL;
96 #endif /* HAVE_SUBSHELL_SUPPORT */
98 #ifdef USE_VFS
99 char *old_vfs_dir = 0;
101 if (!vfs_current_is_local ())
102 old_vfs_dir = g_strdup (vfs_get_current_dir ());
103 #endif /* USE_VFS */
105 save_cwds_stat ();
106 pre_exec ();
107 if (console_flag)
108 handle_console (CONSOLE_RESTORE);
110 if (!use_subshell && command && !(flags & EXECUTE_INTERNAL)) {
111 printf ("%s%s\n", prompt, command);
112 fflush (stdout);
114 #ifdef HAVE_SUBSHELL_SUPPORT
115 if (use_subshell && !(flags & EXECUTE_INTERNAL)) {
116 do_update_prompt ();
118 /* We don't care if it died, higher level takes care of this */
119 #ifdef USE_VFS
120 invoke_subshell (command, VISIBLY, old_vfs_dir ? 0 : &new_dir);
121 #else
122 invoke_subshell (command, VISIBLY, &new_dir);
123 #endif /* !USE_VFS */
124 } else
125 #endif /* HAVE_SUBSHELL_SUPPORT */
126 my_system (flags, shell, command);
128 if (!(flags & EXECUTE_INTERNAL)) {
129 if ((pause_after_run == pause_always
130 || (pause_after_run == pause_on_dumb_terminals && !xterm_flag
131 && !console_flag)) && !quit
132 #ifdef HAVE_SUBSHELL_SUPPORT
133 && subshell_state != RUNNING_COMMAND
134 #endif /* HAVE_SUBSHELL_SUPPORT */
136 printf (_("Press any key to continue..."));
137 fflush (stdout);
138 mc_raw_mode ();
139 get_key_code (0);
140 printf ("\r\n");
141 fflush (stdout);
143 if (console_flag) {
144 if (output_lines && keybar_visible) {
145 putchar ('\n');
146 fflush (stdout);
151 if (console_flag)
152 handle_console (CONSOLE_SAVE);
153 edition_post_exec ();
155 #ifdef HAVE_SUBSHELL_SUPPORT
156 if (new_dir)
157 do_possible_cd (new_dir);
159 #endif /* HAVE_SUBSHELL_SUPPORT */
161 #ifdef USE_VFS
162 if (old_vfs_dir) {
163 mc_chdir (old_vfs_dir);
164 g_free (old_vfs_dir);
166 #endif /* USE_VFS */
168 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
169 update_xterm_title_path ();
171 do_refresh ();
172 use_dash (TRUE);
176 /* Executes a command */
177 void
178 shell_execute (const char *command, int flags)
180 char *cmd = NULL;
182 if (flags & EXECUTE_HIDE) {
183 cmd = g_strconcat (" ", command, (char *) NULL);
184 flags ^= EXECUTE_HIDE;
187 #ifdef HAVE_SUBSHELL_SUPPORT
188 if (use_subshell)
189 if (subshell_state == INACTIVE)
190 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
191 else
192 message (1, MSG_ERROR,
193 _(" The shell is already running a command "));
194 else
195 #endif /* HAVE_SUBSHELL_SUPPORT */
196 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
198 g_free (cmd);
202 void
203 exec_shell (void)
205 do_execute (shell, 0, 0);
209 void
210 toggle_panels (void)
212 #ifdef HAVE_SUBSHELL_SUPPORT
213 char *new_dir = NULL;
214 char **new_dir_p;
215 #endif /* HAVE_SUBSHELL_SUPPORT */
217 channels_down ();
218 disable_mouse ();
219 if (clear_before_exec)
220 clr_scr ();
221 if (alternate_plus_minus)
222 numeric_keypad_mode ();
223 #ifndef HAVE_SLANG
224 /* With slang we don't want any of this, since there
225 * is no mc_raw_mode supported
227 reset_shell_mode ();
228 noecho ();
229 #endif /* !HAVE_SLANG */
230 keypad (stdscr, FALSE);
231 endwin ();
232 do_exit_ca_mode ();
233 mc_raw_mode ();
234 if (console_flag)
235 handle_console (CONSOLE_RESTORE);
237 #ifdef HAVE_SUBSHELL_SUPPORT
238 if (use_subshell) {
239 new_dir_p = vfs_current_is_local ()? &new_dir : NULL;
240 if (invoke_subshell (NULL, VISIBLY, new_dir_p))
241 quiet_quit_cmd (); /* User did `exit' or `logout': quit MC quietly */
242 } else
243 #endif /* HAVE_SUBSHELL_SUPPORT */
245 if (output_starts_shell) {
246 fprintf (stderr,
247 _("Type `exit' to return to the Midnight Commander"));
248 fprintf (stderr, "\n\r\n\r");
250 my_system (EXECUTE_INTERNAL, shell, NULL);
251 } else
252 get_key_code (0);
254 if (console_flag)
255 handle_console (CONSOLE_SAVE);
257 do_enter_ca_mode ();
259 reset_prog_mode ();
260 keypad (stdscr, TRUE);
262 /* Prevent screen flash when user did 'exit' or 'logout' within
263 subshell */
264 if (quit)
265 return;
267 enable_mouse ();
268 channels_up ();
269 if (alternate_plus_minus)
270 application_keypad_mode ();
272 #ifdef HAVE_SUBSHELL_SUPPORT
273 if (use_subshell) {
274 load_prompt (0, 0);
275 if (new_dir)
276 do_possible_cd (new_dir);
277 if (console_flag && output_lines)
278 show_console_contents (output_start_y,
279 LINES - keybar_visible - output_lines -
280 1, LINES - keybar_visible - 1);
282 #endif /* HAVE_SUBSHELL_SUPPORT */
284 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
285 update_xterm_title_path ();
286 do_refresh ();
290 static void
291 do_suspend_cmd (void)
293 pre_exec ();
295 if (console_flag && !use_subshell)
296 handle_console (CONSOLE_RESTORE);
298 #ifdef SIGTSTP
300 struct sigaction sigtstp_action;
302 /* Make sure that the SIGTSTP below will suspend us directly,
303 without calling ncurses' SIGTSTP handler; we *don't* want
304 ncurses to redraw the screen immediately after the SIGCONT */
305 sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
307 kill (getpid (), SIGTSTP);
309 /* Restore previous SIGTSTP action */
310 sigaction (SIGTSTP, &sigtstp_action, NULL);
312 #endif /* SIGTSTP */
314 if (console_flag && !use_subshell)
315 handle_console (CONSOLE_SAVE);
317 edition_post_exec ();
321 void
322 suspend_cmd (void)
324 save_cwds_stat ();
325 do_suspend_cmd ();
326 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
327 do_refresh ();
332 * Execute command on a filename that can be on VFS.
333 * Errors are reported to the user.
335 void
336 execute_with_vfs_arg (const char *command, const char *filename)
338 char *localcopy;
339 char *fn;
340 struct stat st;
341 time_t mtime;
343 /* Simplest case, this file is local */
344 if (!filename || vfs_file_is_local (filename)) {
345 do_execute (command, filename, EXECUTE_INTERNAL);
346 return;
349 /* FIXME: Creation of new files on VFS is not supported */
350 if (!*filename)
351 return;
353 localcopy = mc_getlocalcopy (filename);
354 if (localcopy == NULL) {
355 message (1, MSG_ERROR, _(" Cannot fetch a local copy of %s "),
356 filename);
357 return;
361 * filename can be an entry on panel, it can be changed by executing
362 * the command, so make a copy. Smarter VFS code would make the code
363 * below unnecessary.
365 fn = g_strdup (filename);
366 mc_stat (localcopy, &st);
367 mtime = st.st_mtime;
368 do_execute (command, localcopy, EXECUTE_INTERNAL);
369 mc_stat (localcopy, &st);
370 mc_ungetlocalcopy (fn, localcopy, mtime != st.st_mtime);
371 g_free (localcopy);
372 g_free (fn);