/*** mas.c
Version simplificada de more.
Va mostrando por el terminal el contenido de fichero que se pasa como argumento.
muestra un bloque con las primeras 24 lineas del fichero.
Sucesivamente, bajo control del usuario, se va mostrando el fichero bloque a
bloque o linea a linea.
***/
#include <errno.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define PAGE_SIZE 24
// Configura estado del terminal asignado a la entrada estandar
// a modo No Canonico. En SaveTM guarda el estado previo del
// terminal
void SetTermNoCanon( struct termios *SavedTM)
{
struct termios tm;
tcgetattr(0, &tm);
tcgetattr(0, SavedTM);
tm.c_lflag &= ~(ICANON|ECHO);
tm.c_cc[VMIN]= 1;
tm.c_cc[VTIME]= 0;
tcsetattr(0, TCSANOW, &tm);
}
// Recupera el estado del terminal asignado a la entrada estandar
// a un estado previo (SavedTM)
void RestoreTerm( struct termios *SavedTM)
{
tcsetattr(0, TCSANOW, SavedTM);
}
// Muestra max lineas de texto en la salida estandar
int one_page(FILE* fd, int max)
{
int c;
int n= 0;
while ((c=getc(fd)) != EOF) {
putc(c, stdout);
if (c == '\n') n++;
if (n >= max) break;
}
return(n);
}
int main(int argc, char *argv[])
{
int lineas= PAGE_SIZE;
char buf[50];
char c;
int r;
FILE* fp;
struct termios saved_tm;
if (argc!=2){
strcpy (buf, "Uso: mas fichero \n");
write(2, buf, strlen(buf));
exit(1);
}
if ((fp=fopen(argv[1], "r")) == NULL) {
sprintf (buf, "Error al abrir el fichero: %s\n",argv[1] );
write(2, buf, strlen(buf));
exit(2);
}
SetTermNoCanon( &saved_tm );
while (one_page(fp, lineas)) {
if ((r=read(0, &c, 1)) == -1) {
perror("Error al leer de la entrada estandar :"); // Escribe en el canal 2
// sprintf(buf, "Error al leer de la entrada estandar: %s", strerror(errno);
// write(2, buf, strlen(buf));
RestoreTerm(&saved_tm);
fclose(fp);
exit(3);
}
if (r == 0)
lineas= PAGE_SIZE;
else {
switch (c) {
case 'q': RestoreTerm(&saved_tm);
fclose(fp);
return 0;
case ' ': lineas= PAGE_SIZE;
break;
default: lineas= 1;
}
}
}
RestoreTerm(&saved_tm);
fclose(fp);
exit(0) ; // No es necesario
}