Applied MC indentation policy.
[midnight-commander.git] / src / execute.c
blob507109db2bf89fddefd5ea0660b747227f9c40db
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 "lib/global.h"
30 #include "lib/tty/tty.h"
31 #include "lib/tty/key.h"
32 #include "lib/tty/win.h"
34 #include "main.h"
35 #include "consaver/cons.saver.h"
36 #include "subshell.h"
37 #include "layout.h"
38 #include "dialog.h"
39 #include "wtools.h"
40 #include "panel.h" /* update_panels() */
41 #include "execute.h"
42 #include "lib/vfs/mc-vfs/vfs.h"
45 static void
46 edition_post_exec (void)
48 do_enter_ca_mode ();
50 /* FIXME: Missing on slang endwin? */
51 tty_reset_prog_mode ();
52 tty_flush_input ();
54 tty_keypad (TRUE);
55 tty_raw_mode ();
56 channels_up ();
57 enable_mouse ();
58 if (alternate_plus_minus)
59 application_keypad_mode ();
63 static void
64 edition_pre_exec (void)
66 if (clear_before_exec)
67 clr_scr ();
68 else
70 if (!(console_flag || xterm_flag))
71 printf ("\n\n");
74 channels_down ();
75 disable_mouse ();
77 tty_reset_shell_mode ();
78 tty_keypad (FALSE);
79 tty_reset_screen ();
81 numeric_keypad_mode ();
83 /* on xterms: maybe endwin did not leave the terminal on the shell
84 * screen page: do it now.
86 * Do not move this before endwin: in some systems rmcup includes
87 * a call to clear screen, so it will end up clearing the shell screen.
89 do_exit_ca_mode ();
93 /* Set up the terminal before executing a program */
94 static void
95 pre_exec (void)
97 use_dash (0);
98 edition_pre_exec ();
102 #ifdef HAVE_SUBSHELL_SUPPORT
103 static void
104 do_possible_cd (const char *new_dir)
106 if (!do_cd (new_dir, cd_exact))
107 message (D_ERROR, _("Warning"),
108 _(" The Commander can't change to the directory that \n"
109 " the subshell claims you are in. Perhaps you have \n"
110 " deleted your working directory, or given yourself \n"
111 " extra access permissions with the \"su\" command? "));
113 #endif /* HAVE_SUBSHELL_SUPPORT */
115 static void
116 do_execute (const char *lc_shell, const char *command, int flags)
118 #ifdef HAVE_SUBSHELL_SUPPORT
119 char *new_dir = NULL;
120 #endif /* HAVE_SUBSHELL_SUPPORT */
122 #ifdef ENABLE_VFS
123 char *old_vfs_dir = 0;
125 if (!vfs_current_is_local ())
126 old_vfs_dir = g_strdup (vfs_get_current_dir ());
127 #endif /* ENABLE_VFS */
129 if (mc_run_mode == MC_RUN_FULL)
130 save_cwds_stat ();
131 pre_exec ();
132 if (console_flag)
133 handle_console (CONSOLE_RESTORE);
135 if (!use_subshell && command && !(flags & EXECUTE_INTERNAL))
137 printf ("%s%s\n", mc_prompt, command);
138 fflush (stdout);
140 #ifdef HAVE_SUBSHELL_SUPPORT
141 if (use_subshell && !(flags & EXECUTE_INTERNAL))
143 do_update_prompt ();
145 /* We don't care if it died, higher level takes care of this */
146 #ifdef ENABLE_VFS
147 invoke_subshell (command, VISIBLY, old_vfs_dir ? NULL : &new_dir);
148 #else
149 invoke_subshell (command, VISIBLY, &new_dir);
150 #endif /* !ENABLE_VFS */
152 else
153 #endif /* HAVE_SUBSHELL_SUPPORT */
154 my_system (flags, lc_shell, command);
156 if (!(flags & EXECUTE_INTERNAL))
158 if ((pause_after_run == pause_always
159 || (pause_after_run == pause_on_dumb_terminals && !xterm_flag
160 && !console_flag)) && !quit
161 #ifdef HAVE_SUBSHELL_SUPPORT
162 && subshell_state != RUNNING_COMMAND
163 #endif /* HAVE_SUBSHELL_SUPPORT */
166 printf (_("Press any key to continue..."));
167 fflush (stdout);
168 tty_raw_mode ();
169 get_key_code (0);
170 printf ("\r\n");
171 fflush (stdout);
173 if (console_flag)
175 if (output_lines && keybar_visible)
177 putchar ('\n');
178 fflush (stdout);
183 if (console_flag)
184 handle_console (CONSOLE_SAVE);
185 edition_post_exec ();
187 #ifdef HAVE_SUBSHELL_SUPPORT
188 if (new_dir)
189 do_possible_cd (new_dir);
191 #endif /* HAVE_SUBSHELL_SUPPORT */
193 #ifdef ENABLE_VFS
194 if (old_vfs_dir)
196 mc_chdir (old_vfs_dir);
197 g_free (old_vfs_dir);
199 #endif /* ENABLE_VFS */
201 if (mc_run_mode == MC_RUN_FULL)
203 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
204 update_xterm_title_path ();
207 do_refresh ();
208 use_dash (TRUE);
212 /* Executes a command */
213 void
214 shell_execute (const char *command, int flags)
216 char *cmd = NULL;
218 if (flags & EXECUTE_HIDE)
220 cmd = g_strconcat (" ", command, (char *) NULL);
221 flags ^= EXECUTE_HIDE;
224 #ifdef HAVE_SUBSHELL_SUPPORT
225 if (use_subshell)
226 if (subshell_state == INACTIVE)
227 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
228 else
229 message (D_ERROR, MSG_ERROR, _(" The shell is already running a command "));
230 else
231 #endif /* HAVE_SUBSHELL_SUPPORT */
232 do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
234 g_free (cmd);
238 void
239 exec_shell (void)
241 do_execute (shell, 0, 0);
245 void
246 toggle_panels (void)
248 #ifdef HAVE_SUBSHELL_SUPPORT
249 char *new_dir = NULL;
250 char **new_dir_p;
251 #endif /* HAVE_SUBSHELL_SUPPORT */
253 channels_down ();
254 disable_mouse ();
255 if (clear_before_exec)
256 clr_scr ();
257 if (alternate_plus_minus)
258 numeric_keypad_mode ();
259 #ifndef HAVE_SLANG
260 /* With slang we don't want any of this, since there
261 * is no raw_mode supported
263 tty_reset_shell_mode ();
264 #endif /* !HAVE_SLANG */
265 tty_noecho ();
266 tty_keypad (FALSE);
267 tty_reset_screen ();
268 do_exit_ca_mode ();
269 tty_raw_mode ();
270 if (console_flag)
271 handle_console (CONSOLE_RESTORE);
273 #ifdef HAVE_SUBSHELL_SUPPORT
274 if (use_subshell)
276 new_dir_p = vfs_current_is_local ()? &new_dir : NULL;
277 if (invoke_subshell (NULL, VISIBLY, new_dir_p))
278 quiet_quit_cmd (); /* User did `exit' or `logout': quit MC quietly */
280 else
281 #endif /* HAVE_SUBSHELL_SUPPORT */
283 if (output_starts_shell)
285 fprintf (stderr, _("Type `exit' to return to the Midnight Commander"));
286 fprintf (stderr, "\n\r\n\r");
288 my_system (EXECUTE_INTERNAL, shell, NULL);
290 else
291 get_key_code (0);
293 if (console_flag)
294 handle_console (CONSOLE_SAVE);
296 do_enter_ca_mode ();
298 tty_reset_prog_mode ();
299 tty_keypad (TRUE);
301 /* Prevent screen flash when user did 'exit' or 'logout' within
302 subshell */
303 if (quit)
304 return;
306 enable_mouse ();
307 channels_up ();
308 if (alternate_plus_minus)
309 application_keypad_mode ();
311 #ifdef HAVE_SUBSHELL_SUPPORT
312 if (use_subshell)
314 load_prompt (0, 0);
315 if (new_dir)
316 do_possible_cd (new_dir);
317 if (console_flag && output_lines)
318 show_console_contents (output_start_y,
319 LINES - keybar_visible - output_lines -
320 1, LINES - keybar_visible - 1);
322 #endif /* HAVE_SUBSHELL_SUPPORT */
324 if (mc_run_mode == MC_RUN_FULL)
326 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
327 update_xterm_title_path ();
329 repaint_screen ();
333 static void
334 do_suspend_cmd (void)
336 pre_exec ();
338 if (console_flag && !use_subshell)
339 handle_console (CONSOLE_RESTORE);
341 #ifdef SIGTSTP
343 struct sigaction sigtstp_action;
345 /* Make sure that the SIGTSTP below will suspend us directly,
346 without calling ncurses' SIGTSTP handler; we *don't* want
347 ncurses to redraw the screen immediately after the SIGCONT */
348 sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
350 kill (getpid (), SIGTSTP);
352 /* Restore previous SIGTSTP action */
353 sigaction (SIGTSTP, &sigtstp_action, NULL);
355 #endif /* SIGTSTP */
357 if (console_flag && !use_subshell)
358 handle_console (CONSOLE_SAVE);
360 edition_post_exec ();
364 void
365 suspend_cmd (void)
367 if (mc_run_mode == MC_RUN_FULL)
368 save_cwds_stat ();
369 do_suspend_cmd ();
370 if (mc_run_mode == MC_RUN_FULL)
371 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
372 do_refresh ();
377 * Execute command on a filename that can be on VFS.
378 * Errors are reported to the user.
380 void
381 execute_with_vfs_arg (const char *command, const char *filename)
383 char *localcopy;
384 char *fn;
385 struct stat st;
386 time_t mtime;
388 /* Simplest case, this file is local */
389 if (!filename || vfs_file_is_local (filename))
391 fn = vfs_canon_and_translate (filename);
392 do_execute (command, fn, EXECUTE_INTERNAL);
393 g_free (fn);
394 return;
397 /* FIXME: Creation of new files on VFS is not supported */
398 if (!*filename)
399 return;
401 localcopy = mc_getlocalcopy (filename);
402 if (localcopy == NULL)
404 message (D_ERROR, MSG_ERROR, _(" Cannot fetch a local copy of %s "), filename);
405 return;
409 * filename can be an entry on panel, it can be changed by executing
410 * the command, so make a copy. Smarter VFS code would make the code
411 * below unnecessary.
413 fn = g_strdup (filename);
414 mc_stat (localcopy, &st);
415 mtime = st.st_mtime;
416 do_execute (command, localcopy, EXECUTE_INTERNAL);
417 mc_stat (localcopy, &st);
418 mc_ungetlocalcopy (fn, localcopy, mtime != st.st_mtime);
419 g_free (localcopy);
420 g_free (fn);