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"
35 #include "consaver/cons.saver.h"
40 #include "panel.h" /* update_panels() */
42 #include "lib/vfs/mc-vfs/vfs.h"
46 edition_post_exec (void)
50 /* FIXME: Missing on slang endwin? */
51 tty_reset_prog_mode ();
58 if (alternate_plus_minus
)
59 application_keypad_mode ();
64 edition_pre_exec (void)
66 if (clear_before_exec
)
70 if (!(console_flag
|| xterm_flag
))
77 tty_reset_shell_mode ();
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.
93 /* Set up the terminal before executing a program */
102 #ifdef HAVE_SUBSHELL_SUPPORT
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 */
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 */
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
)
133 handle_console (CONSOLE_RESTORE
);
135 if (!use_subshell
&& command
&& !(flags
& EXECUTE_INTERNAL
))
137 printf ("%s%s\n", mc_prompt
, command
);
140 #ifdef HAVE_SUBSHELL_SUPPORT
141 if (use_subshell
&& !(flags
& EXECUTE_INTERNAL
))
145 /* We don't care if it died, higher level takes care of this */
147 invoke_subshell (command
, VISIBLY
, old_vfs_dir
? NULL
: &new_dir
);
149 invoke_subshell (command
, VISIBLY
, &new_dir
);
150 #endif /* !ENABLE_VFS */
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..."));
175 if (output_lines
&& keybar_visible
)
184 handle_console (CONSOLE_SAVE
);
185 edition_post_exec ();
187 #ifdef HAVE_SUBSHELL_SUPPORT
189 do_possible_cd (new_dir
);
191 #endif /* HAVE_SUBSHELL_SUPPORT */
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 ();
212 /* Executes a command */
214 shell_execute (const char *command
, int flags
)
218 if (flags
& EXECUTE_HIDE
)
220 cmd
= g_strconcat (" ", command
, (char *) NULL
);
221 flags
^= EXECUTE_HIDE
;
224 #ifdef HAVE_SUBSHELL_SUPPORT
226 if (subshell_state
== INACTIVE
)
227 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
229 message (D_ERROR
, MSG_ERROR
, _(" The shell is already running a command "));
231 #endif /* HAVE_SUBSHELL_SUPPORT */
232 do_execute (shell
, cmd
? cmd
: command
, flags
| EXECUTE_AS_SHELL
);
241 do_execute (shell
, 0, 0);
248 #ifdef HAVE_SUBSHELL_SUPPORT
249 char *new_dir
= NULL
;
251 #endif /* HAVE_SUBSHELL_SUPPORT */
255 if (clear_before_exec
)
257 if (alternate_plus_minus
)
258 numeric_keypad_mode ();
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 */
271 handle_console (CONSOLE_RESTORE
);
273 #ifdef HAVE_SUBSHELL_SUPPORT
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 */
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
);
294 handle_console (CONSOLE_SAVE
);
298 tty_reset_prog_mode ();
301 /* Prevent screen flash when user did 'exit' or 'logout' within
308 if (alternate_plus_minus
)
309 application_keypad_mode ();
311 #ifdef HAVE_SUBSHELL_SUPPORT
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 ();
334 do_suspend_cmd (void)
338 if (console_flag
&& !use_subshell
)
339 handle_console (CONSOLE_RESTORE
);
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
);
357 if (console_flag
&& !use_subshell
)
358 handle_console (CONSOLE_SAVE
);
360 edition_post_exec ();
367 if (mc_run_mode
== MC_RUN_FULL
)
370 if (mc_run_mode
== MC_RUN_FULL
)
371 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
377 * Execute command on a filename that can be on VFS.
378 * Errors are reported to the user.
381 execute_with_vfs_arg (const char *command
, const char *filename
)
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
);
397 /* FIXME: Creation of new files on VFS is not supported */
401 localcopy
= mc_getlocalcopy (filename
);
402 if (localcopy
== NULL
)
404 message (D_ERROR
, MSG_ERROR
, _(" Cannot fetch a local copy of %s "), filename
);
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
413 fn
= g_strdup (filename
);
414 mc_stat (localcopy
, &st
);
416 do_execute (command
, localcopy
, EXECUTE_INTERNAL
);
417 mc_stat (localcopy
, &st
);
418 mc_ungetlocalcopy (fn
, localcopy
, mtime
!= st
.st_mtime
);