+1: stdin can be a pipe or redirected from a file.
It should be sent by the user. So is it that only the user can invoke EOF in stdin by pressing Ctrl + Z ? Yes, you can set the EOF indicator for stdin with a special key combination you can input in the console, for linux console that is Ctrl + D and for windows it's Ctrl + Z .
you can just fclose(stdin), it will call close() on the file handle.
Use isatty:
#include <stdio.h>
#include <io.h>
...
if (isatty(fileno(stdin)))
printf( "stdin is a terminal\n" );
else
printf( "stdin is a file or a pipe\n");
(On windows they're prefixed with underscores: _isatty, _fileno)
For many use cases the POSIX function isatty() is all what it is needed to detect if stdin is connected to a terminal. A minimal example:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
if (isatty(fileno(stdin)))
puts("stdin is connected to a terminal");
else
puts("stdin is NOT connected to a terminal");
return 0;
}
The following section compares different methods that can be used if different degrees of interactivity have to be tested.
There are several methods to detect if a program is running interactively. Following table shows an overview:
cmd\method ctermid open isatty fstat ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ./test /dev/tty OK YES S_ISCHR ./test ≺ test.cc /dev/tty OK NO S_ISREG cat test.cc | ./test /dev/tty OK NO S_ISFIFO echo ./test | at now /dev/tty FAIL NO S_ISREG
The results are from a Ubuntu Linux 11.04 system using following program:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main() {
char tty[L_ctermid+1] = {0};
ctermid(tty);
cout << "ID: " << tty << '\n';
int fd = ::open(tty, O_RDONLY);
if (fd < 0) perror("Could not open terminal");
else {
cout << "Opened terminal\n";
struct termios term;
int r = tcgetattr(fd, &term);
if (r < 0) perror("Could not get attributes");
else cout << "Got attributes\n";
}
if (isatty(fileno(stdin))) cout << "Is a terminal\n";
else cout << "Is not a terminal\n";
struct stat stats;
int r = fstat(fileno(stdin), &stats);
if (r < 0) perror("fstat failed");
else {
if (S_ISCHR(stats.st_mode)) cout << "S_ISCHR\n";
else if (S_ISFIFO(stats.st_mode)) cout << "S_ISFIFO\n";
else if (S_ISREG(stats.st_mode)) cout << "S_ISREG\n";
else cout << "unknown stat mode\n";
}
return 0;
}
If the interactive session needs certain capabilities, you can open the
terminal device and (temporarily) set terminal attributes you need
via tcsetattr().
The Python code that decides whether the interpreter runs interactively uses isatty(). The Function PyRun_AnyFileExFlags()
/* Parse input from a file and execute it */
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
if (filename == NULL)
filename = "???";
if (Py_FdIsInteractive(fp, filename)) {
int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
calls Py_FdIsInteractive()
/*
* The file descriptor fd is considered ``interactive'' if either
* a) isatty(fd) is TRUE, or
* b) the -i flag was given, and the filename associated with
* the descriptor is NULL or "<stdin>" or "???".
*/
int
Py_FdIsInteractive(FILE *fp, const char *filename)
{
if (isatty((int)fileno(fp)))
return 1;
which calls isatty().
There are different degrees of interactivity. For checking if stdin is
connected to a pipe/file or a real terminal isatty() is a natural method to
do that.
Probably they are checking the type of file that "stdin" is with fstat, something like this:
struct stat stats;
fstat(0, &stats);
if (S_ISCHR(stats.st_mode)) {
// Looks like a tty, so we're in interactive mode.
} else if (S_ISFIFO(stats.st_mode)) {
// Looks like a pipe, so we're in non-interactive mode.
}
Of course Python is open source, so you can just look at what they do and know for sure:
http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tar.bz2
On Windows you can use GetFileType.
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD type = GetFileType(hIn);
switch (type) {
case FILE_TYPE_CHAR:
// it's from a character device, almost certainly the console
case FILE_TYPE_DISK:
// redirected from a file
case FILE_TYPE_PIPE:
// piped from another program, a la "echo hello | myprog"
case FILE_TYPE_UNKNOWN:
// this shouldn't be happening...
}
Call stat() or fstat() and see if S_IFIFO is set in st_mode.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With