ENUNCIADO

Pongamos en práctica todo lo aprendido en esta sesión. Haced un programa que limpie la pantalla, imprima un mensaje que ponga:
¿Desea que el programa acabe? (s/n) 
con la s en modo inverso para resaltar que es la opción por defecto. El mensaje debe aparecer en la línea 3, columna 7 de la pantalla. No uséis tput para ello. Usad directamente los códigos del terminal vt100 que vienen en el resumen. El programa se debe quedar esperando 10 segundos como máximo a que el usuario pulse una tecla. A la sola pulsación de una 's' el programa acaba con un código de retorno 0. Si se pulsa una 'n' el programa acaba con un código de retorno 1. Si se pulsa otra letra, el programa acaba con un código de retorno 2. Si no se pulsa nada y pasan los diez segundos, el programa acaba con código de retorno 3. No usar alarm. Dejad el terminal como estaba al principio, incluso si se pulsa CTRL+C para interrumpir su funcionamiento.

COMENTARIOS

La práctica que consiguió el 0.25 fue la de Light y Pincushion:
/* Codigos de error         */
/* (no indicados enunciado) */
/* 10: Error de ejecucion   */
/* 11: Salida por CTRL+C    */

#define _HPUX_SOURCE

#define ESC 27
#define STD_IN 0
#define STD_OUT 1

#include <signal.h>
#include <stdio.h>
#include <termio.h>
#include <unistd.h>
#include <sys/ioctl.h>

struct termio vieja;
struct sigaction int_old;
int dev=11;

void aborto (int);

int main (void) {
  char term_clear[7],
       term_posic[7],
       term_invsi[5],
       term_invno[5],
       letra='\0';
  struct termio actual;
  struct sigaction int_new;

  /* Almacenamos cosas */
  if (ioctl (STD_IN,  TCGETA, &vieja)==-1) {
    perror ("ioctl/TCGETA vieja:");
    return 10;
  }
  if (ioctl (STD_IN, TCGETA, &actual)==-1) {
    perror ("ioctl/TCGETA actual:");
    return 10;
  }

  int_new.sa_handler=aborto;
  sigemptyset (&(int_new.sa_mask));
  int_new.sa_flags=0;
  if (sigaction (SIGINT, &int_new, &int_old)==-1) {
    perror ("sigaction:");
    return 10;
  }

  /* Mensaje */
  sprintf (term_clear, "%c[H%c[J", ESC, ESC);
  sprintf (term_posic, "%c[3;7H",  ESC);
  sprintf (term_invsi, "%c[7m",    ESC);
  sprintf (term_invno, "%c[m",     ESC);
  printf ("%s%s¿Desea que el programa acabe? (%ss%s/n)",
          term_clear, term_posic, term_invsi, term_invno);
  fflush (stdout);
/* Es importante poner el fflush(stdout);
   pues si no, la frase se quedaría en el buffer
   intermedio y no aparecería de inmediato en la
   pantalla. */

  /* Entrada */
  actual.c_lflag=actual.c_lflag & ~ICANON | ECHO;
  actual.c_cc[VTIME]=100;
  actual.c_cc[VMIN] =0;
  if (ioctl (STD_IN, TCSETA, &actual)==-1) {
    perror ("ioctl/TCSETA actual:");
    return 10;
  }

  switch (read(STD_IN, &letra, 1)) {
    case 0:
      dev=3;
      break;
    case 1:
      switch (letra) {
        case 's':
          dev=0;
          break;
        case 'n':
          dev=1;
          break;
        default:
          dev=2;
          break;
      }
      break;
    default:
      perror ("read: ");
      return 10; 
  }
  
  printf ("%s", term_clear);
  fflush (stdout);
  aborto (dev);
}

void aborto (int nada) {
  if (ioctl (STD_IN, TCSETA, &vieja)==-1) {
    perror ("ioctl/TCSETA vieja (aborto):");
    exit (10);
  }
  if (sigaction (SIGINT, &int_old, NULL)==-1) {
    perror ("sigaction (aborto):");
    exit (10);
  }
  
  exit (dev);
}

            



© 2001 Guillermo González Talaván.