Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
811 views
in Technique[技术] by (71.8m points)

c - How to restart stdin after Ctrl+D?

Running a program expecting input from terminal I can ”close” stdin by Ctrl+D. Is there any way to reopen stdin after that?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In and on POSIXy systems in general, the standard input descriptor is not closed when you press Ctrl+D in the terminal; it just causes the pseudoterminal layer to become readable, with read() returning 0. This is how POSIXy systems indicate end of input.

It does not mean the file descriptor (or even the stream handle provided on top of it by the C library) gets closed. As Steve Summit mentioned in a comment, you only need to clear the end-of-input status of the stream using clearerr(), to be able to read further data; this tells the C library that you noticed the status change, but want to try further reading anyway.

A similar situation can occur when a process is writing to a file, and another reads it. When the reader gets to the end of the file, a read() returns 0, which the C library understands as end-of-input; it sets an internal flag, so that unless you call clearerr(), feof() will return true for that stream. Now, if the writer writes more data, and the reader does a clearerr(), the reader can read the newly written additional data.

This is perfectly normal, and expected behaviour.

In summary:

  • End of input is indicated by a read() operation returning 0, but the file descriptor status does not change, and can be used as normal.

  • Ctrl+D on a terminal causes only that to happen; the file descriptors open to the terminal are not affected in any other way, and it is up to the foreground process reading the terminal input to decide what it does. It is allowed to simply go on reading more data.

    Most programs do exit when that happens, but that is a convention, not a technical requirement at all.

  • The C library detects read() returning 0, and sets its internal "end of input seen" flag for that stream. That causes feof() to return true, fgets() to return NULL, fgetc() to return EOF, and so on, for that stream.

  • Calling clearerr() on the stream handle clears the flag, so that the next read attempt will actually try to read further data from the descriptor.

    This is described in the very first sentence in the Description section of the man 3 clearerr man page.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...