This source file includes following definitions.
- edition_post_exec
- edition_pre_exec
- do_possible_cd
- do_suspend_cmd
- execute_prepare_with_vfs_arg
- execute_cleanup_with_vfs_arg
- execute_get_opts_from_cfg
- execute_get_external_cmd_opts_from_config
- do_executev
- do_execute
- pre_exec
- post_exec
- shell_execute
- toggle_subshell
- execute_suspend
- execute_with_vfs_arg
- execute_external_editor_or_viewer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <config.h>
31
32 #include <signal.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36
37 #include "lib/global.h"
38
39 #include "lib/tty/tty.h"
40 #include "lib/tty/key.h"
41 #include "lib/tty/win.h"
42 #include "lib/vfs/vfs.h"
43 #include "lib/mcconfig.h"
44 #include "lib/util.h"
45 #include "lib/strutil.h"
46 #include "lib/widget.h"
47
48 #include "filemanager/filemanager.h"
49 #include "filemanager/layout.h"
50 #include "consaver/cons.saver.h"
51 #ifdef ENABLE_SUBSHELL
52 #include "subshell/subshell.h"
53 #endif
54 #include "setup.h"
55
56 #include "execute.h"
57
58
59
60 int pause_after_run = pause_on_dumb_terminals;
61
62
63
64
65
66
67
68 MC_MOCKABLE void do_execute (const char *shell, const char *command, int flags);
69 MC_MOCKABLE void do_executev (const char *shell, int flags, char *const argv[]);
70 MC_MOCKABLE char *execute_get_external_cmd_opts_from_config (const char *command,
71 const vfs_path_t * filename_vpath,
72 long start_line);
73
74
75
76
77
78
79
80 static void
81 edition_post_exec (void)
82 {
83 tty_enter_ca_mode ();
84
85
86 tty_reset_prog_mode ();
87 tty_flush_input ();
88
89 tty_keypad (TRUE);
90 tty_raw_mode ();
91 channels_up ();
92 enable_mouse ();
93 enable_bracketed_paste ();
94 if (mc_global.tty.alternate_plus_minus)
95 application_keypad_mode ();
96 }
97
98
99
100 static void
101 edition_pre_exec (void)
102 {
103 if (clear_before_exec)
104 tty_clear_screen ();
105 else
106 {
107 if (!(mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag))
108 printf ("\n\n");
109 }
110
111 channels_down ();
112 disable_mouse ();
113 disable_bracketed_paste ();
114
115 tty_reset_shell_mode ();
116 tty_keypad (FALSE);
117 tty_reset_screen ();
118
119 numeric_keypad_mode ();
120
121
122
123
124
125
126
127 tty_exit_ca_mode ();
128 }
129
130
131
132 #ifdef ENABLE_SUBSHELL
133 static void
134 do_possible_cd (const vfs_path_t *new_dir_vpath)
135 {
136 if (!panel_cd (current_panel, new_dir_vpath, cd_exact))
137 message (D_ERROR, _("Warning"), "%s",
138 _("The Commander can't change to the directory that\n"
139 "the subshell claims you are in. Perhaps you have\n"
140 "deleted your working directory, or given yourself\n"
141 "extra access permissions with the \"su\" command?"));
142 }
143 #endif
144
145
146
147 static void
148 do_suspend_cmd (void)
149 {
150 pre_exec ();
151
152 if (mc_global.tty.console_flag != '\0' && !mc_global.tty.use_subshell)
153 handle_console (CONSOLE_RESTORE);
154
155 #ifdef SIGTSTP
156 {
157 struct sigaction sigtstp_action;
158
159 memset (&sigtstp_action, 0, sizeof (sigtstp_action));
160
161
162
163 my_sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
164
165 kill (getpid (), SIGTSTP);
166
167
168 my_sigaction (SIGTSTP, &sigtstp_action, NULL);
169 }
170 #endif
171
172 if (mc_global.tty.console_flag != '\0' && !mc_global.tty.use_subshell)
173 handle_console (CONSOLE_SAVE);
174
175 edition_post_exec ();
176 }
177
178
179
180 static gboolean
181 execute_prepare_with_vfs_arg (const vfs_path_t *filename_vpath, vfs_path_t **localcopy_vpath,
182 time_t *mtime)
183 {
184 struct stat st;
185
186
187 if ((filename_vpath == NULL && vfs_file_is_local (vfs_get_raw_current_dir ()))
188 || vfs_file_is_local (filename_vpath))
189 return TRUE;
190
191
192 if (filename_vpath == NULL)
193 return FALSE;
194
195 *localcopy_vpath = mc_getlocalcopy (filename_vpath);
196 if (*localcopy_vpath == NULL)
197 {
198 message (D_ERROR, MSG_ERROR, _("Cannot fetch a local copy of %s"),
199 vfs_path_as_str (filename_vpath));
200 return FALSE;
201 }
202
203 mc_stat (*localcopy_vpath, &st);
204 *mtime = st.st_mtime;
205 return TRUE;
206 }
207
208
209
210 static void
211 execute_cleanup_with_vfs_arg (const vfs_path_t *filename_vpath, vfs_path_t **localcopy_vpath,
212 time_t *mtime)
213 {
214 if (*localcopy_vpath != NULL)
215 {
216 struct stat st;
217
218
219
220
221
222
223 mc_stat (*localcopy_vpath, &st);
224 mc_ungetlocalcopy (filename_vpath, *localcopy_vpath, *mtime != st.st_mtime);
225 vfs_path_free (*localcopy_vpath, TRUE);
226 *localcopy_vpath = NULL;
227 }
228 }
229
230
231
232 static char *
233 execute_get_opts_from_cfg (const char *command, const char *default_str)
234 {
235 char *str_from_config;
236
237 str_from_config =
238 mc_config_get_string_raw (mc_global.main_config, CONFIG_EXT_EDITOR_VIEWER_SECTION, command,
239 NULL);
240
241 if (str_from_config == NULL)
242 {
243 mc_config_t *cfg;
244
245 cfg = mc_config_init (mc_global.profile_name, TRUE);
246 if (cfg == NULL)
247 return g_strdup (default_str);
248
249 str_from_config =
250 mc_config_get_string_raw (cfg, CONFIG_EXT_EDITOR_VIEWER_SECTION, command, default_str);
251
252 mc_config_deinit (cfg);
253 }
254
255 return str_from_config;
256 }
257
258
259
260
261
262 char *
263 execute_get_external_cmd_opts_from_config (const char *command, const vfs_path_t *filename_vpath,
264 long start_line)
265 {
266 char *str_from_config, *return_str;
267 char *parameter;
268
269 if (filename_vpath == NULL)
270 return g_strdup ("");
271
272 parameter = g_shell_quote (vfs_path_get_last_path_str (filename_vpath));
273
274 if (start_line <= 0)
275 return parameter;
276
277 str_from_config = execute_get_opts_from_cfg (command, "%filename");
278
279 return_str = str_replace_all (str_from_config, "%filename", parameter);
280 g_free (parameter);
281 g_free (str_from_config);
282 str_from_config = return_str;
283
284 parameter = g_strdup_printf ("%ld", start_line);
285 return_str = str_replace_all (str_from_config, "%lineno", parameter);
286 g_free (parameter);
287 g_free (str_from_config);
288
289 return return_str;
290 }
291
292
293
294 void
295 do_executev (const char *shell, int flags, char *const argv[])
296 {
297 #ifdef ENABLE_SUBSHELL
298 vfs_path_t *new_dir_vpath = NULL;
299 #endif
300
301 vfs_path_t *old_vfs_dir_vpath = NULL;
302
303 if (!vfs_current_is_local ())
304 old_vfs_dir_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
305
306 if (mc_global.mc_run_mode == MC_RUN_FULL)
307 save_cwds_stat ();
308 pre_exec ();
309 if (mc_global.tty.console_flag != '\0')
310 handle_console (CONSOLE_RESTORE);
311
312 if (!mc_global.tty.use_subshell && *argv != NULL && (flags & EXECUTE_INTERNAL) == 0)
313 {
314 printf ("%s%s\n", mc_prompt, *argv);
315 fflush (stdout);
316 }
317 #ifdef ENABLE_SUBSHELL
318 if (mc_global.tty.use_subshell && (flags & EXECUTE_INTERNAL) == 0)
319 {
320 do_update_prompt ();
321
322
323 invoke_subshell (*argv, VISIBLY, old_vfs_dir_vpath != NULL ? NULL : &new_dir_vpath);
324 }
325 else
326 #endif
327 my_systemv_flags (flags, shell, argv);
328
329 if ((flags & EXECUTE_INTERNAL) == 0)
330 {
331 if ((pause_after_run == pause_always
332 || (pause_after_run == pause_on_dumb_terminals && !mc_global.tty.xterm_flag
333 && mc_global.tty.console_flag == '\0')) && quit == 0
334 #ifdef ENABLE_SUBSHELL
335 && subshell_state != RUNNING_COMMAND
336 #endif
337 )
338 {
339 printf ("%s", _("Press any key to continue..."));
340 fflush (stdout);
341 tty_raw_mode ();
342 get_key_code (0);
343 printf ("\r\n");
344 fflush (stdout);
345 }
346 if (mc_global.tty.console_flag != '\0' && output_lines != 0 && mc_global.keybar_visible)
347 {
348 putchar ('\n');
349 fflush (stdout);
350 }
351 }
352
353 if (mc_global.tty.console_flag != '\0')
354 handle_console (CONSOLE_SAVE);
355 edition_post_exec ();
356
357 #ifdef ENABLE_SUBSHELL
358 if (new_dir_vpath != NULL)
359 {
360 do_possible_cd (new_dir_vpath);
361 vfs_path_free (new_dir_vpath, TRUE);
362 }
363
364 #endif
365
366 if (old_vfs_dir_vpath != NULL)
367 {
368 mc_chdir (old_vfs_dir_vpath);
369 vfs_path_free (old_vfs_dir_vpath, TRUE);
370 }
371
372 if (mc_global.mc_run_mode == MC_RUN_FULL)
373 {
374 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
375 update_xterm_title_path ();
376 update_terminal_cwd ();
377 }
378
379 do_refresh ();
380 use_dash (TRUE);
381 }
382
383
384
385 void
386 do_execute (const char *shell, const char *command, int flags)
387 {
388 GPtrArray *args_array;
389
390 args_array = g_ptr_array_new ();
391 g_ptr_array_add (args_array, (char *) command);
392 g_ptr_array_add (args_array, NULL);
393
394 do_executev (shell, flags, (char *const *) args_array->pdata);
395
396 g_ptr_array_free (args_array, TRUE);
397 }
398
399
400
401
402
403 void
404 pre_exec (void)
405 {
406 use_dash (FALSE);
407 edition_pre_exec ();
408 }
409
410
411
412 void
413 post_exec (void)
414 {
415 edition_post_exec ();
416 use_dash (TRUE);
417 repaint_screen ();
418 }
419
420
421
422
423 void
424 shell_execute (const char *command, int flags)
425 {
426 char *cmd = NULL;
427
428 if ((flags & EXECUTE_HIDE) != 0)
429 {
430 cmd = g_strconcat (" ", command, (char *) NULL);
431 flags ^= EXECUTE_HIDE;
432 }
433
434 #ifdef ENABLE_SUBSHELL
435 if (mc_global.tty.use_subshell)
436 {
437 if (subshell_state == INACTIVE)
438 do_execute (mc_global.shell->path, cmd != NULL ? cmd : command,
439 flags | EXECUTE_AS_SHELL);
440 else
441 message (D_ERROR, MSG_ERROR, "%s", _("The shell is already running a command"));
442 }
443 else
444 #endif
445 do_execute (mc_global.shell->path, cmd != NULL ? cmd : command, flags | EXECUTE_AS_SHELL);
446
447 g_free (cmd);
448 }
449
450
451
452 void
453 toggle_subshell (void)
454 {
455 static gboolean message_flag = TRUE;
456
457 #ifdef ENABLE_SUBSHELL
458 vfs_path_t *new_dir_vpath = NULL;
459 #endif
460
461 SIG_ATOMIC_VOLATILE_T was_sigwinch = 0;
462
463 if (!(mc_global.tty.xterm_flag || mc_global.tty.console_flag != '\0'
464 || mc_global.tty.use_subshell || output_starts_shell))
465 {
466 if (message_flag)
467 message (D_ERROR, MSG_ERROR,
468 _("Not an xterm or Linux console;\nthe subshell cannot be toggled."));
469 message_flag = FALSE;
470 return;
471 }
472
473 channels_down ();
474 disable_mouse ();
475 disable_bracketed_paste ();
476 if (clear_before_exec)
477 tty_clear_screen ();
478 if (mc_global.tty.alternate_plus_minus)
479 numeric_keypad_mode ();
480 #ifndef HAVE_SLANG
481
482
483
484 tty_reset_shell_mode ();
485 #endif
486 tty_noecho ();
487 tty_keypad (FALSE);
488 tty_reset_screen ();
489 tty_exit_ca_mode ();
490 tty_raw_mode ();
491 if (mc_global.tty.console_flag != '\0')
492 handle_console (CONSOLE_RESTORE);
493
494 #ifdef ENABLE_SUBSHELL
495 if (mc_global.tty.use_subshell)
496 {
497 vfs_path_t **new_dir_p;
498
499 new_dir_p = vfs_current_is_local ()? &new_dir_vpath : NULL;
500 invoke_subshell (NULL, VISIBLY, new_dir_p);
501 }
502 else
503 #endif
504 {
505 if (output_starts_shell)
506 {
507 fputs (_("Type 'exit' to return to the Midnight Commander"), stderr);
508 fputs ("\n\r\n\r", stderr);
509
510 my_system (EXECUTE_INTERNAL, mc_global.shell->path, NULL);
511 }
512 else
513 get_key_code (0);
514 }
515
516 if (mc_global.tty.console_flag != '\0')
517 handle_console (CONSOLE_SAVE);
518
519 tty_enter_ca_mode ();
520
521 tty_reset_prog_mode ();
522 tty_keypad (TRUE);
523
524
525
526 if ((quit & SUBSHELL_EXIT) != 0)
527 {
528
529 if (quiet_quit_cmd ())
530 return;
531
532 quit = 0;
533 #ifdef ENABLE_SUBSHELL
534
535 if (mc_global.tty.use_subshell)
536 init_subshell ();
537 #endif
538 }
539
540 enable_mouse ();
541 enable_bracketed_paste ();
542 channels_up ();
543 if (mc_global.tty.alternate_plus_minus)
544 application_keypad_mode ();
545
546
547
548
549
550 was_sigwinch = tty_got_winch ();
551 tty_flush_winch ();
552
553 #ifdef ENABLE_SUBSHELL
554 if (mc_global.tty.use_subshell)
555 {
556 if (mc_global.mc_run_mode == MC_RUN_FULL)
557 {
558 if (new_dir_vpath != NULL)
559 do_possible_cd (new_dir_vpath);
560 }
561 else if (new_dir_vpath != NULL && mc_chdir (new_dir_vpath) != -1)
562 vfs_setup_cwd ();
563 }
564
565 vfs_path_free (new_dir_vpath, TRUE);
566 #endif
567
568 if (mc_global.mc_run_mode == MC_RUN_FULL)
569 {
570 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
571 update_xterm_title_path ();
572 update_terminal_cwd ();
573 }
574
575 if (was_sigwinch != 0 || tty_got_winch ())
576 dialog_change_screen_size ();
577 else
578 repaint_screen ();
579 }
580
581
582
583
584 gboolean
585 execute_suspend (const gchar *event_group_name, const gchar *event_name,
586 gpointer init_data, gpointer data)
587 {
588 (void) event_group_name;
589 (void) event_name;
590 (void) init_data;
591 (void) data;
592
593 if (mc_global.mc_run_mode == MC_RUN_FULL)
594 save_cwds_stat ();
595 do_suspend_cmd ();
596 if (mc_global.mc_run_mode == MC_RUN_FULL)
597 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
598 do_refresh ();
599
600 return TRUE;
601 }
602
603
604
605
606
607
608
609
610 void
611 execute_with_vfs_arg (const char *command, const vfs_path_t *filename_vpath)
612 {
613 vfs_path_t *localcopy_vpath = NULL;
614 const vfs_path_t *do_execute_vpath;
615 time_t mtime;
616
617 if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
618 return;
619
620 do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
621
622 do_execute (command, vfs_path_get_last_path_str (do_execute_vpath), EXECUTE_INTERNAL);
623
624 execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
625 }
626
627
628
629
630
631
632
633
634
635
636
637 void
638 execute_external_editor_or_viewer (const char *command, const vfs_path_t *filename_vpath,
639 long start_line)
640 {
641 vfs_path_t *localcopy_vpath = NULL;
642 const vfs_path_t *do_execute_vpath;
643 char *extern_cmd_options;
644 time_t mtime = 0;
645
646 if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
647 return;
648
649 do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
650
651 extern_cmd_options =
652 execute_get_external_cmd_opts_from_config (command, do_execute_vpath, start_line);
653
654 if (extern_cmd_options != NULL)
655 {
656 char **argv_cmd_options;
657 int argv_count;
658
659 if (g_shell_parse_argv (extern_cmd_options, &argv_count, &argv_cmd_options, NULL))
660 {
661 do_executev (command, EXECUTE_INTERNAL, argv_cmd_options);
662 g_strfreev (argv_cmd_options);
663 }
664 else
665 do_executev (command, EXECUTE_INTERNAL, NULL);
666
667 g_free (extern_cmd_options);
668 }
669
670 execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
671 }
672
673