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 = mc_config_get_string_raw (mc_global.main_config,
238 CONFIG_EXT_EDITOR_VIEWER_SECTION, command, NULL);
239
240 if (str_from_config == NULL)
241 {
242 mc_config_t *cfg;
243
244 cfg = mc_config_init (mc_global.profile_name, TRUE);
245 if (cfg == NULL)
246 return g_strdup (default_str);
247
248 str_from_config =
249 mc_config_get_string_raw (cfg, CONFIG_EXT_EDITOR_VIEWER_SECTION, command, default_str);
250
251 mc_config_deinit (cfg);
252 }
253
254 return str_from_config;
255 }
256
257
258
259
260
261 char *
262 execute_get_external_cmd_opts_from_config (const char *command, const vfs_path_t *filename_vpath,
263 long start_line)
264 {
265 char *str_from_config, *return_str;
266 char *parameter;
267
268 if (filename_vpath == NULL)
269 return g_strdup ("");
270
271 parameter = g_shell_quote (vfs_path_get_last_path_str (filename_vpath));
272
273 if (start_line <= 0)
274 return parameter;
275
276 str_from_config = execute_get_opts_from_cfg (command, "%filename");
277
278 return_str = str_replace_all (str_from_config, "%filename", parameter);
279 g_free (parameter);
280 g_free (str_from_config);
281 str_from_config = return_str;
282
283 parameter = g_strdup_printf ("%ld", start_line);
284 return_str = str_replace_all (str_from_config, "%lineno", parameter);
285 g_free (parameter);
286 g_free (str_from_config);
287
288 return return_str;
289 }
290
291
292
293 void
294 do_executev (const char *shell, int flags, char *const argv[])
295 {
296 #ifdef ENABLE_SUBSHELL
297 vfs_path_t *new_dir_vpath = NULL;
298 #endif
299
300 vfs_path_t *old_vfs_dir_vpath = NULL;
301
302 if (!vfs_current_is_local ())
303 old_vfs_dir_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
304
305 if (mc_global.mc_run_mode == MC_RUN_FULL)
306 save_cwds_stat ();
307 pre_exec ();
308 if (mc_global.tty.console_flag != '\0')
309 handle_console (CONSOLE_RESTORE);
310
311 if (!mc_global.tty.use_subshell && (flags & EXECUTE_INTERNAL) == 0 && argv != NULL
312 && *argv != NULL)
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 && argv != NULL)
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'))
334 && quit == 0
335 #ifdef ENABLE_SUBSHELL
336 && subshell_state != RUNNING_COMMAND
337 #endif
338 )
339 {
340 printf ("%s", _ ("Press any key to continue..."));
341 fflush (stdout);
342 tty_raw_mode ();
343 get_key_code (0);
344 printf ("\r\n");
345 fflush (stdout);
346 }
347 if (mc_global.tty.console_flag != '\0' && output_lines != 0 && mc_global.keybar_visible)
348 {
349 putchar ('\n');
350 fflush (stdout);
351 }
352 }
353
354 if (mc_global.tty.console_flag != '\0')
355 handle_console (CONSOLE_SAVE);
356 edition_post_exec ();
357
358 #ifdef ENABLE_SUBSHELL
359 if (new_dir_vpath != NULL)
360 {
361 do_possible_cd (new_dir_vpath);
362 vfs_path_free (new_dir_vpath, TRUE);
363 }
364
365 #endif
366
367 if (old_vfs_dir_vpath != NULL)
368 {
369 mc_chdir (old_vfs_dir_vpath);
370 vfs_path_free (old_vfs_dir_vpath, TRUE);
371 }
372
373 if (mc_global.mc_run_mode == MC_RUN_FULL)
374 {
375 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
376 update_xterm_title_path ();
377 update_terminal_cwd ();
378 }
379
380 do_refresh ();
381 use_dash (TRUE);
382 }
383
384
385
386 void
387 do_execute (const char *shell, const char *command, int flags)
388 {
389 GPtrArray *args_array;
390
391 args_array = g_ptr_array_new ();
392 g_ptr_array_add (args_array, (char *) command);
393 g_ptr_array_add (args_array, NULL);
394
395 do_executev (shell, flags, (char *const *) args_array->pdata);
396
397 g_ptr_array_free (args_array, TRUE);
398 }
399
400
401
402
403
404 void
405 pre_exec (void)
406 {
407 use_dash (FALSE);
408 edition_pre_exec ();
409 }
410
411
412
413 void
414 post_exec (void)
415 {
416 edition_post_exec ();
417 use_dash (TRUE);
418 repaint_screen ();
419 }
420
421
422
423
424 void
425 shell_execute (const char *command, int flags)
426 {
427 char *cmd = NULL;
428
429 if ((flags & EXECUTE_HIDE) != 0)
430 {
431 cmd = g_strconcat (" ", command, (char *) NULL);
432 flags ^= EXECUTE_HIDE;
433 }
434
435 #ifdef ENABLE_SUBSHELL
436 if (mc_global.tty.use_subshell)
437 {
438 if (subshell_state == INACTIVE)
439 do_execute (mc_global.shell->path, cmd != NULL ? cmd : command,
440 flags | EXECUTE_AS_SHELL);
441 else
442 message (D_ERROR, MSG_ERROR, "%s", _ ("The shell is already running a command"));
443 }
444 else
445 #endif
446 do_execute (mc_global.shell->path, cmd != NULL ? cmd : command, flags | EXECUTE_AS_SHELL);
447
448 g_free (cmd);
449 }
450
451
452
453 void
454 toggle_subshell (void)
455 {
456 static gboolean message_flag = TRUE;
457
458 #ifdef ENABLE_SUBSHELL
459 vfs_path_t *new_dir_vpath = NULL;
460 #endif
461
462 SIG_ATOMIC_VOLATILE_T was_sigwinch = 0;
463
464 if (!(mc_global.tty.xterm_flag || mc_global.tty.console_flag != '\0'
465 || mc_global.tty.use_subshell || output_starts_shell))
466 {
467 if (message_flag)
468 message (D_ERROR, MSG_ERROR,
469 _ ("Not an xterm or Linux console;\nthe subshell cannot be toggled."));
470 message_flag = FALSE;
471 return;
472 }
473
474 channels_down ();
475 disable_mouse ();
476 disable_bracketed_paste ();
477 if (clear_before_exec)
478 tty_clear_screen ();
479 if (mc_global.tty.alternate_plus_minus)
480 numeric_keypad_mode ();
481 #ifndef HAVE_SLANG
482
483
484
485 tty_reset_shell_mode ();
486 #endif
487 tty_noecho ();
488 tty_keypad (FALSE);
489 tty_reset_screen ();
490 tty_exit_ca_mode ();
491 tty_raw_mode ();
492 if (mc_global.tty.console_flag != '\0')
493 handle_console (CONSOLE_RESTORE);
494
495 #ifdef ENABLE_SUBSHELL
496 if (mc_global.tty.use_subshell)
497 {
498 vfs_path_t **new_dir_p;
499
500 new_dir_p = vfs_current_is_local () ? &new_dir_vpath : NULL;
501 invoke_subshell (NULL, VISIBLY, new_dir_p);
502 }
503 else
504 #endif
505 {
506 if (output_starts_shell)
507 {
508 fputs (_ ("Type 'exit' to return to the Midnight Commander"), stderr);
509 fputs ("\n\r\n\r", stderr);
510
511 my_system (EXECUTE_INTERNAL, mc_global.shell->path, NULL);
512 }
513 else
514 get_key_code (0);
515 }
516
517 if (mc_global.tty.console_flag != '\0')
518 handle_console (CONSOLE_SAVE);
519
520 tty_enter_ca_mode ();
521
522 tty_reset_prog_mode ();
523 tty_keypad (TRUE);
524
525
526
527 if ((quit & SUBSHELL_EXIT) != 0)
528 {
529
530 if (quiet_quit_cmd ())
531 return;
532
533 quit = 0;
534 #ifdef ENABLE_SUBSHELL
535
536 if (mc_global.tty.use_subshell)
537 init_subshell ();
538 #endif
539 }
540
541 enable_mouse ();
542 enable_bracketed_paste ();
543 channels_up ();
544 if (mc_global.tty.alternate_plus_minus)
545 application_keypad_mode ();
546
547
548
549
550
551 was_sigwinch = 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, gpointer init_data,
586 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