C restaurar stdout a la terminal

4 minutos de lectura

avatar de usuario
alessandroempire

Estoy trabajando con un programa multihilo.

Primero redirijo mi salida estándar a un archivo determinado. No hay problema allí (usé dup2(fd, 1) donde fd es el descriptor de archivo para el archivo).

Luego, necesito redirigir mi salida estándar a la terminal nuevamente.

Mi primer acercamiento:

      /*Declaration*/
      fpost_t  stream_sdout;
      /*code*/
      if ( fgetpos( stdout, &stream_sdout) == -1 )
          perror(Error:);

Dice búsqueda ilegal.
No tengo idea de por qué sucede esto.
Pero si logro que esto funcione, entonces solo necesito usar fsetpos(stdout, &stream_stdout) y debería funcionar.

Mi segunda idea fue copiar la salida estándar usando dup2(stdout, 4) a la tabla de descriptores de archivo, en la posición 4. Pero eso tampoco funciona.

¿Cómo puedo cambiar la salida estándar a su destino original (terminal, conducto, archivo, lo que sea)?

  • Tengo la sensación de que tratando de moverme stdout alrededor de esta manera es probablemente una mala idea: ¿en qué posición exactamente debería estar el Terminal informe en fgetpos()? ¿Por qué no simplemente abrir un archivo y enviarlo usando fwrite() o fprintf() o write() y la salida a la terminal a través de /dev/tty ¿Cuándo lo necesitas?

    – Sarnold

    14/06/2012 a las 22:30

  • @sarnold: probablemente porque el programa tiene bibliotecas u otro código inalterable que está conectado a stdout.

    – Wallyk

    14 de junio de 2012 a las 22:31

  • @sarnold, en realidad no pensé en esa posibilidad. Déjame comprobar rápidamente.

    – Imperio Alessandro

    14 de junio de 2012 a las 22:37

  • No tengo suficiente información para publicar una buena respuesta, así que estoy comentando en su lugar. En Windows, puede volver a conectar la consola. Miraría cualquier documentación del SDK de Win32. No es dificil; Simplemente no puedo recordar cómo hacerlo.

    – pulpo agarrar

    14 de junio de 2012 a las 22:49

  • @sarnold gracias por el consejo! Eso fue mucho más fácil. Pude hacerlo funcionar a la perfección. Aún tengo la duda de si es posible restaurar el std, pero tu solución me sacó de un apuro. ¡Gracias!

    – Imperio Alessandro

    14 de junio de 2012 a las 22:54

#include <unistd.h>

...

int saved_stdout;

...

/* Save current stdout for use later */
saved_stdout = dup(1);
dup2(my_temporary_stdout_fd, 1);

... do some work on your new stdout ...

/* Restore stdout */
dup2(saved_stdout, 1);
close(saved_stdout);

  • Esto realmente me ayudó mucho. Me preguntaba cuál es la función de cerrar (saved_stdout)? He usado close para cerrar archivos, pero aún no estoy familiarizado con el funcionamiento de todo el proceso de la función dup.

    – Piense en Bonobo

    13/04/2014 a las 19:22

  • @PiensaBonobo, saved_stdout es un duplicado (por lo tanto, dup()) del descriptor de archivo original para el archivo original subyacente a la salida estándar del programa. ¿Cuándo se vuelve a duplicar en (dup2()) stdout (descriptor de archivo n.° 1), el programa tiene dos copias/identificadores/descriptores para el mismo archivo subyacente. No hay necesidad de esto una vez que finaliza la redirección de salida (y podría confundir los límites de recursos o las suposiciones sobre bloqueos de archivos, etc.), por lo que una buena práctica es descartar el recurso cuando ya no se necesite.

    – almohada

    15/04/2014 a las 15:44

avatar de usuario
jonathan leffler

Antes de hacer el dup2(fd, STDOUT_FILENO)debe guardar el descriptor de archivo abierto actual para la salida estándar haciendo int saved_stdout = dup(STDOUT_FILENO); (alquilar dup() elegir un número de descriptor de archivo disponible para usted). Luego, una vez que haya terminado con la salida redirigida a un archivo, puede hacer dup2(saved_stdout, STDOUT_FILENO) para restaurar la salida estándar a donde estaba antes de que comenzara todo esto (y debe cerrar saved_stdout también).

Debe preocuparse por vaciar los flujos de E/S estándar (fflush(stdout)) en los momentos apropiados mientras juegas con esto. Eso significa ‘antes de cambiar stdout’.

Si el programa se ejecuta en un entorno Linux, puede freopen ("/dev/stdout", "a", stdout).

pero si sabes eso stdout era la terminal, freopen ("/dev/tty", "a", stdout) o el equivalente para otros sistemas operativos, incluso Windows.

  • Cuando el dup2() obras, /dev/stdout debe consultar el archivo. Así que has cambiado la salida del archivo al archivo, creo.

    –Jonathan Leffler

    14 de junio de 2012 a las 23:02

  • @JonathanLeffler: Si está cambiando el fds alrededor, eso sería cierto. Está lejos de ser aparente de su descripción que es lo que está sucediendo. Parece que podría estar cambiando las conexiones de ARCHIVO en su lugar.

    – Wallyk

    14 de junio de 2012 a las 23:11

  • Ya que menciona usar dup2() para cambiar la salida estándar, me parece que está jugando con los descriptores de archivos para empezar. El código para restablecer las cosas en la pregunta es extraño más allá del rescate; una reescritura está en orden. Pero de eso se supone que tratan las respuestas, por supuesto.

    –Jonathan Leffler

    14 de junio de 2012 a las 23:15

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad