140 votes

Détecter si stdin est un terminal ou un tuyau en C / C + c++ / Qt ?

Quand j’ai exécuter " `` " de la borne sans arguments, il évoque le shell interactif de Python.

Quand j’ai exécuter " `` " de la borne il ne lance pas le mode interactif. En quelque sorte, sans obtenir n’importe quelle entrée, il a détecté qu’il est connecté à un tuyau.

Comment puis-je faire une détection similaire en C ou C++, Qt ?

160voto

RichieHindle Points 98544

Utilisation `` :

(Sous windows, ils sont préfixés avec des traits de soulignement : , )

86voto

maxschlepzig Points 3578

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 stdinest connecté à un tuyau/fichier ou un vrai terminal isatty() est une méthode naturelle pour le faire.

8voto

Eric Melski Points 8325

Probablement ils vérifient que le type de fichier que « stdin » est avec fstat, quelque chose comme ceci :

Mais pourquoi nous demander ? Python est open source. Vous pouvez simplement aller regarder ce qu’ils font et de savent avec certitude :

http://www.Python.org/FTP/Python/2.6.2/Python-2.6.2.tar.bz2

Espoir qui aide,

Eric Melski

3voto

sigjuice Points 9166

Appelez stat() ou fstat() et voir si S_IFIFO est défini dans st_mode.

3voto

Marc Mutz - mmutz Points 10367

Vous pouvez appeler et recherchez . C’est Posix, pas de C/C++, cependant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X