diff --git a/src/command.c b/src/command.c
index e608bf0..81cbc5c 100644
a
|
b
|
enter (WInput *cmdline) |
229 | 229 | #ifdef HAVE_SUBSHELL_SUPPORT |
230 | 230 | /* Check this early before we clean command line |
231 | 231 | * (will be checked again by shell_execute) */ |
232 | | if (use_subshell && subshell_state != INACTIVE) { |
| 232 | if (use_subshell && subshell_state != INACTIVE |
| 233 | && subshell_state != ACTIVE2) { |
233 | 234 | message (1, MSG_ERROR, |
234 | 235 | _(" The shell is already running a command ")); |
235 | 236 | return MSG_NOT_HANDLED; |
diff --git a/src/execute.c b/src/execute.c
index eb31cac..07e5f34 100644
a
|
b
|
do_execute (const char *shell, const char *command, int flags) |
131 | 131 | && !console_flag)) && !quit |
132 | 132 | #ifdef HAVE_SUBSHELL_SUPPORT |
133 | 133 | && subshell_state != RUNNING_COMMAND |
| 134 | && subshell_state != RUNNING_COMMAND2 |
134 | 135 | #endif /* HAVE_SUBSHELL_SUPPORT */ |
135 | 136 | ) { |
136 | 137 | printf (_("Press any key to continue...")); |
… |
… |
shell_execute (const char *command, int flags) |
186 | 187 | |
187 | 188 | #ifdef HAVE_SUBSHELL_SUPPORT |
188 | 189 | if (use_subshell) |
189 | | if (subshell_state == INACTIVE) |
| 190 | if (subshell_state == INACTIVE || subshell_state == ACTIVE2) |
190 | 191 | do_execute (shell, cmd ? cmd : command, flags | EXECUTE_AS_SHELL); |
191 | 192 | else |
192 | 193 | message (1, MSG_ERROR, |
diff --git a/src/main.c b/src/main.c
index db26945..9f68881 100644
a
|
b
|
void |
436 | 436 | do_update_prompt (void) |
437 | 437 | { |
438 | 438 | if (update_prompt) { |
439 | | printf ("%s", subshell_prompt); |
| 439 | /* FIXME: quick hack to eliminate 'stacked prompts bug'. |
| 440 | Actually should be done with ncurses. */ |
| 441 | printf ("\033[1K\033[1G%s", subshell_prompt); |
440 | 442 | fflush (stdout); |
441 | 443 | update_prompt = 0; |
442 | 444 | } |
diff --git a/src/subshell.c b/src/subshell.c
index 8d98da5..e84527e 100644
a
|
b
|
enum {READ=0, WRITE=1}; |
123 | 123 | static char *pty_buffer; /* For reading/writing on the subshell's pty */ |
124 | 124 | static int pty_buffer_size; /* The buffer grows as needed */ |
125 | 125 | static int subshell_pipe[2]; /* To pass CWD info from the subshell to MC */ |
| 126 | static int subshell_pipe2[2]; /* To indicate subshell command run */ |
126 | 127 | static pid_t subshell_pid = 1; /* The subshell's process ID */ |
127 | 128 | static char subshell_cwd[MC_MAXPATHLEN+1]; /* One extra char for final '\n' */ |
128 | 129 | |
129 | 130 | /* Subshell type (gleaned from the SHELL environment variable, if available) */ |
130 | | static enum {BASH, TCSH, ZSH} subshell_type; |
| 131 | enum subshell_type_enum subshell_type; |
131 | 132 | |
132 | 133 | /* Flag to indicate whether the subshell is ready for next command */ |
133 | 134 | static int subshell_ready; |
… |
… |
init_subshell_child (const char *pty_name) |
282 | 283 | |
283 | 284 | switch (subshell_type) { |
284 | 285 | case BASH: |
| 286 | close (subshell_pipe[READ]); |
285 | 287 | execl (shell, "bash", "-rcfile", init_file, (char *) NULL); |
286 | 288 | break; |
287 | 289 | |
… |
… |
init_subshell (void) |
439 | 441 | use_subshell = FALSE; |
440 | 442 | return; |
441 | 443 | } |
442 | | } else /* subshell_type is BASH or ZSH */ if (pipe (subshell_pipe)) { |
443 | | perror (__FILE__": couldn't create pipe"); |
444 | | use_subshell = FALSE; |
445 | | return; |
446 | | } |
| 444 | } else /* subshell_type is BASH or ZSH */ { |
| 445 | if (pipe (subshell_pipe) || pipe (subshell_pipe2)) { |
| 446 | perror (__FILE__": couldn't create pipe"); |
| 447 | use_subshell = FALSE; |
| 448 | return; |
| 449 | } |
| 450 | } |
447 | 451 | } |
448 | 452 | |
449 | 453 | /* Fork the subshell */ |
… |
… |
init_subshell (void) |
469 | 473 | switch (subshell_type) { |
470 | 474 | case BASH: |
471 | 475 | g_snprintf (precmd, sizeof (precmd), |
472 | | " PROMPT_COMMAND='pwd>&%d;kill -STOP $$'\n", |
473 | | subshell_pipe[WRITE]); |
| 476 | " PROMPT_COMMAND='pwd>&%d;kill -STOP $$';" |
| 477 | "trap '[ \"$BASH_COMMAND\" != \"kill -STOP \\$\\$\" ] && echo $BASH_COMMAND>&%d' DEBUG\n", |
| 478 | subshell_pipe[WRITE], |
| 479 | subshell_pipe2[WRITE]); |
474 | 480 | break; |
475 | 481 | |
476 | 482 | case ZSH: |
… |
… |
int invoke_subshell (const char *command, int how, char **new_dir) |
548 | 554 | } |
549 | 555 | else /* MC has passed us a user command */ |
550 | 556 | { |
| 557 | if (subshell_state == ACTIVE2) { |
| 558 | /* Send Ctrl-C if something was typed on subshell prompt */ |
| 559 | subshell_state = RUNNING_COMMAND; |
| 560 | write_all (subshell_pty, "\x3", 1); |
| 561 | feed_subshell (how, FALSE); |
| 562 | } |
| 563 | |
551 | 564 | if (how == QUIETLY) |
552 | 565 | write_all (subshell_pty, " ", 1); |
553 | 566 | /* FIXME: if command is long (>8KB ?) we go comma */ |
554 | 567 | write_all (subshell_pty, command, strlen (command)); |
555 | 568 | write_all (subshell_pty, "\n", 1); |
556 | | subshell_state = RUNNING_COMMAND; |
557 | | subshell_ready = FALSE; |
| 569 | subshell_state = RUNNING_COMMAND; |
| 570 | subshell_ready = FALSE; |
558 | 571 | } |
559 | 572 | |
560 | 573 | feed_subshell (how, FALSE); |
… |
… |
subshell_name_quote (const char *s) |
743 | 756 | void |
744 | 757 | do_subshell_chdir (const char *directory, int do_update, int reset_prompt) |
745 | 758 | { |
746 | | if (! |
| 759 | if (subshell_state == ACTIVE2) { |
| 760 | /* Send Ctrl-C if something was typed on subshell prompt */ |
| 761 | subshell_state = RUNNING_COMMAND; |
| 762 | write_all (subshell_pty, "\x3", 1); |
| 763 | /* FIXME: command prompt with old typed characters should be visible */ |
| 764 | feed_subshell (VISIBLY, FALSE); |
| 765 | } else if (! |
747 | 766 | (subshell_state == INACTIVE |
748 | 767 | && strcmp (subshell_cwd, current_panel->cwd))) { |
749 | 768 | /* We have to repaint the subshell prompt if we read it from |
… |
… |
do_subshell_chdir (const char *directory, int do_update, int reset_prompt) |
803 | 822 | } |
804 | 823 | |
805 | 824 | if (reset_prompt) |
806 | | prompt_pos = 0; |
| 825 | prompt_pos = 0; |
807 | 826 | update_prompt = FALSE; |
808 | 827 | /* Make sure that MC never stores the CWD in a silly format */ |
809 | 828 | /* like /usr////lib/../bin, or the strcmp() above will fail */ |
… |
… |
feed_subshell (int how, int fail_on_error) |
902 | 921 | FD_ZERO (&read_set); |
903 | 922 | FD_SET (subshell_pty, &read_set); |
904 | 923 | FD_SET (subshell_pipe[READ], &read_set); |
905 | | maxfdp = max (subshell_pty, subshell_pipe[READ]); |
| 924 | FD_SET (subshell_pipe2[READ], &read_set); |
| 925 | maxfdp = max(max (subshell_pty, subshell_pipe[READ]), subshell_pipe2[READ]); |
906 | 926 | if (how == VISIBLY) { |
907 | 927 | FD_SET (STDIN_FILENO, &read_set); |
908 | 928 | maxfdp = max (maxfdp, STDIN_FILENO); |
… |
… |
feed_subshell (int how, int fail_on_error) |
918 | 938 | unix_error_string (errno)); |
919 | 939 | exit (1); |
920 | 940 | } |
921 | | |
922 | | if (FD_ISSET (subshell_pty, &read_set)) |
| 941 | |
| 942 | if (subshell_type == BASH |
| 943 | && FD_ISSET (subshell_pipe2[READ], &read_set)) { |
| 944 | char buf[255]; |
| 945 | int s = read (subshell_pipe2[READ], buf, 255); |
| 946 | if (0 >= s) { |
| 947 | tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); |
| 948 | fprintf (stderr, |
| 949 | "read (subshell_pipe2[READ], buf...): %s\r\n", |
| 950 | unix_error_string (errno)); |
| 951 | exit (1); |
| 952 | } |
| 953 | if (subshell_state == ACTIVE) { |
| 954 | subshell_state = RUNNING_COMMAND2; |
| 955 | subshell_ready = FALSE; |
| 956 | } |
| 957 | } |
| 958 | |
| 959 | else if (FD_ISSET (subshell_pty, &read_set)) |
923 | 960 | /* Read from the subshell, write to stdout */ |
924 | 961 | |
925 | 962 | /* This loop improves performance by reducing context switches |
… |
… |
feed_subshell (int how, int fail_on_error) |
965 | 1002 | subshell_ready = TRUE; |
966 | 1003 | if (subshell_state == RUNNING_COMMAND) { |
967 | 1004 | subshell_state = INACTIVE; |
968 | | return 1; |
| 1005 | return TRUE; |
969 | 1006 | } |
| 1007 | if (subshell_state == RUNNING_COMMAND2 || |
| 1008 | subshell_state == ACTIVE2) |
| 1009 | { |
| 1010 | subshell_state = INACTIVE; |
| 1011 | } |
970 | 1012 | } |
971 | 1013 | |
972 | 1014 | else if (FD_ISSET (STDIN_FILENO, &read_set)) |
… |
… |
feed_subshell (int how, int fail_on_error) |
990 | 1032 | } |
991 | 1033 | |
992 | 1034 | write_all (subshell_pty, pty_buffer, bytes); |
993 | | subshell_ready = FALSE; |
| 1035 | subshell_ready = FALSE; |
| 1036 | if (subshell_type == BASH) |
| 1037 | subshell_state = ACTIVE2; |
994 | 1038 | } else { |
995 | 1039 | return FALSE; |
996 | 1040 | } |
diff --git a/src/subshell.h b/src/subshell.h
index 072871d..9c874e2 100644
a
|
b
|
extern int use_subshell; |
14 | 14 | extern int subshell_pty; |
15 | 15 | |
16 | 16 | /* State of the subshell; see subshell.c for an explanation */ |
17 | | enum subshell_state_enum {INACTIVE, ACTIVE, RUNNING_COMMAND}; |
| 17 | enum subshell_state_enum {INACTIVE, ACTIVE, RUNNING_COMMAND, ACTIVE2, RUNNING_COMMAND2}; |
18 | 18 | extern enum subshell_state_enum subshell_state; |
19 | 19 | |
| 20 | enum subshell_type_enum {BASH, TCSH, ZSH}; |
| 21 | extern enum subshell_type_enum subshell_type; |
| 22 | |
20 | 23 | /* Holds the latest prompt captured from the subshell */ |
21 | 24 | extern char *subshell_prompt; |
22 | 25 | |