CallSytem.c



#include <sys/types.h>
#include <sys/dir.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>




int mindist(char *, char*, char *);
int spname(char *, char *);
int spdist(char *, char *);
void print(FILE *, int );
char ttyin();
FILE *efopen(char *, char *);


#define EQ(s,t)	(strcmp(s,t) == 0)
#define PAGESIZE 22
#define DIRSIZE  14
char *progname;								// nombre del programa para mensajes de error


FILE *efopen(char *file, char *mode)
{
	FILE *fp, *fopen();
	extern char *progname;			// variable definida como global aquí se declara como extern par poderla usar

	if ((fp = fopen(file, mode)) != NULL) return fp;
	fprintf(stderr, "%s: Imposible abrir el archivo %s mode %s\n", progname, file, mode);
	exit(1);
}



// procesamiento de la respuesta a partir de /dev/tty (versión 1)	
char ttyin()
{
	char buf[BUFSIZ];
	FILE *efopen();
	static FILE *tty = NULL;			// es como una variable global

	if (tty == NULL) tty = efopen("/dev/tty", "r");
	if (fgets(buf, BUFSIZ, tty) == NULL || buf[0] == 'q') exit(0);
	else return buf[0];						// línea ordinaria
}


void print(FILE *fp, int pagesize)
{
	static int lines = 0;						// número de líneas hasta aquí
	char buf[BUFSIZ];

	while (fgets(buf, sizeof buf, fp) != NULL )
		if (++lines < pagesize) fputs(buf, stdout);
		else
		{
			buf[strlen(buf)-1] = '\0';
			fputs(buf, stdout);
			fflush(stdout);
			ttyin();
			lines = 0;
		}
}


/*
	spdist:	retorna la distancia entre dos nombres

	parametros poco precisos de escritura:
	0	si las cadebas son idénticas
	1	si dos caracteres están transpuestos
	2	si un carácter está equivocado, de más o de menos
	3	cualquier otra cosa
*/
int spdist(char *s, char *t)
{
	while(*s++ == *t) if(*t++ == '\0') return 0;			// correspondencia exácta
	if(*--s)
	{
		if(*t)
		{
			if(s[1] && t[1] && *s == t[1] && *t == s[1] && EQ(s+2, t+2)) return 1;	// transpuesto
			if(EQ(s+1, t+1)) return 2;			// un carácter extra
		}
		if(*t && EQ(s, t+1)) return 2;				// falta un carácter
		return 3;
	}
}

/*
	spname:	retorna el nombre del archivo correctamente escrito
		-1	si no se encuentra nada parecido a oldname
		0	si concuerda exactamente
		1	si se corrigio
		guarda el nombre correcto en newname
*/

// ==========================
int spname(char *oldname, char *newname)
{
	char *p, guess[DIRSIZE+1], best[DIRSIZE+1], *new=newname, *old=oldname;

	for(;;)
	{
		while(*old == '/') *new++ = *old++;			// saltar las diagonales
		*new = '\0';
		if(*old == '\0') return strcmp(oldname, newname) != 0;	// exacto o corregido
		p = guess;						// copiar el siguiente componente en el nombre supuesto
		for( ; *old != '/' && *old != '\0'; old++)
			if(p < guess + DIRSIZE) *p++ = *old;
		*p = '\0';
		if(mindist(newname, guess, best) >= 3) return -1;	// nada que hacer
		for(p = best; *new = *p++; ) new++;			// agregar al final de newname
	}
}

// Buscar nombre supuesto en el directorio
// ==========================
int mindist(char *dir, char *guess, char *best)
{
									
	int d, nd, fd;
	struct                                      			// escoge el mejor, retorna la distancia 0..3
	{
		ino_t ino;
		char name[DIRSIZE+1];					// 1 mas que en dir.h
	} nbuf;

	nbuf.name[DIRSIZE] = '\0';					// +1 para el '\0' terminal
	if(dir[0] == '\0') dir = ".";					// directorio actual
	d = 3;								// distancia minima
	if((fd = open(dir, 0)) == -1) return d;
	while(read(fd, (char*) &nbuf, sizeof(struct direct)) > 0)
		if(nbuf.ino)
		{
			nd = spdist(nbuf.name, guess);
			if(nd <= d && nd != 3)
			{
				strcpy(best, nbuf.name);
				d = nd;
				if(d == 0) break;			// correspondencia exacta
			}
		}
	close(fd);
	return d;
}

int main(int Argc, char **Argv)
{
	FILE *fp, *efopen();
	int i, pagesize = PAGESIZE;
	char *p, *getenv(), buf[BUFSIZ];

	progname = malloc(sizeof(char)*80);
	strcpy(progname, Argv[0]);
	if ((p = getenv("PAGESIZE")) != NULL) pagesize = atoi(p);
	if ((Argc > 1) && Argv[1][0] == '-')
	{
		pagesize = atoi(&Argv[1][1]);
		Argc--;
		Argv++;
	}
	if (Argc == 1) print(stdin, pagesize);
	else
		for (i = 1; i < Argc; i++)
			switch (spname(Argv[i], buf))
			{
				case -1:			// no hay correspondencia posible
					fp = efopen(Argv[i], "r"); break;

				case 1:
					fprintf(stderr, "\"%s\"? ", buf);
					if (ttyin() == 'n') break;
					Argv[i] = buf;		// aborta
				case 0:				// correspondencia exácta
					fp = efopen(Argv[i], "r");
					print(fp, pagesize);
					fclose(fp);
			}
		exit(0);
}