Zusammenfassung
Für viele Anwendungsfälle ist die POSIX- Funktion isatty()
alles, was benötigt wird, um festzustellen, ob stdin an ein Terminal angeschlossen ist. Ein minimales Beispiel:
#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;
}
Im folgenden Abschnitt werden verschiedene Methoden verglichen, die verwendet werden können, wenn unterschiedliche Interaktivitätsgrade getestet werden müssen.
Methoden im Detail
Es gibt verschiedene Methoden, um festzustellen, ob ein Programm interaktiv ausgeführt wird. Die folgende Tabelle zeigt eine Übersicht:
cmd \ method ctermid open isatty fstat
―――――――――――――――――――――――――――――――――――――――――――――――――――― ――――――――――
./test / dev / tty OK JA S_ISCHR
./test ≺ test.cc / dev / tty OK NEIN S_ISREG
cat test.cc | ./test / dev / tty OK NEIN S_ISFIFO
echo ./test | at now / dev / tty FAIL NO S_ISREG
Die Ergebnisse stammen von einem Ubuntu Linux 11.04-System mit folgendem Programm:
#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;
}
Endgerät
Wenn für die interaktive Sitzung bestimmte Funktionen erforderlich sind, können Sie das Endgerät öffnen und (vorübergehend) die erforderlichen Terminalattribute festlegen tcsetattr()
.
Python-Beispiel
Der Python-Code, der entscheidet, ob der Interpreter interaktiv ausgeführt wird, wird verwendet isatty()
. Die FunktionPyRun_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);
Anrufe 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;
was anruft isatty()
.
Fazit
Es gibt verschiedene Grade an Interaktivität. Die Überprüfung, ob stdin
eine Verbindung zu einer Pipe / Datei oder einem realen Terminal besteht, isatty()
ist eine natürliche Methode, um dies zu tun.