Ticket #4114: persistent_subshell_command_buffer2.patch
File persistent_subshell_command_buffer2.patch, 24.1 KB (added by congest, 4 years ago) |
---|
-
src/execute.c
diff --git a/src/execute.c b/src/execute.c index d9b306e67..f35c53d94 100644
a b toggle_subshell (void) 551 551 { 552 552 if (mc_global.mc_run_mode == MC_RUN_FULL) 553 553 { 554 do_load_prompt ();555 554 if (new_dir_vpath != NULL) 556 555 do_possible_cd (new_dir_vpath); 557 556 } -
src/filemanager/layout.c
diff --git a/src/filemanager/layout.c b/src/filemanager/layout.c index dfffa96f5..56318d99d 100644
a b load_prompt (int fd, void *unused) 1497 1497 { 1498 1498 (void) fd; 1499 1499 (void) unused; 1500 1501 do_load_prompt (); 1500 if (should_read_new_subshell_prompt) 1501 do_load_prompt (); 1502 else 1503 flush_subshell(0, QUIETLY); 1502 1504 return 0; 1503 1505 } 1504 1506 #endif /* ENABLE_SUBSHELL */ -
src/subshell/common.c
diff --git a/src/subshell/common.c b/src/subshell/common.c index 06699233c..eb794251f 100644
a b 105 105 #include "lib/util.h" 106 106 #include "lib/widget.h" 107 107 108 #include "src/filemanager/layout.h" /* setup_cmdline() */ 109 #include "src/filemanager/command.h" /* cmdline */ 110 108 111 #include "subshell.h" 109 112 #include "internal.h" 110 113 … … GString *subshell_prompt = NULL; 123 126 /* We need to paint it after CONSOLE_RESTORE, see: load_prompt */ 124 127 gboolean update_subshell_prompt = FALSE; 125 128 129 /* If set, then a command has just finished executing, and we need */ 130 /* to be on the lookout for a new prompt string from the subshell. */ 131 gboolean should_read_new_subshell_prompt; 132 126 133 /*** file scope macro definitions ****************************************************************/ 127 134 128 135 #ifndef WEXITSTATUS … … enum 151 158 WRITE = 1 152 159 }; 153 160 161 /* This is the keybinding that is sent to the shell, to make the shell send us the contents of 162 * the current command buffer. */ 163 #define SHELL_BUFFER_KEYBINDING "[98~" 164 165 /* This is the keybinding that is sent to the shell, to make the shell send us the location of 166 * the cursor. */ 167 #define SHELL_CURSOR_KEYBINDING "[99~" 168 154 169 /*** file scope variables ************************************************************************/ 155 170 156 171 /* tcsh closes all non-standard file descriptors, so we have to use a pipe */ … … static char pty_buffer[PTY_BUFFER_SIZE] = "\0"; 169 184 /* To pass CWD info from the subshell to MC */ 170 185 static int subshell_pipe[2]; 171 186 187 /* To pass command buffer info from the subshell to MC */ 188 static int command_buffer_pipe[2]; 189 172 190 /* The subshell's process ID */ 173 191 static pid_t subshell_pid = 1; 174 192 … … static char subshell_cwd[MC_MAXPATHLEN + 1]; 178 196 /* Flag to indicate whether the subshell is ready for next command */ 179 197 static int subshell_ready; 180 198 199 /* Flag to indicate if the contents of the subshell command line need to be cleared before */ 200 /* executing a command. This should only end up set to true if there is some sort of error.*/ 201 /* This allows us to recover gracefully from an error.*/ 202 static gboolean subshell_should_clear_command_line; 203 204 /* This is the local variable where the subshell prompt is stored while we are working on it. */ 205 static GString *subshell_prompt_temp_buffer = NULL; 206 181 207 /* The following two flags can be changed by the SIGCHLD handler. This is */ 182 208 /* OK, because the 'int' type is updated atomically on all known machines */ 183 209 static volatile int subshell_alive, subshell_stopped; … … init_subshell_child (const char *pty_name) 362 388 dup2 (subshell_pty_slave, STDERR_FILENO); 363 389 364 390 close (subshell_pipe[READ]); 391 if (mc_global.shell->type == SHELL_BASH 392 || mc_global.shell->type == SHELL_ZSH 393 || mc_global.shell->type == SHELL_FISH) 394 close (command_buffer_pipe[READ]); 365 395 close (subshell_pty_slave); /* These may be FD_CLOEXEC, but just in case... */ 366 396 /* Close master side of pty. This is important; apart from */ 367 397 /* freeing up the descriptor for use in the subshell, it also */ … … synchronize (void) 469 499 } 470 500 471 501 /* --------------------------------------------------------------------------------------------- */ 502 /* Get the contents of the current subshell command line buffer, and */ 503 /* transfer the contents to the panel command prompt. */ 504 505 static gboolean 506 read_command_line_buffer(void) 507 { 508 fd_set read_set; 509 int j; 510 int bytes; 511 char subshell_command_buffer[BUF_LARGE]; 512 struct timeval subshell_prompt_timer = { 0, 0 }; 513 int command_buffer_length; 514 int cursor_position; 515 int maxfdp; 516 517 if (mc_global.shell->type == SHELL_BASH 518 || mc_global.shell->type == SHELL_ZSH 519 || mc_global.shell->type == SHELL_FISH) 520 { 521 FD_ZERO (&read_set); 522 FD_SET (command_buffer_pipe[READ], &read_set); 523 maxfdp = command_buffer_pipe[READ]; 524 /* First, flush the command buffer pipe. This pipe shouldn't be written 525 * to under normal circumstances, but if it somehow does get written 526 * to, we need to make sure to discard whatever data is there before 527 * we try to use it. */ 528 while (select (maxfdp + 1, &read_set, NULL, NULL, &subshell_prompt_timer) != 0) 529 { 530 bytes = read (command_buffer_pipe[READ], subshell_command_buffer, sizeof(subshell_command_buffer)); 531 } 532 533 subshell_prompt_timer.tv_sec = 1; 534 /* get contents of command line buffer */ 535 write_all (mc_global.tty.subshell_pty, ESC_STR SHELL_BUFFER_KEYBINDING, 536 sizeof(ESC_STR SHELL_CURSOR_KEYBINDING) - 1); 537 FD_ZERO (&read_set); 538 FD_SET (command_buffer_pipe[READ], &read_set); 539 maxfdp = command_buffer_pipe[READ]; 540 if (select (maxfdp + 1, &read_set, NULL, NULL, &subshell_prompt_timer) != 1) 541 return FALSE; 542 bytes = read (command_buffer_pipe[READ], subshell_command_buffer, sizeof(subshell_command_buffer)); 543 if (bytes == sizeof(subshell_command_buffer)) 544 return FALSE; 545 subshell_command_buffer[bytes - 1] = 0; 546 /* Erase non-text characters in the command buffer, such as tab, or newline, as this 547 * could cause problems. */ 548 for(j = 0;j < bytes - 1;j++) 549 { 550 if ((unsigned char) subshell_command_buffer[j] < 32 551 || (unsigned char)subshell_command_buffer[j] == 127) 552 subshell_command_buffer[j] = ' '; 553 } 554 input_assign_text (cmdline, ""); 555 input_insert (cmdline, subshell_command_buffer, 0); 556 command_buffer_length = str_length(subshell_command_buffer); 557 558 /* get cursor position */ 559 write_all (mc_global.tty.subshell_pty, ESC_STR SHELL_CURSOR_KEYBINDING, 560 sizeof(ESC_STR SHELL_CURSOR_KEYBINDING) - 1); 561 FD_ZERO (&read_set); 562 FD_SET (command_buffer_pipe[READ], &read_set); 563 maxfdp = command_buffer_pipe[READ]; 564 if (select (maxfdp + 1, &read_set, NULL, NULL, &subshell_prompt_timer) != 1) 565 return FALSE; 566 bytes = read (command_buffer_pipe[READ], subshell_command_buffer, sizeof(subshell_command_buffer)); 567 subshell_command_buffer[bytes - 1] = 0; 568 cursor_position = atoi(subshell_command_buffer); 569 if (mc_global.shell->type == SHELL_BASH) 570 { 571 for (j = 0;j < command_buffer_length;j++) 572 if (str_offset_to_pos(subshell_command_buffer, j) == cursor_position) 573 break; 574 cursor_position = j; 575 } 576 if (cursor_position > command_buffer_length) 577 cursor_position = command_buffer_length; 578 cmdline->point = cursor_position; 579 /* We send any remaining data to STDOUT before we finish. */ 580 flush_subshell(0, VISIBLY); 581 582 /* Now we erase the current contents of the command line buffer */ 583 if (mc_global.shell->type != SHELL_ZSH) 584 /* In zsh, we can just press c-u to clear the line, without needing to go to the end of 585 * the line first first. In all other shells, we must go to the end of the line first. */ 586 { 587 /* If we are not at the end of the line, we go to the end. */ 588 if (cursor_position != command_buffer_length) 589 { 590 write_all (mc_global.tty.subshell_pty, "\005", 1); 591 if (flush_subshell(1, VISIBLY) != 1) 592 return FALSE; 593 } 594 } 595 if (command_buffer_length > 0) /* Now we clear the line. */ 596 { 597 write_all (mc_global.tty.subshell_pty, "\025", 1); 598 if (flush_subshell(1, VISIBLY) != 1) 599 return FALSE; 600 } 601 } 602 return TRUE; 603 } 604 605 /* --------------------------------------------------------------------------------------------- */ 606 607 static void 608 clear_subshell_prompt_string (void) 609 { 610 if(subshell_prompt_temp_buffer != NULL) 611 g_string_set_size (subshell_prompt_temp_buffer, 0); 612 } 613 614 /* --------------------------------------------------------------------------------------------- */ 615 616 static gboolean 617 parse_subshell_prompt_string (const char *buffer, int bytes) 618 { 619 int rc = 0; 620 int i; 621 622 /* First time through */ 623 if (subshell_prompt == NULL) 624 { 625 subshell_prompt = g_string_sized_new (INITIAL_PROMPT_SIZE); 626 } 627 if (subshell_prompt_temp_buffer == NULL) 628 { 629 subshell_prompt_temp_buffer = g_string_sized_new (INITIAL_PROMPT_SIZE); 630 } 631 632 /* Extract the prompt from the shell output */ 633 for (i = 0; i < bytes; i++) 634 if (buffer[i] == '\n' || buffer[i] == '\r') 635 { 636 g_string_set_size (subshell_prompt_temp_buffer, 0); 637 } 638 else if (buffer[i] != '\0') 639 g_string_append_c (subshell_prompt_temp_buffer, buffer[i]); 640 641 return (rc != 0 || bytes != 0); 642 } 643 644 /* --------------------------------------------------------------------------------------------- */ 645 646 static void 647 set_prompt_string (void) 648 { 649 if (subshell_prompt_temp_buffer->len != 0) 650 g_string_assign (subshell_prompt, subshell_prompt_temp_buffer->str); 651 652 setup_cmdline(); 653 } 654 655 /* --------------------------------------------------------------------------------------------- */ 472 656 /** Feed the subshell our keyboard input until it says it's finished */ 473 657 474 658 static gboolean … … feed_subshell (int how, gboolean fail_on_error) 481 665 struct timeval wtime; /* Maximum time we wait for the subshell */ 482 666 struct timeval *wptr; 483 667 668 should_read_new_subshell_prompt = FALSE; 669 subshell_should_clear_command_line = FALSE; 670 484 671 /* we wait up to 10 seconds if fail_on_error, forever otherwise */ 485 672 wtime.tv_sec = 10; 486 673 wtime.tv_usec = 0; … … feed_subshell (int how, gboolean fail_on_error) 549 736 550 737 if (how == VISIBLY) 551 738 write_all (STDOUT_FILENO, pty_buffer, bytes); 739 if (should_read_new_subshell_prompt) 740 { 741 parse_subshell_prompt_string(pty_buffer, bytes); 742 } 743 552 744 } 553 745 554 746 else if (FD_ISSET (subshell_pipe[READ], &read_set)) … … feed_subshell (int how, gboolean fail_on_error) 567 759 568 760 synchronize (); 569 761 762 clear_subshell_prompt_string(); 763 should_read_new_subshell_prompt = TRUE; 570 764 subshell_ready = TRUE; 571 765 if (subshell_state == RUNNING_COMMAND) 572 766 { … … feed_subshell (int how, gboolean fail_on_error) 578 772 else if (FD_ISSET (STDIN_FILENO, &read_set)) 579 773 /* Read from stdin, write to the subshell */ 580 774 { 775 should_read_new_subshell_prompt = FALSE; 581 776 bytes = read (STDIN_FILENO, pty_buffer, sizeof (pty_buffer)); 582 777 if (bytes <= 0) 583 778 { … … feed_subshell (int how, gboolean fail_on_error) 592 787 { 593 788 write_all (mc_global.tty.subshell_pty, pty_buffer, i); 594 789 if (subshell_ready) 790 { 595 791 subshell_state = INACTIVE; 792 set_prompt_string (); 793 if (subshell_ready == TRUE) 794 { 795 if (!read_command_line_buffer()) 796 { 797 /* If we got here, some unforseen error must have occurred. */ 798 flush_subshell(0, VISIBLY); 799 input_assign_text (cmdline, ""); 800 subshell_should_clear_command_line = TRUE; 801 return TRUE; 802 } 803 } 804 } 596 805 return TRUE; 597 806 } 598 807 599 808 write_all (mc_global.tty.subshell_pty, pty_buffer, bytes); 600 809 601 810 if (pty_buffer[bytes - 1] == '\n' || pty_buffer[bytes - 1] == '\r') 811 { 812 /* We should only clear the command line if we are using a shell that works 813 * with persistent command buffer, otherwise we get awkward results. */ 814 if (mc_global.shell->type == SHELL_BASH 815 || mc_global.shell->type == SHELL_ZSH 816 || mc_global.shell->type == SHELL_FISH) 817 input_assign_text (cmdline, ""); 602 818 subshell_ready = FALSE; 819 } 603 820 } 604 821 else 605 822 return FALSE; … … init_subshell_precmd (char *precmd, size_t buff_size) 784 1001 { 785 1002 case SHELL_BASH: 786 1003 g_snprintf (precmd, buff_size, 1004 " bind -x '\"\\e" SHELL_BUFFER_KEYBINDING "\":\"echo $READLINE_LINE>&%d\"'\n" 1005 " bind -x '\"\\e" SHELL_CURSOR_KEYBINDING "\":\"echo $READLINE_POINT>&%d\"'\n" 787 1006 " PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND\n}'pwd>&%d;kill -STOP $$'\n" 788 "PS1='\\u@\\h:\\w\\$ '\n", subshell_pipe[WRITE]); 1007 "PS1='\\u@\\h:\\w\\$ '\n", 1008 command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]); 789 1009 break; 790 1010 791 1011 case SHELL_ASH_BUSYBOX: … … init_subshell_precmd (char *precmd, size_t buff_size) 844 1064 845 1065 case SHELL_ZSH: 846 1066 g_snprintf (precmd, buff_size, 1067 " mc_print_command_buffer () { echo $BUFFER >&%d}\n" 1068 " zle -N mc_print_command_buffer\n" 1069 " bindkey '^[" SHELL_BUFFER_KEYBINDING "' mc_print_command_buffer\n" 1070 " mc_print_cursor_position () { echo $CURSOR >&%d}\n" 1071 " zle -N mc_print_cursor_position\n" 1072 " bindkey '^[" SHELL_CURSOR_KEYBINDING "' mc_print_cursor_position\n" 847 1073 " _mc_precmd(){ pwd>&%d;kill -STOP $$ }; precmd_functions+=(_mc_precmd)\n" 848 "PS1='%%n@%%m:%%~%%# '\n", subshell_pipe[WRITE]); 1074 "PS1='%%n@%%m:%%~%%# '\n", 1075 command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]); 849 1076 break; 850 1077 851 1078 case SHELL_TCSH: … … init_subshell_precmd (char *precmd, size_t buff_size) 854 1081 "set prompt='%%n@%%m:%%~%%# '; " 855 1082 "alias precmd 'echo $cwd:q >>%s; kill -STOP $$'\n", tcsh_fifo); 856 1083 break; 857 858 1084 case SHELL_FISH: 859 1085 g_snprintf (precmd, buff_size, 860 1086 " if not functions -q fish_prompt_mc;" 861 1087 "functions -e fish_right_prompt;" 862 1088 "functions -c fish_prompt fish_prompt_mc; end;" 863 1089 "function fish_prompt;" 1090 "bind \\e\\" SHELL_BUFFER_KEYBINDING " 'echo (commandline)>&%d'\n" 1091 "bind \\e\\" SHELL_CURSOR_KEYBINDING " 'echo (commandline -C)>&%d'\n" 864 1092 "echo \"$PWD\">&%d; fish_prompt_mc; kill -STOP %%self; end\n", 865 subshell_pipe[WRITE]);1093 command_buffer_pipe[WRITE], command_buffer_pipe[WRITE], subshell_pipe[WRITE]); 866 1094 break; 867 1095 868 1096 default: … … init_subshell (void) 1040 1268 mc_global.tty.use_subshell = FALSE; 1041 1269 return; 1042 1270 } 1271 if (mc_global.shell->type == SHELL_BASH 1272 || mc_global.shell->type == SHELL_ZSH 1273 || mc_global.shell->type == SHELL_FISH) 1274 { 1275 if (pipe (command_buffer_pipe)) 1276 { 1277 perror (__FILE__ ": couldn't create pipe"); 1278 mc_global.tty.use_subshell = FALSE; 1279 return; 1280 } 1281 } 1043 1282 } 1044 1283 1045 1284 /* Fork the subshell */ … … init_subshell (void) 1061 1300 /* We are in the child process */ 1062 1301 init_subshell_child (pty_name); 1063 1302 } 1064 1065 1303 init_subshell_precmd (precmd, BUF_MEDIUM); 1066 1304 1067 1305 write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd)); … … init_subshell (void) 1084 1322 int 1085 1323 invoke_subshell (const char *command, int how, vfs_path_t ** new_dir_vpath) 1086 1324 { 1325 size_t i; 1087 1326 /* Make the MC terminal transparent */ 1088 1327 tcsetattr (STDOUT_FILENO, TCSANOW, &raw_mode); 1089 1328 … … invoke_subshell (const char *command, int how, vfs_path_t ** new_dir_vpath) 1100 1339 /* FIXME: possibly take out this hack; the user can re-play it by hitting C-hyphen a few times! */ 1101 1340 if (subshell_ready && mc_global.mc_run_mode == MC_RUN_FULL) 1102 1341 write_all (mc_global.tty.subshell_pty, " \b", 2); /* Hack to make prompt reappear */ 1342 1343 if (mc_global.shell->type == SHELL_BASH 1344 || mc_global.shell->type == SHELL_ZSH 1345 || mc_global.shell->type == SHELL_FISH) 1346 { 1347 /* Check to make sure there are no non text characters in the command buffer, 1348 * such as tab, or newline, as this could cause problems. */ 1349 for(i = 0;i < strlen(cmdline->buffer);i++) 1350 { 1351 if ((unsigned char) cmdline->buffer[i] < 32 1352 || (unsigned char)cmdline->buffer[i] == 127) 1353 cmdline->buffer[i] = ' '; 1354 } 1355 1356 /* Write the command buffer to the subshell. */ 1357 write_all (mc_global.tty.subshell_pty, cmdline->buffer, strlen (cmdline->buffer)); 1358 1359 /* Put the cursor in the correct place in the subshell. */ 1360 for (int j = 0;j < str_length (cmdline->buffer) - cmdline->point;j++) 1361 write_all (mc_global.tty.subshell_pty, ESC_STR "[D", 3); 1362 } 1103 1363 } 1104 1364 } 1105 1365 else /* MC has passed us a user command */ 1106 1366 { 1367 /* Before we write to the command prompt, we need to clear whatever */ 1368 /* data is there, but only if we are using one of the shells that */ 1369 /* doesn't support keeping command buffer contents, OR if there was */ 1370 /* some sort of error. */ 1371 if (!(mc_global.shell->type == SHELL_BASH 1372 || mc_global.shell->type == SHELL_ZSH 1373 || mc_global.shell->type == SHELL_FISH) 1374 || subshell_should_clear_command_line) 1375 { 1376 write_all (mc_global.tty.subshell_pty, "\003", 1); 1377 subshell_state = RUNNING_COMMAND; 1378 if (mc_global.shell->type != SHELL_FISH) 1379 feed_subshell (QUIETLY, FALSE); 1380 } 1107 1381 if (how == QUIETLY) 1108 1382 write_all (mc_global.tty.subshell_pty, " ", 1); 1109 1383 /* FIXME: if command is long (>8KB ?) we go comma */ … … invoke_subshell (const char *command, int how, vfs_path_t ** new_dir_vpath) 1131 1405 return subshell_get_mainloop_quit (); 1132 1406 } 1133 1407 1134 1135 1408 /* --------------------------------------------------------------------------------------------- */ 1136 1409 1137 1410 gboolean 1138 read_subshell_prompt (void)1411 flush_subshell (int max_wait_length, int how) 1139 1412 { 1140 1413 int rc = 0; 1141 1414 ssize_t bytes = 0; 1142 1415 struct timeval timeleft = { 0, 0 }; 1143 GString *p; 1144 gboolean prompt_was_reset = FALSE; 1145 1416 int return_value = FALSE; 1146 1417 fd_set tmp; 1418 1419 timeleft.tv_sec = max_wait_length; 1147 1420 FD_ZERO (&tmp); 1148 1421 FD_SET (mc_global.tty.subshell_pty, &tmp); 1149 1422 1150 /* First time through */1151 if (subshell_prompt == NULL)1152 subshell_prompt = g_string_sized_new (INITIAL_PROMPT_SIZE);1153 1154 p = g_string_sized_new (INITIAL_PROMPT_SIZE);1155 1156 1423 while (subshell_alive 1157 1424 && (rc = select (mc_global.tty.subshell_pty + 1, &tmp, NULL, NULL, &timeleft)) != 0) 1158 1425 { 1159 ssize_t i;1160 1161 1426 /* Check for 'select' errors */ 1162 1427 if (rc == -1) 1163 1428 { … … read_subshell_prompt (void) 1172 1437 fprintf (stderr, "select (FD_SETSIZE, &tmp...): %s\r\n", unix_error_string (errno)); 1173 1438 exit (EXIT_FAILURE); 1174 1439 } 1440 return_value = TRUE; 1441 timeleft.tv_sec = 0; 1442 timeleft.tv_usec = 0; 1175 1443 1176 1444 bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer)); 1445 if (how == VISIBLY) 1446 write_all (STDOUT_FILENO, pty_buffer, bytes); 1447 } 1448 return return_value; 1449 } 1450 1451 /* --------------------------------------------------------------------------------------------- */ 1177 1452 1178 /* Extract the prompt from the shell output */ 1179 for (i = 0; i < bytes; i++) 1180 if (pty_buffer[i] == '\n' || pty_buffer[i] == '\r') 1453 gboolean 1454 read_subshell_prompt (void) 1455 { 1456 int rc = 0; 1457 ssize_t bytes = 0; 1458 struct timeval timeleft = { 0, 0 }; 1459 int should_reset_prompt = TRUE; 1460 int got_new_prompt = FALSE; 1461 1462 fd_set tmp; 1463 FD_ZERO (&tmp); 1464 FD_SET (mc_global.tty.subshell_pty, &tmp); 1465 1466 while (subshell_alive 1467 && (rc = select (mc_global.tty.subshell_pty + 1, &tmp, NULL, NULL, &timeleft)) != 0) 1468 { 1469 /* Check for 'select' errors */ 1470 if (rc == -1) 1471 { 1472 if (errno == EINTR) 1181 1473 { 1182 g_string_set_size (p, 0); 1183 prompt_was_reset = TRUE; 1474 if (tty_got_winch ()) 1475 tty_change_screen_size (); 1476 1477 continue; 1184 1478 } 1185 else if (pty_buffer[i] != '\0')1186 g_string_append_c (p, pty_buffer[i]);1187 }1188 1479 1189 if (p->len != 0 || prompt_was_reset) 1190 g_string_assign (subshell_prompt, p->str); 1480 fprintf (stderr, "select (FD_SETSIZE, &tmp...): %s\r\n", unix_error_string (errno)); 1481 exit (EXIT_FAILURE); 1482 } 1191 1483 1192 g_string_free (p, TRUE); 1484 bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer)); 1485 if (should_reset_prompt) 1486 { 1487 should_reset_prompt = FALSE; 1488 clear_subshell_prompt_string(); 1489 } 1490 parse_subshell_prompt_string (pty_buffer, bytes); 1491 got_new_prompt = TRUE; 1492 } 1493 if (got_new_prompt == TRUE) 1494 { 1495 set_prompt_string (); 1496 } 1193 1497 1194 1498 return (rc != 0 || bytes != 0); 1195 1499 } … … exit_subshell (void) 1231 1535 1232 1536 g_string_free (subshell_prompt, TRUE); 1233 1537 subshell_prompt = NULL; 1538 g_string_free (subshell_prompt_temp_buffer, TRUE); 1539 subshell_prompt_temp_buffer = NULL; 1234 1540 pty_buffer[0] = '\0'; 1235 1541 } 1236 1542 … … do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt) 1259 1565 return; 1260 1566 } 1261 1567 1568 /* If we are using a shell that doesn't support persistent command buffer, we need to clear 1569 * the command prompt before we send the cd command. */ 1570 if (!(mc_global.shell->type == SHELL_BASH 1571 || mc_global.shell->type == SHELL_ZSH 1572 || mc_global.shell->type == SHELL_FISH) 1573 || subshell_should_clear_command_line) 1574 { 1575 write_all (mc_global.tty.subshell_pty, "\003", 1); 1576 subshell_state = RUNNING_COMMAND; 1577 if (mc_global.shell->type != SHELL_FISH) 1578 feed_subshell (QUIETLY, FALSE); 1579 } 1262 1580 /* The initial space keeps this out of the command history (in bash 1263 1581 because we set "HISTCONTROL=ignorespace") */ 1264 1582 write_all (mc_global.tty.subshell_pty, " cd ", 4); -
src/subshell/subshell.h
diff --git a/src/subshell/subshell.h b/src/subshell/subshell.h index e0fdfb13e..bde19c469 100644
a b extern GString *subshell_prompt; 36 36 37 37 extern gboolean update_subshell_prompt; 38 38 39 extern gboolean should_read_new_subshell_prompt; 40 39 41 /*** declarations of public functions ************************************************************/ 40 42 41 43 void init_subshell (void); 42 44 int invoke_subshell (const char *command, int how, vfs_path_t ** new_dir); 45 gboolean flush_subshell (int max_wait_length, int how); 43 46 gboolean read_subshell_prompt (void); 44 47 void do_update_prompt (void); 45 48 gboolean exit_subshell (void);