2010-04-02 13 views
7

Estoy escribiendo un programa que debe leer la entrada a través de stdin, por lo que tengo la siguiente construcción.¿Cómo puedo verificar si mi programa tiene datos conectados

FILE *fp=stdin; 

Pero esto sólo se bloquea si el usuario no ha canalizado nada en el programa, ¿cómo puedo comprobar si el usuario está realmente de tuberías de datos en mi programa como

gunzip -c file.gz |./a.out #should work 
./a.out #should exit program with nice msg. 

gracias

+0

Para el registro, el programa no está colgando; simplemente está esperando la entrada. Si envía un EOF (Ctrl-D en la mayoría de las plataformas), se interpreta como si la entrada terminara temprano. – greyfade

Respuesta

8

Dado que está utilizando punteros de archivos, necesitará tanto isatty() y fileno() Para ello:

#include <unistd.h> 
#include <stdio.h> 

int main(int argc, char* argv[]) 
{ 
    FILE* fp = stdin; 

    if(isatty(fileno(fp))) 
    { 
     fprintf(stderr, "A nice msg.\n"); 
     exit(1); 
    } 

    /* carry on... */ 
    return 0; 
} 

En realidad, es el camino más largo. La forma más sencilla es no utilizar punteros de archivo:

#include <unistd.h> 

int main(int argc, char* argv[]) 
{ 
    if(isatty(STDIN_FILENO)) 
    { 
     fprintf(stderr, "A nice msg.\n"); 
     exit(1); 
    } 

    /* carry on... */ 
    return 0; 
} 

Varios programas estándar Unix hacen esta comprobación para modificar su comportamiento. Por ejemplo, si tiene ls configurado para darle bonitos colores, apagará los colores si canaliza su salida estándar a otro programa.

3

Pasar stdin a select() o poll() debería decirle si la entrada está esperando. En muchos sistemas operativos también se puede decir si stdin es un tty o tubería.

EDIT: veo que voy a tener que enfatizar el también parte de la prueba de tty. Una fifo no es una tty, sin embargo, puede que no haya ninguna entrada preparada por un tiempo indefinido.

+0

Creo que el OP solo quería cubrir el caso de "ejecutar-línea de comandos-y-preguntarse-por-qué-cuelga". Probablemente tratando de arreglar un error PEBKAC. Sentarse allí esperando en una FIFO u otra tubería estaría bien. –

3

Pruebe "man isatty", creo que la función le dirá si está hablando con el usuario o no.

2

Utilice isatty para detectar que stdin proviene de un terminal en lugar de una redirección.

1

Consulte la función "isatty" - si STDIN es un terminal, puede omitir la lectura de este. Si no es una terminal, recibirá datos canalizados o redirigidos y podrá leer hasta EOF.

0

Una opción adicional que obtienes con select() es establecer un tiempo de espera para leer desde stdin (con respecto a la primera lectura de stdin o lecturas consecutivas desde stdin).

Para un ejemplo de código usando selección en la entrada estándar, véase:

How to check if stdin is still opened without blocking?

Cuestiones relacionadas