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