Résumé
Pour de nombreux cas d'utilisation de la POSIX fonction isatty()
est tout ce qu'il est nécessaire de détecter si stdin est connecté à un terminal. Un exemple minimal:
#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;
}
La section suivante compare les différentes méthodes qui peuvent être utilisées si différents degrés d'interactivité besoin d'être testé.
Méthodes en Détail
Il existe plusieurs méthodes pour détecter si un programme est exécuté de manière interactive.
Tableau suivant montre un aperçu:
cmd\méthode ctermid ouvrir isatty fstat
------------------------------------------------------------
./test /dev/tty OK OUI S_ISCHR
./test ≺ test.cc /dev/tty OK PAS de S_ISREG
chat test.cc | ./test /dev/tty OK PAS de S_ISFIFO
echo ./test | à /dev/tty manquera PAS non S_ISREG
Les résultats sont à partir d'un Linux Ubuntu 11.04 système en utilisant le programme suivant:
#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;
}
Termimal appareil
Si la session interactive a besoin de certaines fonctionnalités, vous pouvez ouvrir le
terminal et (temporairement) définissez les attributs que vous devez
via tcsetattr()
.
Exemple Python
Le code Python qui décide si l'interprète s'exécute de manière interactive utilise isatty()
. La Fonction 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);
appels 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;
qui demande isatty()
.
Conclusion
Il y a différents degrés d'interactivité. Pour vérifier si stdin
est
connecté à un tuyau/fichier ou un vrai terminal isatty()
est une méthode naturelle pour
le faire.