This source file includes following definitions.
- write_all
- init_subshell_child
- init_raw_mode
- synchronize
- read_command_line_buffer
- clear_subshell_prompt_string
- parse_subshell_prompt_string
- set_prompt_string
- feed_subshell
- pty_open_master
- pty_open_slave
- pty_open_master
- pty_open_slave
- init_subshell_precmd
- subshell_name_quote
- clear_cwd_pipe
- init_subshell
- invoke_subshell
- flush_subshell
- read_subshell_prompt
- do_update_prompt
- exit_subshell
- do_subshell_chdir
- subshell_get_console_attributes
- sigchld_handler
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 #include <config.h>
56
57 #ifndef _GNU_SOURCE
58 #define _GNU_SOURCE 1
59 #endif
60
61 #include <ctype.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <errno.h>
65 #include <string.h>
66 #include <signal.h>
67 #ifdef HAVE_SYS_SELECT_H
68 #include <sys/select.h>
69 #else
70 #include <sys/time.h>
71 #include <unistd.h>
72 #endif
73 #include <sys/types.h>
74 #include <sys/wait.h>
75 #ifdef HAVE_SYS_IOCTL_H
76 #include <sys/ioctl.h>
77 #endif
78 #include <termios.h>
79
80 #ifdef HAVE_STROPTS_H
81 #include <stropts.h>
82 #endif
83
84 #ifdef HAVE_OPENPTY
85
86 #ifdef HAVE_PTY_H
87 #include <pty.h>
88 #endif
89 #ifdef HAVE_UTIL_H
90 #include <util.h>
91 #endif
92
93 #ifdef HAVE_LIBUTIL_H
94 #include <libutil.h>
95 #endif
96 #endif
97
98 #include "lib/global.h"
99
100 #include "lib/fileloc.h"
101 #include "lib/unixcompat.h"
102 #include "lib/tty/tty.h"
103 #include "lib/tty/key.h"
104 #include "lib/vfs/vfs.h"
105 #include "lib/strutil.h"
106 #include "lib/mcconfig.h"
107 #include "lib/util.h"
108 #include "lib/widget.h"
109
110 #include "src/filemanager/layout.h"
111 #include "src/filemanager/command.h"
112
113 #include "subshell.h"
114 #include "internal.h"
115
116
117
118
119
120
121
122 enum subshell_state_enum subshell_state;
123
124
125 GString *subshell_prompt = NULL;
126
127
128
129 gboolean update_subshell_prompt = FALSE;
130
131
132
133 gboolean should_read_new_subshell_prompt;
134
135
136
137 #ifndef WEXITSTATUS
138 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
139 #endif
140
141 #ifndef WIFEXITED
142 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
143 #endif
144
145
146 #define INITIAL_PROMPT_SIZE 10
147
148
149 #define FORK_FAILURE 69
150
151
152 #define PTY_BUFFER_SIZE BUF_MEDIUM
153
154
155
156
157 enum
158 {
159 READ = 0,
160 WRITE = 1
161 };
162
163
164
165 #define SHELL_BUFFER_KEYBINDING "_"
166
167
168
169 #define SHELL_CURSOR_KEYBINDING "+"
170
171
172
173
174
175
176 static char tcsh_fifo[128];
177
178 static int subshell_pty_slave = -1;
179
180
181
182 static const char subshell_switch_key = XCTRL ('o') & 255;
183
184 static const char subshell_switch_key_csi_u[] = "\x1b[111;5u";
185 static const size_t subshell_switch_key_csi_u_len = sizeof(subshell_switch_key_csi_u) - 1;
186
187
188
189 static char pty_buffer[PTY_BUFFER_SIZE] = "\0";
190
191
192 static int subshell_pipe[2];
193
194
195 static int command_buffer_pipe[2];
196
197
198 static pid_t subshell_pid = 1;
199
200
201 static char subshell_cwd[MC_MAXPATHLEN + 1];
202
203
204 static int subshell_ready;
205
206
207 static gboolean use_persistent_buffer = FALSE;
208
209
210 static GString *subshell_prompt_temp_buffer = NULL;
211
212
213
214 static volatile int subshell_alive, subshell_stopped;
215
216
217
218
219 static struct termios shell_mode;
220
221
222
223
224 static struct termios raw_mode;
225
226
227
228
229
230
231
232
233 static ssize_t
234 write_all (int fd, const void *buf, size_t count)
235 {
236 ssize_t written = 0;
237
238 while (count > 0)
239 {
240 ssize_t ret;
241
242 ret = write (fd, (const unsigned char *) buf + written, count);
243 if (ret < 0)
244 {
245 if (errno == EINTR)
246 {
247 if (tty_got_winch ())
248 tty_change_screen_size ();
249
250 continue;
251 }
252
253 return written > 0 ? written : ret;
254 }
255 count -= ret;
256 written += ret;
257 }
258 return written;
259 }
260
261
262
263
264
265
266
267
268
269
270
271 static void
272 init_subshell_child (const char *pty_name)
273 {
274 char *init_file = NULL;
275 pid_t mc_sid;
276
277 (void) pty_name;
278 setsid ();
279
280
281
282
283
284 #ifdef TIOCSCTTY
285 ioctl (subshell_pty_slave, TIOCSCTTY, 0);
286 #endif
287
288
289
290
291 if (tcsetattr (subshell_pty_slave, TCSANOW, &shell_mode))
292 {
293 fprintf (stderr, "Cannot set pty terminal modes: %s\r\n", unix_error_string (errno));
294 my_exit (FORK_FAILURE);
295 }
296
297
298
299 tty_resize (subshell_pty_slave);
300
301
302
303
304
305 {
306 int ret;
307
308 ret = chdir (mc_config_get_home_dir ());
309 (void) ret;
310 }
311
312
313 mc_sid = getsid (0);
314 if (mc_sid != -1)
315 {
316 char sid_str[BUF_SMALL];
317
318 g_snprintf (sid_str, sizeof (sid_str), "MC_SID=%ld", (long) mc_sid);
319 putenv (g_strdup (sid_str));
320 }
321
322 switch (mc_global.shell->type)
323 {
324 case SHELL_BASH:
325
326 init_file = mc_config_get_full_path (MC_BASHRC_FILE);
327
328
329 if (!exist_file (init_file))
330 {
331 g_free (init_file);
332 init_file = g_strdup (".bashrc");
333 }
334
335
336
337 putenv ((char *) "HISTCONTROL=ignoreboth");
338
339
340 {
341 char *input_file;
342
343 input_file = mc_config_get_full_path (MC_INPUTRC_FILE);
344 if (exist_file (input_file))
345 g_setenv ("INPUTRC", input_file, TRUE);
346 g_free (input_file);
347 }
348
349 break;
350
351 case SHELL_ASH_BUSYBOX:
352 case SHELL_DASH:
353
354 init_file = mc_config_get_full_path (MC_ASHRC_FILE);
355
356
357 if (!exist_file (init_file))
358 {
359 g_free (init_file);
360 init_file = g_strdup (".profile");
361 }
362
363
364 g_setenv ("ENV", init_file, TRUE);
365
366 break;
367
368 case SHELL_ZSH:
369
370
371
372
373 if (g_getenv ("ZDOTDIR") != NULL)
374 {
375
376
377 init_file = mc_config_get_full_path (MC_ZSHRC_FILE);
378 if (exist_file (init_file))
379 {
380
381 g_setenv ("ZDOTDIR", mc_config_get_data_path (), TRUE);
382 }
383 }
384 break;
385
386
387 case SHELL_TCSH:
388 case SHELL_FISH:
389 break;
390
391 default:
392 fprintf (stderr, __FILE__ ": unimplemented subshell type %u\r\n", mc_global.shell->type);
393 my_exit (FORK_FAILURE);
394 }
395
396
397
398
399
400
401
402 dup2 (subshell_pty_slave, STDIN_FILENO);
403 dup2 (subshell_pty_slave, STDOUT_FILENO);
404 dup2 (subshell_pty_slave, STDERR_FILENO);
405
406 close (subshell_pipe[READ]);
407
408 if (use_persistent_buffer)
409 close (command_buffer_pipe[READ]);
410
411 close (subshell_pty_slave);
412
413
414
415
416
417 close (mc_global.tty.subshell_pty);
418
419
420
421 switch (mc_global.shell->type)
422 {
423 case SHELL_BASH:
424 execl (mc_global.shell->path, mc_global.shell->path, "-rcfile", init_file, (char *) NULL);
425 break;
426
427 case SHELL_ZSH:
428
429
430 execl (mc_global.shell->path, mc_global.shell->path, "-Z", "-g", (char *) NULL);
431 break;
432
433 case SHELL_FISH:
434 execl (mc_global.shell->path, mc_global.shell->path,
435 "--init-command", "set --global __mc_csi_u 1", (char *) NULL);
436 break;
437
438 case SHELL_ASH_BUSYBOX:
439 case SHELL_DASH:
440 case SHELL_TCSH:
441 execl (mc_global.shell->path, mc_global.shell->path, (char *) NULL);
442 break;
443
444 default:
445 break;
446 }
447
448
449 g_free (init_file);
450 my_exit (FORK_FAILURE);
451 }
452
453
454
455 static void
456 init_raw_mode (void)
457 {
458 static gboolean initialized = FALSE;
459
460
461
462
463
464
465
466 if (!initialized)
467 {
468 tcgetattr (STDOUT_FILENO, &raw_mode);
469 raw_mode.c_lflag &= ~ICANON;
470 raw_mode.c_lflag &= ~ISIG;
471 raw_mode.c_lflag &= ~ECHO;
472 raw_mode.c_iflag &= ~IXON;
473 raw_mode.c_iflag &= ~ICRNL;
474 raw_mode.c_oflag &= ~OPOST;
475 raw_mode.c_cc[VTIME] = 0;
476 raw_mode.c_cc[VMIN] = 1;
477 initialized = TRUE;
478 }
479 }
480
481
482
483
484
485
486
487 static void
488 synchronize (void)
489 {
490 sigset_t sigchld_mask, old_mask;
491
492 sigemptyset (&sigchld_mask);
493 sigaddset (&sigchld_mask, SIGCHLD);
494 sigprocmask (SIG_BLOCK, &sigchld_mask, &old_mask);
495
496
497
498
499
500 sigdelset (&old_mask, SIGCHLD);
501
502
503 while (subshell_alive && !subshell_stopped)
504 sigsuspend (&old_mask);
505
506 if (subshell_state != ACTIVE)
507 {
508
509 tcflush (subshell_pty_slave, TCIFLUSH);
510 }
511
512 subshell_stopped = FALSE;
513 kill (subshell_pid, SIGCONT);
514
515 sigprocmask (SIG_SETMASK, &old_mask, NULL);
516
517 }
518
519
520
521
522
523 static gboolean
524 read_command_line_buffer (gboolean test_mode)
525 {
526 char subshell_command_buffer[BUF_LARGE];
527 char subshell_cursor_buffer[BUF_SMALL];
528
529 fd_set read_set;
530 int i;
531 ssize_t bytes;
532 struct timeval subshell_prompt_timer = { 0, 0 };
533 int command_buffer_length;
534 int command_buffer_char_length;
535 int bash_version;
536 int cursor_position;
537 int maxfdp;
538 int rc;
539
540 if (!use_persistent_buffer)
541 return TRUE;
542
543 FD_ZERO (&read_set);
544 FD_SET (command_buffer_pipe[READ], &read_set);
545 maxfdp = command_buffer_pipe[READ];
546
547
548
549
550
551 while ((rc = select (maxfdp + 1, &read_set, NULL, NULL, &subshell_prompt_timer)) != 0)
552 {
553 if (rc == -1)
554 {
555 if (errno == EINTR)
556 continue;
557
558 return FALSE;
559 }
560
561 if (rc == 1)
562 {
563 bytes = read (command_buffer_pipe[READ], subshell_command_buffer,
564 sizeof (subshell_command_buffer));
565 (void) bytes;
566 }
567 }
568
569
570 write_all (mc_global.tty.subshell_pty, ESC_STR SHELL_BUFFER_KEYBINDING,
571 sizeof (ESC_STR SHELL_CURSOR_KEYBINDING) - 1);
572
573 subshell_prompt_timer.tv_sec = 1;
574 FD_ZERO (&read_set);
575 FD_SET (command_buffer_pipe[READ], &read_set);
576
577 while ((rc = select (maxfdp + 1, &read_set, NULL, NULL, &subshell_prompt_timer)) != 1)
578 {
579 if (rc == -1)
580 {
581 if (errno == EINTR)
582 continue;
583
584 return FALSE;
585 }
586
587 if (rc == 0)
588 return FALSE;
589 }
590
591 bytes =
592 read (command_buffer_pipe[READ], subshell_command_buffer, sizeof (subshell_command_buffer));
593 if (bytes == 0 || bytes == sizeof (subshell_command_buffer))
594 return FALSE;
595
596 command_buffer_char_length = bytes - 1;
597 subshell_command_buffer[command_buffer_char_length] = '\0';
598 command_buffer_length = str_length (subshell_command_buffer);
599
600
601 write_all (mc_global.tty.subshell_pty, ESC_STR SHELL_CURSOR_KEYBINDING,
602 sizeof (ESC_STR SHELL_CURSOR_KEYBINDING) - 1);
603
604 subshell_prompt_timer.tv_sec = 1;
605 subshell_prompt_timer.tv_usec = 0;
606 FD_ZERO (&read_set);
607 FD_SET (command_buffer_pipe[READ], &read_set);
608
609 while ((rc = select (maxfdp + 1, &read_set, NULL, NULL, &subshell_prompt_timer)) != 1)
610 {
611 if (rc == -1)
612 {
613 if (errno == EINTR)
614 continue;
615
616 return FALSE;
617 }
618
619 if (rc == 0)
620 return FALSE;
621 }
622
623 bytes =
624 read (command_buffer_pipe[READ], subshell_cursor_buffer, sizeof (subshell_cursor_buffer));
625 if (bytes == 0)
626 return FALSE;
627
628 subshell_cursor_buffer[bytes - 1] = '\0';
629 if (mc_global.shell->type == SHELL_BASH)
630 {
631 if (sscanf (subshell_cursor_buffer, "%d:%d", &bash_version, &cursor_position) != 2)
632 return FALSE;
633 }
634 else
635 {
636 if (sscanf (subshell_cursor_buffer, "%d", &cursor_position) != 1)
637 return FALSE;
638 bash_version = 1000;
639 }
640
641 if (test_mode)
642 return TRUE;
643
644
645
646 for (i = 0; i < command_buffer_char_length; i++)
647 if ((unsigned char) subshell_command_buffer[i] < 32
648 || (unsigned char) subshell_command_buffer[i] == 127)
649 subshell_command_buffer[i] = ' ';
650
651 input_assign_text (cmdline, "");
652 input_insert (cmdline, subshell_command_buffer, FALSE);
653
654 if (bash_version < 5)
655 {
656
657
658 char *curr, *stop;
659
660 curr = subshell_command_buffer;
661 stop = curr + cursor_position;
662
663 for (cursor_position = 0; curr < stop; cursor_position++)
664 str_next_char_safe (&curr);
665 }
666 if (cursor_position > command_buffer_length)
667 cursor_position = command_buffer_length;
668 cmdline->point = cursor_position;
669
670 flush_subshell (0, VISIBLY);
671
672
673 if (mc_global.shell->type != SHELL_ZSH)
674 {
675
676
677
678
679 if (cursor_position != command_buffer_length)
680 {
681 write_all (mc_global.tty.subshell_pty, "\005", 1);
682 if (flush_subshell (1, VISIBLY) != 1)
683 return FALSE;
684 }
685 }
686
687 if (command_buffer_length > 0)
688 {
689
690 write_all (mc_global.tty.subshell_pty, "\025", 1);
691 if (flush_subshell (1, VISIBLY) != 1)
692 return FALSE;
693 }
694
695 return TRUE;
696 }
697
698
699
700 static void
701 clear_subshell_prompt_string (void)
702 {
703 if (subshell_prompt_temp_buffer != NULL)
704 g_string_set_size (subshell_prompt_temp_buffer, 0);
705 }
706
707
708
709 static void
710 parse_subshell_prompt_string (const char *buffer, int bytes)
711 {
712 int i;
713
714 if (mc_global.mc_run_mode != MC_RUN_FULL)
715 return;
716
717
718 if (subshell_prompt == NULL)
719 subshell_prompt = g_string_sized_new (INITIAL_PROMPT_SIZE);
720 if (subshell_prompt_temp_buffer == NULL)
721 subshell_prompt_temp_buffer = g_string_sized_new (INITIAL_PROMPT_SIZE);
722
723
724 for (i = 0; i < bytes; i++)
725 if (buffer[i] == '\n' || buffer[i] == '\r')
726 g_string_set_size (subshell_prompt_temp_buffer, 0);
727 else if (buffer[i] != '\0')
728 g_string_append_c (subshell_prompt_temp_buffer, buffer[i]);
729 }
730
731
732
733 static void
734 set_prompt_string (void)
735 {
736 if (mc_global.mc_run_mode != MC_RUN_FULL)
737 return;
738
739 if (subshell_prompt_temp_buffer->len != 0)
740 mc_g_string_copy (subshell_prompt, subshell_prompt_temp_buffer);
741
742 setup_cmdline ();
743 }
744
745
746
747
748 static gboolean
749 feed_subshell (int how, gboolean fail_on_error)
750 {
751 fd_set read_set;
752 int bytes;
753 int i;
754
755 struct timeval wtime;
756 struct timeval *wptr;
757
758 should_read_new_subshell_prompt = FALSE;
759
760
761
762 wtime.tv_sec = 10;
763 wtime.tv_usec = 0;
764 wptr = fail_on_error ? &wtime : NULL;
765
766 while (TRUE)
767 {
768 int maxfdp;
769
770 if (!subshell_alive)
771 return FALSE;
772
773
774
775 FD_ZERO (&read_set);
776 FD_SET (mc_global.tty.subshell_pty, &read_set);
777 FD_SET (subshell_pipe[READ], &read_set);
778 maxfdp = MAX (mc_global.tty.subshell_pty, subshell_pipe[READ]);
779 if (how == VISIBLY)
780 {
781 FD_SET (STDIN_FILENO, &read_set);
782 maxfdp = MAX (maxfdp, STDIN_FILENO);
783 }
784
785 if (select (maxfdp + 1, &read_set, NULL, NULL, wptr) == -1)
786 {
787
788 if (errno == EINTR)
789 {
790 if (tty_got_winch ())
791 tty_change_screen_size ();
792
793 continue;
794 }
795 tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
796 fprintf (stderr, "select (FD_SETSIZE, &read_set...): %s\r\n",
797 unix_error_string (errno));
798 exit (EXIT_FAILURE);
799 }
800
801 if (FD_ISSET (mc_global.tty.subshell_pty, &read_set))
802
803
804
805
806
807
808 {
809 bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer));
810
811
812 if (bytes == -1 && errno == EIO && !subshell_alive)
813 return FALSE;
814
815 if (bytes <= 0)
816 {
817 #ifdef PTY_ZEROREAD
818
819 continue;
820 #else
821 tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
822 fprintf (stderr, "read (subshell_pty...): %s\r\n", unix_error_string (errno));
823 exit (EXIT_FAILURE);
824 #endif
825 }
826
827 if (how == VISIBLY)
828 write_all (STDOUT_FILENO, pty_buffer, bytes);
829
830 if (should_read_new_subshell_prompt)
831 parse_subshell_prompt_string (pty_buffer, bytes);
832 }
833
834 else if (FD_ISSET (subshell_pipe[READ], &read_set))
835
836 {
837 bytes = read (subshell_pipe[READ], subshell_cwd, sizeof (subshell_cwd));
838 if (bytes <= 0)
839 {
840 tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
841 fprintf (stderr, "read (subshell_pipe[READ]...): %s\r\n",
842 unix_error_string (errno));
843 exit (EXIT_FAILURE);
844 }
845
846 subshell_cwd[bytes - 1] = '\0';
847
848 synchronize ();
849
850 clear_subshell_prompt_string ();
851 should_read_new_subshell_prompt = TRUE;
852 subshell_ready = TRUE;
853 if (subshell_state == RUNNING_COMMAND)
854 {
855 subshell_state = INACTIVE;
856 return TRUE;
857 }
858 }
859
860 else if (FD_ISSET (STDIN_FILENO, &read_set))
861
862 {
863 should_read_new_subshell_prompt = FALSE;
864 bytes = read (STDIN_FILENO, pty_buffer, sizeof (pty_buffer));
865 if (bytes <= 0)
866 {
867 tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
868 fprintf (stderr,
869 "read (STDIN_FILENO, pty_buffer...): %s\r\n", unix_error_string (errno));
870 exit (EXIT_FAILURE);
871 }
872
873 for (i = 0; i < bytes; ++i)
874 if (pty_buffer[i] == subshell_switch_key ||
875 (subshell_switch_key_csi_u_len <= (size_t) bytes - i &&
876 memcmp (&pty_buffer[i], subshell_switch_key_csi_u,
877 subshell_switch_key_csi_u_len) == 0))
878 {
879 write_all (mc_global.tty.subshell_pty, pty_buffer, i);
880
881 if (subshell_ready)
882 {
883 subshell_state = INACTIVE;
884 set_prompt_string ();
885 if (subshell_ready && !read_command_line_buffer (FALSE))
886 {
887
888 if (mc_global.shell->type != SHELL_FISH)
889 {
890 write_all (mc_global.tty.subshell_pty, "\003", 1);
891 subshell_state = RUNNING_COMMAND;
892 if (feed_subshell (QUIETLY, TRUE))
893 if (read_command_line_buffer (FALSE))
894 return TRUE;
895 }
896 subshell_state = ACTIVE;
897 flush_subshell (0, VISIBLY);
898 input_assign_text (cmdline, "");
899 }
900 }
901
902 return TRUE;
903 }
904
905 write_all (mc_global.tty.subshell_pty, pty_buffer, bytes);
906
907 if (pty_buffer[bytes - 1] == '\n' || pty_buffer[bytes - 1] == '\r')
908 {
909
910
911 if (use_persistent_buffer)
912 input_assign_text (cmdline, "");
913 subshell_ready = FALSE;
914 }
915 }
916 else
917 return FALSE;
918 }
919 }
920
921
922
923
924 #ifndef HAVE_OPENPTY
925
926 #ifdef HAVE_GRANTPT
927
928
929
930 static int
931 pty_open_master (char *pty_name)
932 {
933 char *slave_name;
934 int pty_master;
935
936 #ifdef HAVE_POSIX_OPENPT
937 pty_master = posix_openpt (O_RDWR);
938 #elif defined HAVE_GETPT
939
940 pty_master = getpt ();
941 #elif defined IS_AIX
942 strcpy (pty_name, "/dev/ptc");
943 pty_master = open (pty_name, O_RDWR);
944 #else
945 strcpy (pty_name, "/dev/ptmx");
946 pty_master = open (pty_name, O_RDWR);
947 #endif
948
949 if (pty_master == -1)
950 return -1;
951
952 if (grantpt (pty_master) == -1
953 || unlockpt (pty_master) == -1
954 || !(slave_name = ptsname (pty_master)))
955 {
956 close (pty_master);
957 return -1;
958 }
959 strcpy (pty_name, slave_name);
960 return pty_master;
961 }
962
963
964
965
966 static int
967 pty_open_slave (const char *pty_name)
968 {
969 int pty_slave;
970
971 pty_slave = open (pty_name, O_RDWR);
972 if (pty_slave == -1)
973 {
974 fprintf (stderr, "open (%s, O_RDWR): %s\r\n", pty_name, unix_error_string (errno));
975 return -1;
976 }
977 #if !defined(__osf__) && !defined(__linux__)
978 #if defined (I_FIND) && defined (I_PUSH)
979 if (ioctl (pty_slave, I_FIND, "ptem") == 0)
980 if (ioctl (pty_slave, I_PUSH, "ptem") == -1)
981 {
982 fprintf (stderr, "ioctl (%d, I_PUSH, \"ptem\") failed: %s\r\n",
983 pty_slave, unix_error_string (errno));
984 close (pty_slave);
985 return -1;
986 }
987
988 if (ioctl (pty_slave, I_FIND, "ldterm") == 0)
989 if (ioctl (pty_slave, I_PUSH, "ldterm") == -1)
990 {
991 fprintf (stderr,
992 "ioctl (%d, I_PUSH, \"ldterm\") failed: %s\r\n",
993 pty_slave, unix_error_string (errno));
994 close (pty_slave);
995 return -1;
996 }
997 #if !defined(sgi) && !defined(__sgi)
998 if (ioctl (pty_slave, I_FIND, "ttcompat") == 0)
999 if (ioctl (pty_slave, I_PUSH, "ttcompat") == -1)
1000 {
1001 fprintf (stderr,
1002 "ioctl (%d, I_PUSH, \"ttcompat\") failed: %s\r\n",
1003 pty_slave, unix_error_string (errno));
1004 close (pty_slave);
1005 return -1;
1006 }
1007 #endif
1008 #endif
1009 #endif
1010
1011 fcntl (pty_slave, F_SETFD, FD_CLOEXEC);
1012 return pty_slave;
1013 }
1014
1015 #else
1016
1017
1018
1019 static int
1020 pty_open_master (char *pty_name)
1021 {
1022 int pty_master;
1023 const char *ptr1, *ptr2;
1024
1025 strcpy (pty_name, "/dev/ptyXX");
1026 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1; ++ptr1)
1027 {
1028 pty_name[8] = *ptr1;
1029 for (ptr2 = "0123456789abcdef"; *ptr2 != '\0'; ++ptr2)
1030 {
1031 pty_name[9] = *ptr2;
1032
1033
1034 pty_master = open (pty_name, O_RDWR);
1035 if (pty_master == -1)
1036 {
1037 if (errno == ENOENT)
1038 return -1;
1039 continue;
1040 }
1041 pty_name[5] = 't';
1042 if (access (pty_name, 6) != 0)
1043 {
1044 close (pty_master);
1045 pty_name[5] = 'p';
1046 continue;
1047 }
1048 return pty_master;
1049 }
1050 }
1051 return -1;
1052 }
1053
1054
1055
1056
1057 static int
1058 pty_open_slave (const char *pty_name)
1059 {
1060 int pty_slave;
1061 struct group *group_info;
1062
1063 group_info = getgrnam ("tty");
1064 if (group_info != NULL)
1065 {
1066
1067
1068
1069
1070 }
1071 pty_slave = open (pty_name, O_RDWR);
1072 if (pty_slave == -1)
1073 fprintf (stderr, "open (pty_name, O_RDWR): %s\r\n", pty_name);
1074 fcntl (pty_slave, F_SETFD, FD_CLOEXEC);
1075 return pty_slave;
1076 }
1077 #endif
1078
1079 #endif
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 static void
1093 init_subshell_precmd (char *precmd, size_t buff_size)
1094 {
1095 switch (mc_global.shell->type)
1096 {
1097 case SHELL_BASH:
1098 g_snprintf (precmd, buff_size,
1099 " mc_print_command_buffer () { printf \"%%s\\\\n\" \"$READLINE_LINE\" >&%d; }\n"
1100 " bind -x '\"\\e" SHELL_BUFFER_KEYBINDING "\":\"mc_print_command_buffer\"'\n"
1101 " bind -x '\"\\e" SHELL_CURSOR_KEYBINDING
1102 "\":\"echo $BASH_VERSINFO:$READLINE_POINT >&%d\"'\n"
1103 " if test ${BASH_VERSION%%%%.*} -ge 5 && [[ ${PROMPT_COMMAND@a} == *a* ]] 2> /dev/null; then\n"
1104 " eval \"PROMPT_COMMAND+=( 'pwd>&%d;kill -STOP $$' )\"\n"
1105 " else\n"
1106 " PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND\n}'pwd>&%d;kill -STOP $$'\n"
1107 " fi\n"
1108 "PS1='\\u@\\h:\\w\\$ '\n", command_buffer_pipe[WRITE],
1109 command_buffer_pipe[WRITE], subshell_pipe[WRITE], subshell_pipe[WRITE]);
1110 break;
1111
1112 case SHELL_ASH_BUSYBOX:
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 case SHELL_DASH:
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 g_snprintf (precmd, buff_size,
1154 "precmd() { "
1155 "if [ ! \"${PWD##$HOME}\" ]; then "
1156 "MC_PWD=\"~\"; "
1157 "else "
1158 "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; "
1159 "fi; "
1160 "echo \"$USER@$(hostname -s):$MC_PWD\"; "
1161 "pwd>&%d; "
1162 "kill -STOP $$; "
1163 "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]);
1164 break;
1165
1166 case SHELL_ZSH:
1167 g_snprintf (precmd, buff_size,
1168 " mc_print_command_buffer () { printf \"%%s\\\\n\" \"$BUFFER\" >&%d; }\n"
1169 " zle -N mc_print_command_buffer\n"
1170 " bindkey '^[" SHELL_BUFFER_KEYBINDING "' mc_print_command_buffer\n"
1171 " mc_print_cursor_position () { echo $CURSOR >&%d}\n"
1172 " zle -N mc_print_cursor_position\n"
1173 " bindkey '^[" SHELL_CURSOR_KEYBINDING "' mc_print_cursor_position\n"
1174 " _mc_precmd(){ pwd>&%d;kill -STOP $$ }; precmd_functions+=(_mc_precmd)\n"
1175 "PS1='%%n@%%m:%%~%%# '\n",
1176 command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]);
1177 break;
1178
1179 case SHELL_TCSH:
1180 g_snprintf (precmd, buff_size,
1181 "set echo_style=both; "
1182 "set prompt='%%n@%%m:%%~%%# '; "
1183 "alias precmd 'echo -n;echo $cwd:q >>%s; kill -STOP $$'\n", tcsh_fifo);
1184 break;
1185 case SHELL_FISH:
1186 g_snprintf (precmd, buff_size,
1187 " bind \\e" SHELL_BUFFER_KEYBINDING " 'commandline >&%d';"
1188 "bind \\e" SHELL_CURSOR_KEYBINDING " 'commandline -C >&%d';"
1189 "if not functions -q fish_prompt_mc;"
1190 "functions -e fish_right_prompt;"
1191 "functions -c fish_prompt fish_prompt_mc; end;"
1192 "function fish_prompt;"
1193 "echo \"$PWD\">&%d; fish_prompt_mc; kill -STOP $fish_pid; end\n",
1194 command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]);
1195 break;
1196
1197 default:
1198 break;
1199 }
1200 }
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 static GString *
1223 subshell_name_quote (const char *s)
1224 {
1225 GString *ret;
1226 const char *su, *n;
1227 const char *quote_cmd_start, *quote_cmd_end;
1228
1229 if (mc_global.shell->type == SHELL_FISH)
1230 {
1231 quote_cmd_start = "(printf '%b' '";
1232 quote_cmd_end = "')";
1233 }
1234
1235
1236
1237
1238
1239
1240
1241 else
1242 {
1243 quote_cmd_start = "\"`printf '%b' '";
1244 quote_cmd_end = "'`\"";
1245 }
1246
1247 ret = g_string_sized_new (64);
1248
1249
1250 if (s[0] == '-')
1251 g_string_append (ret, "./");
1252
1253
1254 g_string_append (ret, quote_cmd_start);
1255
1256
1257
1258
1259
1260
1261 for (su = s; su[0] != '\0'; su = n)
1262 {
1263 n = str_cget_next_char_safe (su);
1264
1265 if (str_isalnum (su))
1266 g_string_append_len (ret, su, n - su);
1267 else
1268 {
1269 int c;
1270
1271 for (c = 0; c < n - su; c++)
1272 g_string_append_printf (ret, "\\0%03o", (unsigned char) su[c]);
1273 }
1274 }
1275
1276 g_string_append (ret, quote_cmd_end);
1277
1278 return ret;
1279 }
1280
1281
1282
1283
1284
1285
1286
1287 static void
1288 clear_cwd_pipe (void)
1289 {
1290 fd_set read_set;
1291 struct timeval wtime = { 0, 0 };
1292 int maxfdp;
1293
1294 FD_ZERO (&read_set);
1295 FD_SET (subshell_pipe[READ], &read_set);
1296 maxfdp = subshell_pipe[READ];
1297
1298 if (select (maxfdp + 1, &read_set, NULL, NULL, &wtime) > 0
1299 && FD_ISSET (subshell_pipe[READ], &read_set))
1300 {
1301 if (read (subshell_pipe[READ], subshell_cwd, sizeof (subshell_cwd)) <= 0)
1302 {
1303 tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode);
1304 fprintf (stderr, "read (subshell_pipe[READ]...): %s\r\n", unix_error_string (errno));
1305 exit (EXIT_FAILURE);
1306 }
1307
1308 synchronize ();
1309 }
1310 }
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326 void
1327 init_subshell (void)
1328 {
1329
1330 static char pty_name[BUF_SMALL];
1331
1332 char precmd[BUF_MEDIUM];
1333
1334
1335
1336 init_raw_mode ();
1337
1338 if (mc_global.tty.subshell_pty == 0)
1339 {
1340 if (mc_global.shell->type == SHELL_NONE)
1341 return;
1342
1343
1344
1345
1346
1347 #ifdef HAVE_OPENPTY
1348 if (openpty (&mc_global.tty.subshell_pty, &subshell_pty_slave, NULL, NULL, NULL))
1349 {
1350 fprintf (stderr, "Cannot open master and slave sides of pty: %s\n",
1351 unix_error_string (errno));
1352 mc_global.tty.use_subshell = FALSE;
1353 return;
1354 }
1355 #else
1356 mc_global.tty.subshell_pty = pty_open_master (pty_name);
1357 if (mc_global.tty.subshell_pty == -1)
1358 {
1359 fprintf (stderr, "Cannot open master side of pty: %s\r\n", unix_error_string (errno));
1360 mc_global.tty.use_subshell = FALSE;
1361 return;
1362 }
1363 subshell_pty_slave = pty_open_slave (pty_name);
1364 if (subshell_pty_slave == -1)
1365 {
1366 fprintf (stderr, "Cannot open slave side of pty %s: %s\r\n",
1367 pty_name, unix_error_string (errno));
1368 mc_global.tty.use_subshell = FALSE;
1369 return;
1370 }
1371 #endif
1372
1373
1374
1375 if (mc_global.shell->type == SHELL_TCSH)
1376 {
1377 g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d",
1378 mc_tmpdir (), (int) getpid ());
1379 if (mkfifo (tcsh_fifo, 0600) == -1)
1380 {
1381 fprintf (stderr, "mkfifo(%s) failed: %s\r\n", tcsh_fifo, unix_error_string (errno));
1382 mc_global.tty.use_subshell = FALSE;
1383 return;
1384 }
1385
1386
1387
1388 if ((subshell_pipe[READ] = open (tcsh_fifo, O_RDWR)) == -1
1389 || (subshell_pipe[WRITE] = open (tcsh_fifo, O_RDWR)) == -1)
1390 {
1391 fprintf (stderr, _("Cannot open named pipe %s\n"), tcsh_fifo);
1392 perror (__FILE__ ": open");
1393 mc_global.tty.use_subshell = FALSE;
1394 return;
1395 }
1396 }
1397 else if (pipe (subshell_pipe) != 0)
1398 {
1399 perror (__FILE__ ": couldn't create pipe");
1400 mc_global.tty.use_subshell = FALSE;
1401 return;
1402 }
1403
1404 if (mc_global.mc_run_mode == MC_RUN_FULL &&
1405 (mc_global.shell->type == SHELL_BASH || mc_global.shell->type == SHELL_ZSH
1406 || mc_global.shell->type == SHELL_FISH))
1407 use_persistent_buffer = TRUE;
1408 if (use_persistent_buffer && pipe (command_buffer_pipe) != 0)
1409 {
1410 perror (__FILE__ ": couldn't create pipe");
1411 mc_global.tty.use_subshell = FALSE;
1412 return;
1413 }
1414 }
1415
1416
1417
1418 subshell_alive = TRUE;
1419 subshell_stopped = FALSE;
1420 subshell_pid = my_fork ();
1421
1422 if (subshell_pid == -1)
1423 {
1424 fprintf (stderr, "Cannot spawn the subshell process: %s\r\n", unix_error_string (errno));
1425
1426
1427 exit (EXIT_FAILURE);
1428 }
1429
1430 if (subshell_pid == 0)
1431 {
1432
1433 init_subshell_child (pty_name);
1434 }
1435
1436 init_subshell_precmd (precmd, BUF_MEDIUM);
1437
1438 write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd));
1439
1440
1441
1442 subshell_state = RUNNING_COMMAND;
1443 tty_enable_interrupt_key ();
1444 if (!feed_subshell (QUIETLY, TRUE))
1445 mc_global.tty.use_subshell = FALSE;
1446 tty_disable_interrupt_key ();
1447 if (!subshell_alive)
1448 mc_global.tty.use_subshell = FALSE;
1449
1450
1451
1452
1453
1454 if (use_persistent_buffer && !read_command_line_buffer (TRUE))
1455 use_persistent_buffer = FALSE;
1456 }
1457
1458
1459
1460 int
1461 invoke_subshell (const char *command, int how, vfs_path_t **new_dir_vpath)
1462 {
1463
1464 tcsetattr (STDOUT_FILENO, TCSANOW, &raw_mode);
1465
1466
1467 if (new_dir_vpath != NULL)
1468 do_subshell_chdir (subshell_get_cwd (), TRUE);
1469
1470 if (command == NULL)
1471 {
1472 if (subshell_state == INACTIVE)
1473 {
1474 subshell_state = ACTIVE;
1475
1476
1477 if (subshell_ready && mc_global.mc_run_mode == MC_RUN_FULL)
1478 write_all (mc_global.tty.subshell_pty, " \b", 2);
1479
1480 if (use_persistent_buffer)
1481 {
1482 const char *s;
1483 size_t i;
1484 int pos;
1485
1486 s = input_get_ctext (cmdline);
1487
1488
1489
1490 for (i = 0; i < cmdline->buffer->len; i++)
1491 if ((unsigned char) s[i] < 32 || (unsigned char) s[i] == 127)
1492 g_string_overwrite_len (cmdline->buffer, i, " ", 1);
1493
1494
1495 write_all (mc_global.tty.subshell_pty, s, cmdline->buffer->len);
1496
1497
1498 pos = str_length (s) - cmdline->point;
1499 for (i = 0; i < (size_t) pos; i++)
1500 write_all (mc_global.tty.subshell_pty, ESC_STR "[D", 3);
1501 }
1502 }
1503 }
1504 else
1505 {
1506
1507
1508
1509
1510 if (use_persistent_buffer)
1511 clear_cwd_pipe ();
1512 else
1513 {
1514
1515
1516 if (mc_global.shell->type != SHELL_FISH)
1517 {
1518 write_all (mc_global.tty.subshell_pty, "\003", 1);
1519 subshell_state = RUNNING_COMMAND;
1520 feed_subshell (QUIETLY, FALSE);
1521 }
1522 }
1523
1524 if (how == QUIETLY)
1525 write_all (mc_global.tty.subshell_pty, " ", 1);
1526
1527 write_all (mc_global.tty.subshell_pty, command, strlen (command));
1528 write_all (mc_global.tty.subshell_pty, "\n", 1);
1529 subshell_state = RUNNING_COMMAND;
1530 subshell_ready = FALSE;
1531 }
1532
1533 feed_subshell (how, FALSE);
1534
1535 if (new_dir_vpath != NULL && subshell_alive)
1536 {
1537 const char *pcwd;
1538
1539 pcwd = vfs_translate_path (vfs_path_as_str (subshell_get_cwd ()));
1540 if (strcmp (subshell_cwd, pcwd) != 0)
1541 *new_dir_vpath = vfs_path_from_str (subshell_cwd);
1542 }
1543
1544
1545 while (!subshell_alive && subshell_get_mainloop_quit () == 0 && mc_global.tty.use_subshell)
1546 init_subshell ();
1547
1548 return subshell_get_mainloop_quit ();
1549 }
1550
1551
1552
1553 gboolean
1554 flush_subshell (int max_wait_length, int how)
1555 {
1556 int rc = 0;
1557 ssize_t bytes = 0;
1558 struct timeval timeleft = { 0, 0 };
1559 gboolean return_value = FALSE;
1560 fd_set tmp;
1561
1562 timeleft.tv_sec = max_wait_length;
1563 FD_ZERO (&tmp);
1564 FD_SET (mc_global.tty.subshell_pty, &tmp);
1565
1566 while (subshell_alive
1567 && (rc = select (mc_global.tty.subshell_pty + 1, &tmp, NULL, NULL, &timeleft)) != 0)
1568 {
1569
1570 if (rc == -1)
1571 {
1572 if (errno == EINTR)
1573 {
1574 if (tty_got_winch ())
1575 tty_change_screen_size ();
1576
1577 continue;
1578 }
1579
1580 fprintf (stderr, "select (FD_SETSIZE, &tmp...): %s\r\n", unix_error_string (errno));
1581 exit (EXIT_FAILURE);
1582 }
1583
1584 return_value = TRUE;
1585 timeleft.tv_sec = 0;
1586 timeleft.tv_usec = 0;
1587
1588 bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer));
1589 if (how == VISIBLY)
1590 write_all (STDOUT_FILENO, pty_buffer, bytes);
1591 }
1592
1593 return return_value;
1594 }
1595
1596
1597
1598 gboolean
1599 read_subshell_prompt (void)
1600 {
1601 int rc = 0;
1602 ssize_t bytes = 0;
1603 struct timeval timeleft = { 0, 0 };
1604 gboolean got_new_prompt = FALSE;
1605
1606 fd_set tmp;
1607 FD_ZERO (&tmp);
1608 FD_SET (mc_global.tty.subshell_pty, &tmp);
1609
1610 while (subshell_alive
1611 && (rc = select (mc_global.tty.subshell_pty + 1, &tmp, NULL, NULL, &timeleft)) != 0)
1612 {
1613
1614 if (rc == -1)
1615 {
1616 if (errno == EINTR)
1617 {
1618 if (tty_got_winch ())
1619 tty_change_screen_size ();
1620
1621 continue;
1622 }
1623
1624 fprintf (stderr, "select (FD_SETSIZE, &tmp...): %s\r\n", unix_error_string (errno));
1625 exit (EXIT_FAILURE);
1626 }
1627
1628 bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer));
1629
1630 parse_subshell_prompt_string (pty_buffer, bytes);
1631 got_new_prompt = TRUE;
1632 }
1633
1634 if (got_new_prompt)
1635 set_prompt_string ();
1636
1637 return (rc != 0 || bytes != 0);
1638 }
1639
1640
1641
1642 void
1643 do_update_prompt (void)
1644 {
1645 if (update_subshell_prompt)
1646 {
1647 if (subshell_prompt != NULL)
1648 {
1649 printf ("\r\n%s", subshell_prompt->str);
1650 fflush (stdout);
1651 }
1652 update_subshell_prompt = FALSE;
1653 }
1654 }
1655
1656
1657
1658 gboolean
1659 exit_subshell (void)
1660 {
1661 gboolean subshell_quit = TRUE;
1662
1663 if (subshell_state != INACTIVE && subshell_alive)
1664 subshell_quit =
1665 query_dialog (_("Warning"),
1666 _("The shell is still active. Quit anyway?"),
1667 D_NORMAL, 2, _("&Yes"), _("&No")) == 0;
1668
1669 if (subshell_quit)
1670 {
1671 if (mc_global.shell->type == SHELL_TCSH)
1672 {
1673 if (unlink (tcsh_fifo) == -1)
1674 fprintf (stderr, "Cannot remove named pipe %s: %s\r\n",
1675 tcsh_fifo, unix_error_string (errno));
1676 }
1677
1678 if (subshell_prompt != NULL)
1679 {
1680 g_string_free (subshell_prompt, TRUE);
1681 subshell_prompt = NULL;
1682 }
1683
1684 if (subshell_prompt_temp_buffer != NULL)
1685 {
1686 g_string_free (subshell_prompt_temp_buffer, TRUE);
1687 subshell_prompt_temp_buffer = NULL;
1688 }
1689
1690 pty_buffer[0] = '\0';
1691 }
1692
1693 return subshell_quit;
1694 }
1695
1696
1697
1698
1699 void
1700 do_subshell_chdir (const vfs_path_t *vpath, gboolean update_prompt)
1701 {
1702 char *pcwd;
1703
1704 pcwd = vfs_path_to_str_flags (subshell_get_cwd (), 0, VPF_RECODE);
1705
1706 if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0))
1707 {
1708
1709
1710
1711
1712 if (update_prompt)
1713 do_update_prompt ();
1714 g_free (pcwd);
1715 return;
1716 }
1717
1718
1719
1720 if (!use_persistent_buffer)
1721 {
1722 write_all (mc_global.tty.subshell_pty, "\003", 1);
1723 subshell_state = RUNNING_COMMAND;
1724 if (mc_global.shell->type != SHELL_FISH)
1725 if (!feed_subshell (QUIETLY, TRUE))
1726 {
1727 subshell_state = ACTIVE;
1728 return;
1729 }
1730 }
1731
1732
1733
1734
1735
1736 if (mc_global.shell->type == SHELL_FISH)
1737 {
1738 write_all (mc_global.tty.subshell_pty, "\n", 1);
1739 subshell_state = RUNNING_COMMAND;
1740 feed_subshell (QUIETLY, TRUE);
1741 }
1742
1743
1744
1745 write_all (mc_global.tty.subshell_pty, " cd ", 4);
1746
1747 if (vpath == NULL)
1748 write_all (mc_global.tty.subshell_pty, "/", 1);
1749 else
1750 {
1751 const char *translate;
1752
1753 translate = vfs_translate_path (vfs_path_as_str (vpath));
1754 if (translate == NULL)
1755 write_all (mc_global.tty.subshell_pty, ".", 1);
1756 else
1757 {
1758 GString *temp;
1759
1760 temp = subshell_name_quote (translate);
1761 write_all (mc_global.tty.subshell_pty, temp->str, temp->len);
1762 g_string_free (temp, TRUE);
1763 }
1764 }
1765
1766 write_all (mc_global.tty.subshell_pty, "\n", 1);
1767
1768 subshell_state = RUNNING_COMMAND;
1769 if (!feed_subshell (QUIETLY, TRUE))
1770 {
1771 subshell_state = ACTIVE;
1772 return;
1773 }
1774
1775 if (subshell_alive)
1776 {
1777 gboolean bPathNotEq;
1778
1779 bPathNotEq = strcmp (subshell_cwd, pcwd) != 0;
1780
1781 if (bPathNotEq && mc_global.shell->type == SHELL_TCSH)
1782 {
1783 char rp_subshell_cwd[PATH_MAX];
1784 char rp_current_panel_cwd[PATH_MAX];
1785 char *p_subshell_cwd, *p_current_panel_cwd;
1786
1787 p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd);
1788 p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd);
1789
1790 if (p_subshell_cwd == NULL)
1791 p_subshell_cwd = subshell_cwd;
1792 if (p_current_panel_cwd == NULL)
1793 p_current_panel_cwd = pcwd;
1794 bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd) != 0;
1795 }
1796
1797 if (bPathNotEq && !DIR_IS_DOT (pcwd))
1798 {
1799 char *cwd;
1800
1801 cwd = vfs_path_to_str_flags (subshell_get_cwd (), 0, VPF_STRIP_PASSWORD);
1802 vfs_print_message (_("Warning: Cannot change to %s.\n"), cwd);
1803 g_free (cwd);
1804 }
1805 }
1806
1807
1808 if (mc_global.shell->type == SHELL_ZSH || mc_global.shell->type == SHELL_FISH)
1809 {
1810
1811
1812
1813
1814
1815
1816
1817 write_all (mc_global.tty.subshell_pty, " \n", 2);
1818 subshell_state = RUNNING_COMMAND;
1819 feed_subshell (QUIETLY, TRUE);
1820 }
1821
1822 update_subshell_prompt = FALSE;
1823
1824 g_free (pcwd);
1825
1826
1827 }
1828
1829
1830
1831 void
1832 subshell_get_console_attributes (void)
1833 {
1834
1835
1836 if (tcgetattr (STDOUT_FILENO, &shell_mode))
1837 {
1838 fprintf (stderr, "Cannot get terminal settings: %s\r\n", unix_error_string (errno));
1839 mc_global.tty.use_subshell = FALSE;
1840 }
1841 }
1842
1843
1844
1845
1846
1847
1848 void
1849 sigchld_handler (int sig)
1850 {
1851 int status;
1852 pid_t pid;
1853
1854 (void) sig;
1855
1856 pid = waitpid (subshell_pid, &status, WUNTRACED | WNOHANG);
1857
1858 if (pid == subshell_pid)
1859 {
1860
1861
1862 if (WIFSTOPPED (status))
1863 {
1864 if (WSTOPSIG (status) == SIGSTOP)
1865 {
1866
1867 subshell_stopped = TRUE;
1868 }
1869 else
1870 {
1871
1872 kill (subshell_pid, SIGCONT);
1873 }
1874 }
1875 else
1876 {
1877
1878 subshell_alive = FALSE;
1879 delete_select_channel (mc_global.tty.subshell_pty);
1880 if (WIFEXITED (status) && WEXITSTATUS (status) != FORK_FAILURE)
1881 {
1882 int subshell_quit;
1883 subshell_quit = subshell_get_mainloop_quit () | SUBSHELL_EXIT;
1884 subshell_set_mainloop_quit (subshell_quit);
1885 }
1886 }
1887 }
1888 subshell_handle_cons_saver ();
1889
1890
1891 }
1892
1893