files: when needed, reconnect the keyboard and reenter curses mode

When after reading a file we are not in curses mode, it means we have
read data from standard input, either from the keyboard or from a pipe.
In the latter case, we first need to reconnect standard input to the tty.
And in both cases, we then need to reenter curses mode before being able
to display the number of lines that were read (or an error message).

So, move the reconnecting code from scoop_stdin() to its own function,
and call this function from read_file() when needed.

This fixes https://savannah.gnu.org/bugs/?56310.

Bug existed since version 2.1.8 when reading from stdin was introduced.
master
Benno Schulenberg 2019-05-28 11:06:42 +02:00
parent b53dffaeed
commit d946f38a2b
3 changed files with 38 additions and 23 deletions

View File

@ -711,6 +711,8 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
int input_int;
/* The current value we read from the file, whether an input
* character or EOF. */
int errornumber;
/* The error code, in case an error occurred during reading. */
bool writable = TRUE;
/* Whether the file is writable (in case we care). */
#ifndef NANO_TINY
@ -814,6 +816,8 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
#endif
}
errornumber = errno;
/* We are done with the file, unlock it. */
funlockfile(f);
@ -821,10 +825,19 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
block_sigwinch(FALSE);
#endif
/* Perhaps this could use some better handling. */
if (ferror(f))
nperror(filename);
/* When reading from stdin, restore the terminal and reenter curses mode. */
if (isendwin()) {
if (!isatty(0))
reconnect_and_store_state();
terminal_init();
doupdate();
}
/* If there was a real error during the reading, let the user know. */
if (ferror(f) && errornumber != EINTR && errornumber != 0)
statusline(ALERT, strerror(errornumber));
fclose(f);
if (fd > 0 && !undoable) {
close(fd);
writable = (ISSET(VIEW_MODE) || access(filename, W_OK) == 0);

View File

@ -1075,11 +1075,30 @@ void restore_handler_for_Ctrl_C(void)
disable_kb_interrupt();
}
/* Reconnect standard input to the tty, and store its state. */
void reconnect_and_store_state(void)
{
int thetty = open("/dev/tty", O_RDONLY);
if (thetty < 1)
die(_("Could not reconnect stdin to keyboard\n"));
dup2(thetty, 0);
close(thetty);
/* If there were no signals, store the current state of the terminal. */
if (!control_C_was_pressed) {
#ifndef NANO_TINY
if (!size_changed)
#endif
tcgetattr(0, &oldterm);
}
}
/* Read whatever comes from standard input into a new buffer. */
bool scoop_stdin(void)
{
FILE *stream;
int thetty;
/* Exit from curses mode and put the terminal into its original state. */
endwin();
@ -1110,27 +1129,9 @@ bool scoop_stdin(void)
#ifdef ENABLE_COLOR
color_update();
#endif
fprintf(stderr, ".\n");
/* Reconnect the tty as the input source. */
thetty = open("/dev/tty", O_RDONLY);
if (!thetty)
die(_("Couldn't reopen stdin from keyboard, sorry\n"));
dup2(thetty, 0);
close(thetty);
/* If there were no signals, store the current state of the terminal. */
if (!control_C_was_pressed) {
#ifndef NANO_TINY
if (!size_changed)
#endif
tcgetattr(0, &oldterm);
}
/* Restore the original ^C handler, the terminal setup, and curses mode. */
/* Restore the original ^C handler. */
restore_handler_for_Ctrl_C();
terminal_init();
doupdate();
if (!ISSET(VIEW_MODE) && openfile->totsize > 0)
set_modified();

View File

@ -416,6 +416,7 @@ void do_exit(void);
void close_and_go(void);
void install_handler_for_Ctrl_C(void);
void restore_handler_for_Ctrl_C(void);
void reconnect_and_store_state(void);
RETSIGTYPE handle_hupterm(int signal);
#ifndef DEBUG
RETSIGTYPE handle_crash(int signal);