Rework strutils for usage GString instread of self-made buffers.
[midnight-commander.git] / src / execute.c
bloba989563aecd55c4cb99f8c9998593516eb47e24f
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"
33 #include "../vfs/vfs.h"
36 static void
37 edition_post_exec (void)
39 do_enter_ca_mode ();
41 /* FIXME: Missing on slang endwin? */
42 reset_prog_mode ();
43 flushinp ();
45 keypad (stdscr, TRUE);
46 mc_raw_mode ();
47 channels_up ();
48 enable_mouse ();
49 if (alternate_plus_minus)
50 application_keypad_mode ();
54 static void
55 edition_pre_exec (void)
57 if (clear_before_exec)
58 clr_scr ();
59 else {
60 if (!(console_flag || xterm_flag))
61 printf ("\n\n");
64 channels_down ();
65 disable_mouse ();
67 reset_shell_mode ();
68 keypad (stdscr, FALSE);
69 endwin ();
71 numeric_keypad_mode ();
73 /* on xterms: maybe endwin did not leave the terminal on the shell
74 * screen page: do it now.
76 * Do not move this before endwin: in some systems rmcup includes
77 * a call to clear screen, so it will end up clearing the shell screen.
79 do_exit_ca_mode ();
83 /* Set up the terminal before executing a program */
84 static void
85 pre_exec (void)
87 use_dash (0);
88 edition_pre_exec ();
92 static void
93 do_execute (const char *shell, const char *command, int flags)
95 #ifdef HAVE_SUBSHELL_SUPPORT
96 char *new_dir = NULL;
97 #endif /* HAVE_SUBSHELL_SUPPORT */
99 #ifdef USE_VFS
100 char *old_vfs_dir = 0;
102 if (!vfs_current_is_local ())
103 old_vfs_dir = g_strdup (vfs_get_current_dir ());
104 #endif /* USE_VFS */
106 save_cwds_stat ();
107 pre_exec ();
108 if (console_flag)
109 handle_console (CONSOLE_RESTORE);
111 if (!use_subshell && command && !(flags & EXECUTE_INTERNAL)) {
112 printf ("%s%s\n", prompt, command);
113 fflush (stdout);
115 #ifdef HAVE_SUBSHELL_SUPPORT
116 if (use_subshell && !(flags & EXECUTE_INTERNAL)) {
117 do_update_prompt ();
119 /* We don't care if it died, higher level takes care of this */
120 #ifdef USE_VFS
121 invoke_subshell (command, VISIBLY, old_vfs_dir ? 0 : &new_dir);
122 #else
123 invoke_subshell (command, VISIBLY, &new_dir);
124 #endif /* !USE_VFS */
125 } else
126 #endif /* HAVE_SUBSHELL_SUPPORT */
127 my_system (flags, shell, command);
129 if (!(flags & EXECUTE_INTERNAL)) {
130 if ((pause_after_run == pause_always
131 || (pause_after_run == pause_on_dumb_terminals && !xterm_flag
132 && !console_flag)) && !quit
133 #ifdef HAVE_SUBSHELL_SUPPORT
134 && subshell_state != RUNNING_COMMAND
135 #endif /* HAVE_SUBSHELL_SUPPORT */
137 printf (_("Press any key to continue..."));
138 fflush (stdout);
139 mc_raw_mode ();
140 get_key_code (0);
141 printf ("\r\n");
142 fflush (stdout);
144 if (console_flag) {
145 if (output_lines && keybar_visible) {
146 putchar ('\n');
147 fflush (stdout);
152 if (console_flag)
153 handle_console (CONSOLE_SAVE);
154 edition_post_exec ();
156 #ifdef HAVE_SUBSHELL_SUPPORT
157 if (new_dir)
158 do_possible_cd (new_dir);
160 #endif /* HAVE_SUBSHELL_SUPPORT */
162 #ifdef USE_VFS
163 if (old_vfs_dir) {
164 mc_chdir (old_vfs_dir);
165 g_free (old_vfs_dir);
167 #endif /* USE_VFS */
169 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
170 update_xterm_title_path ();
172 do_refresh ();
173 use_dash (TRUE);
177 /* Executes a command */
178 void
179 shell_execute (const char *command, int flags)
181 char *cmd = NULL;
183 if (flags & EXECUTE_HIDE) {
184 cmd = g_strconcat (" ", command, (char *) NULL);
185 flags ^= EXECUTE_HIDE;
188 #ifdef HAVE_SUBSHELL_SUPPORT
189 if (use_subshell)
190 if (subshell_state == INACTIVE)
191 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
192 else
193 message (D_ERROR, MSG_ERROR,
194 _(" The shell is already running a command "));
195 else
196 #endif /* HAVE_SUBSHELL_SUPPORT */
197 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
199 g_free (cmd);
203 void
204 exec_shell (void)
206 do_execute (shell, 0, 0);
210 void
211 toggle_panels (void)
213 #ifdef HAVE_SUBSHELL_SUPPORT
214 char *new_dir = NULL;
215 char **new_dir_p;
216 #endif /* HAVE_SUBSHELL_SUPPORT */
218 channels_down ();
219 disable_mouse ();
220 if (clear_before_exec)
221 clr_scr ();
222 if (alternate_plus_minus)
223 numeric_keypad_mode ();
224 #ifndef HAVE_SLANG
225 /* With slang we don't want any of this, since there
226 * is no mc_raw_mode supported
228 reset_shell_mode ();
229 noecho ();
230 #endif /* !HAVE_SLANG */
231 keypad (stdscr, FALSE);
232 endwin ();
233 do_exit_ca_mode ();
234 mc_raw_mode ();
235 if (console_flag)
236 handle_console (CONSOLE_RESTORE);
238 #ifdef HAVE_SUBSHELL_SUPPORT
239 if (use_subshell) {
240 new_dir_p = vfs_current_is_local ()? &new_dir : NULL;
241 if (invoke_subshell (NULL, VISIBLY, new_dir_p))
242 quiet_quit_cmd (); /* User did `exit' or `logout': quit MC quietly */
243 } else
244 #endif /* HAVE_SUBSHELL_SUPPORT */
246 if (output_starts_shell) {
247 fprintf (stderr,
248 _("Type `exit' to return to the Midnight Commander"));
249 fprintf (stderr, "\n\r\n\r");
251 my_system (EXECUTE_INTERNAL, shell, NULL);
252 } else
253 get_key_code (0);
255 if (console_flag)
256 handle_console (CONSOLE_SAVE);
258 do_enter_ca_mode ();
260 reset_prog_mode ();
261 keypad (stdscr, TRUE);
263 /* Prevent screen flash when user did 'exit' or 'logout' within
264 subshell */
265 if (quit)
266 return;
268 enable_mouse ();
269 channels_up ();
270 if (alternate_plus_minus)
271 application_keypad_mode ();
273 #ifdef HAVE_SUBSHELL_SUPPORT
274 if (use_subshell) {
275 load_prompt (0, 0);
276 if (new_dir)
277 do_possible_cd (new_dir);
278 if (console_flag && output_lines)
279 show_console_contents (output_start_y,
280 LINES - keybar_visible - output_lines -
281 1, LINES - keybar_visible - 1);
283 #endif /* HAVE_SUBSHELL_SUPPORT */
285 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
286 update_xterm_title_path ();
287 do_refresh ();
291 static void
292 do_suspend_cmd (void)
294 pre_exec ();
296 if (console_flag && !use_subshell)
297 handle_console (CONSOLE_RESTORE);
299 #ifdef SIGTSTP
301 struct sigaction sigtstp_action;
303 /* Make sure that the SIGTSTP below will suspend us directly,
304 without calling ncurses' SIGTSTP handler; we *don't* want
305 ncurses to redraw the screen immediately after the SIGCONT */
306 sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
308 kill (getpid (), SIGTSTP);
310 /* Restore previous SIGTSTP action */
311 sigaction (SIGTSTP, &sigtstp_action, NULL);
313 #endif /* SIGTSTP */
315 if (console_flag && !use_subshell)
316 handle_console (CONSOLE_SAVE);
318 edition_post_exec ();
322 void
323 suspend_cmd (void)
325 save_cwds_stat ();
326 do_suspend_cmd ();
327 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
328 do_refresh ();
333 * Execute command on a filename that can be on VFS.
334 * Errors are reported to the user.
336 void
337 execute_with_vfs_arg (const char *command, const char *filename)
339 char *localcopy;
340 char *fn;
341 struct stat st;
342 time_t mtime;
344 /* Simplest case, this file is local */
345 if (!filename || vfs_file_is_local (filename)) {
346 fn = vfs_canon_and_translate (filename);
347 do_execute (command, fn, EXECUTE_INTERNAL);
348 g_free (fn);
349 return;
352 /* FIXME: Creation of new files on VFS is not supported */
353 if (!*filename)
354 return;
356 localcopy = mc_getlocalcopy (filename);
357 if (localcopy == NULL) {
358 message (D_ERROR, MSG_ERROR, _(" Cannot fetch a local copy of %s "),
359 filename);
360 return;
364 * filename can be an entry on panel, it can be changed by executing
365 * the command, so make a copy. Smarter VFS code would make the code
366 * below unnecessary.
368 fn = g_strdup (filename);
369 mc_stat (localcopy, &st);
370 mtime = st.st_mtime;
371 do_execute (command, localcopy, EXECUTE_INTERNAL);
372 mc_stat (localcopy, &st);
373 mc_ungetlocalcopy (fn, localcopy, mtime != st.st_mtime);
374 g_free (localcopy);
375 g_free (fn);