- /* 
-  *  AUTHOR: Sven Goldt (goldt@math.tu-berlin.de) 
-  * 
-  *  This program is free software; you can redistribute it and/or 
-  *  modify it under the terms of the GNU General Public License 
-  *  as published by the Free Software Foundation; either version 2 
-  *  of the License, or (at your option) any later version. 
-  * 
-  *  This program is distributed in the hope that it will be useful, 
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-  *  GNU General Public License for more details. 
-  * 
- */ 
-   
- // 
- // miniterm.c 
- // 
-   
- #include <termios.h> 
- #include <stdio.h> 
- #include <unistd.h> 
- #include <fcntl.h> 
- #include <sys/signal.h> 
-   
- #define TXRXDEVICE "/dev/ttyS0"    // COM1 
- //#define TXRXDEVICE "/dev/ttyS1"    // COM2 
-   
- #define BAUDRATE B38400      // Las ctes. estan definidas en asm/termbits.h 
- #define ENDMINITERM 2      // Ctrl+B para salir de miniterm 
-   
- #define _POSIX_SOURCE 1     // Fuente compatible POSIX 
-   
- #define FALSE 0 
- #define TRUE 1 
-   
- #define STDIN 0 
- #define STDOUT 1 
-   
- volatile int STOP = FALSE;    // flag de salida 
-   
- // Esta funcion recibe el numero de senyal que emita el proceso hijo. Como la unica que va a emitir 
- // es la de finalizar, siempre va a poner STOP a TRUE 
- void child_handler(int s) 
- { 
-   STOP = TRUE; 
- } 
-   
- // Punto de entrada del programa 
- int main(int argn, char *argv[]) 
- { 
-   int   fd,  // Descriptor del dispositivo de E/S 
-     c;  // Lectura de caracteres del teclado 
-   struct termios oldDevice, newDevice, oldStdin, newStdin, oldStdout; 
-   
-   struct sigaction sa;  // Para manipular el proceso hijo 
-   
-   /* 
-   ================================================= 
-   APERTURA DEL DISPOSITIVO DE TRANSMISION/RECEPCION 
-   ================================================= 
-   */ 
-   // Abre el dispositivo de transmision para lectura y escritura y no como controlador tty, ya 
-   // que no queremos cortar si el ruido de la linea envia un Ctrl+C 
-   fd = open(TXRXDEVICE, O_RDWR | O_NOCTTY); 
-   if (fd < 0) 
-   { 
-     perror(TXRXDEVICE); 
-     exit(-1); 
-   } 
-   
-   /* 
-   ============================================ 
-   GUARDAR TODAS LAS CONFIGURACIONES ANTERIORES 
-   ============================================ 
-   */ 
-   // Lo primero es guardar todas las configuraciones anteriores de los dispositivos 
-   tcgetattr(fd, &oldDevice);  // Guarda la configuracion actual del dispositivo de transmision 
-   tcgetattr(STDIN, &oldStdin);  // Guarda la cfg de STDIN 
-   tcgetattr(STDOUT, &oldStdout);  // Guarda la cfg de STDOUT 
-   
-   /* 
-   =============================== 
-   CONFIGURA EL DISPOSITIVO DE E/S 
-   =============================== 
-   */ 
-   // Configura el ratio de bps, el flujo de control por hardware y 8n1 (8 bits, sin paridad, 
-   // 1 sopbit). Tambien no colgar automaticamente e ignorar el estado del modem. Finalmente 
-   // habilita la recepcion de caracteres. 
-   newDevice.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; 
-   
-   // Ignora bits con errores de paridad 
-   newDevice.c_iflag = IGNPAR; 
-   
-   // Salida 
-   newDevice.c_oflag = 0; 
-   //                                                               , 
-   // No hacer eco con caracteres, ya que si te conectas a un host, el o el modem lo hara por ti. 
-   // No generar senales. 
-   newDevice.c_lflag = 0; 
-   
-   // Bloquea la lectura hasta que un caracter llega 
-   newDevice.c_cc[VMIN]=1; 
-   newDevice.c_cc[VTIME]=0; 
-   
-   // Ahora limpia la linea del modem y activa su configuracion 
-   tcflush(fd, TCIFLUSH); 
-   tcsetattr(fd, TCSANOW, &newDevice);  // Aplica la nueva cfg 
-   
-   /* 
-   ======================= 
-   CONFIGURACION DE STDOUT 
-   ======================= 
-   */ 
-   tcsetattr(STDOUT, TCSANOW, &newDevice); // Configura stdout como si fuera el dispositivo de E/S 
-   
-   /* 
-   ====================== 
-   CONFIGURACION DE STDIN 
-   ====================== 
-   */ 
-   tcgetattr(STDIN, &newStdin);     // obtengo la cfg de stdin 
-   newStdin.c_lflag &= ~(ICANON | ECHO);  // la modifico para detener el eco por pantalla y el buffering 
-   tcsetattr(STDIN, TCSANOW, &newStdin);  // y la aplico 
-   
-   /* 
-   ========================= 
-   MANEJAR LA ENTRADA/SALIDA 
-   ========================= 
-   */ 
-   switch (fork())  // Crea un proceso hijo que es instancia de este. Retorna 0 si estamos en el hijo, -1 si hubo error o el PID del hijo si estamos en el padre 
-   { 
-   case 0:  // ==== Si ahora estamos en el hijo ==== 
-     //close(STDOUT); 
-     for (c=getchar(); c!=ENDMINITERM; c=getchar())  // Lee los caracteres desde el usauario hasta que se introduzca Ctrl+B (ENDMINITERM) 
-       write(fd,&c,1);        // Los va escribiendo en el dispositivo de salida 
-     tcsetattr(fd, TCSANOW, &oldDevice);  // Restaura la antigua configuracion del dispositivo de E/S 
-     tcsetattr(STDIN, TCSANOW, &oldStdin);  // Restaura la antigua cfg de Stdin 
-     close(fd);        // Cierra el dispositivo E/S 
-     exit(0);        // envia SIGCHLD al padre 
-     break; 
-   
-   case -1:// ==== Si hubo un error y no fue creada la instancia ==== 
-     perror("fork"); 
-     tcsetattr(fd, TCSANOW, &oldDevice);  // Restaura la cfg del dispositivo 
-     close(fd);        // Lo cierra 
-     exit(-1); 
-   
-   default:// ==== Si ahora estamos en el padre ==== 
-     //close(STDIN); 
-     sa.sa_handler = child_handler;  // Puntero a la funcion de manipulacion de senyales del hijo 
-     sa.sa_flags = 0;    // No son necesarias ninguna flag en especial 
-     sigaction(SIGCHLD, &sa, NULL);  // Aplica la cfg de la manipulacion del proceso hijo 
-     while (STOP==FALSE)    // Mientras que la funcion child_handler no indique que el hijo ha finalizado 
-     { 
-       read(fd, &c, 1);  // Lee desde el dispositivo 
-       write(STDOUT, &c, 1);  // Lo escribe por pantalla 
-     } 
-     tcsetattr(STDOUT, TCSANOW, &oldStdout);  // Restauro la cfg de STDOUT 
-     wait(NULL);  // Espera a que el proceso hijo sea matado o quede zombi 
-     break; 
-   } 
-   return 0; 
- } 
-