martes, 2 de abril de 2013

Limpiar la entrada estándar en C en Linux, fflush(stdin)

Uno de los problemas que surgen a la hora de programar en C en Linux es que no podemos limpiar los caracteres no deseados que quedan almacenados en ocasiones en la entrada estándar, ya que al ejecutar la función fflush(stdin) no tiene efecto al usarse sobre el flujo de entrada.

Podemos solucionar este problema usando una función como la siguiente:


void fflushin()
{

 int d, i=0;

 d = stdin->_IO_read_end - stdin->_IO_read_ptr;

 for(i=0; i<d; i++)
  getchar();
}


La operación stdin->_IO_read_end - stdin->_IO_read_ptr nos permite calcular el número de caracteres que quedan almacenados en la entrada estándar a partir de la posición actual del puntero (osea, los caracteres sobrantes), después solo tenemos que ejecutar la función getchar() tantas veces como caracteres haya, para limpiar así la entrada estándar y deshacernos de esos caracteres no deseados.


EJEMPLO DE USO

Una situación muy habitual en la que es necesario usar una función como la anterior es la siguiente:

#include <stdio.h>

main()
{

 int num;

 printf("\nInserta un numero: ");
 
 scanf("%d", &num);

 printf("numero insertado: %d", num);

 printf("\n\nPulsa enter para continuar\n\n");

 getchar();
}


En el programa anterior tenemos la intención de usar la función getchar() para pausar la ejecución del programa hasta que el usuario pulse la tecla enter, pero debido a la función scanf se queda un caracter sin leer en la entrada estándar (el caracter de nueva linea), caracter que leerá la función getchar() sin detenerse como teníamos previsto.

Para solucionarlo lo único que tenemos que hacer es limpiar los caracteres no deseados que se han quedado en la entrada estándar usando la función fflushin() que hemos definido:



#include <stdio.h>

void fflushin()
{

 int d, i=0;

 d = stdin->_IO_read_end - stdin->_IO_read_ptr;

 for(i=0; i<d; i++)
  getchar();
}

main()
{

 int num;

 printf("\nInserta un numero: ");
 
 scanf("%d", &num);

 printf("numero insertado: %d", num);

 printf("\n\nPulsa enter para continuar\n\n");

 fflushin();

 getchar();
}




Y de esta manera el programa funciona tal y como habíamos planeado ya que la función fflushin() ha limpiado esos caracteres no deseados de la entrada estándar y por lo tanto la función getchar() detiene la ejecución del programa hasta que el usuario pulse la tecla enter.

Saludos =)


domingo, 3 de marzo de 2013

Netstat, ¿Quién está conectado a mi ordenador?

Buenas, en muchas ocasiones queremos saber si algún programa de nuestro ordenador se está conectando con otro programa en otro ordenador a través de la red, o dicho de otra manera, queremos saber si algún programa está haciendo uso de la red (conectándose a internet o a otro ordenador de nuestra propia red).

En esta entrada os enseñaré como ver las conexiones de red que tiene establecidas vuestro ordenador usando netstat. Gracias a esto podréis saber que programas están haciendo uso de la red, lo cual os puede servir además de para saber que programas en cuestión están haciendo uso de la red también para detectar posibles programas no autorizados que estén haciendo uso de la red en vuestro ordenador.

Bien, para saber que programas tienen alguna conexión establecida usaremos netstat, este programa viene en todos los sistemas linux (no necesitáis instalar nada), el programa lo ejecutaremos desde la línea de comandos.

Nota: Usando este método solo veremos los programas que usen una transmisión TCP, ya que UDP no está orientado a conexión (por lo tanto no existe ninguna conexión), de todos modos la gran mayoría de los programas usan TCP y no UDP.

El programa lo podemos ejecutar sin mas, osea, simplemente abrimos una shell y tecleamos netstat pero este método no es muy eficiente, ya que la salida de datos que nos dará el programa es demasiado grande y será demasiado liosa como para sacar conclusiones, así que os daré un par de opciones para usar con el programa para que produzca una salida mas limpia y fácil de interpretar.

Algunas de las opciones que podemos incluir son las siguientes:

-n: muestra la dirección y el puerto de manera numérica, esta opción en ocasiones puede interesarnos quitarla, para que se nos muestre el nombre de dominio y el nombre del puerto.

-t: muestra las conexiones TCP.

-p: muestra el nombre del proceso (programa) relacionado con la conexión.

Ejecutamos netstat con estas opciones:


netstat -ntp


y obtenemos una salida tal que así:





Nota: La salida ha sido truncada con el fin de que no rompa la estructura del blog, de todos modos la salida real es prácticamente la misma, solo he dejado los campos que me interesa comentar.

Los datos que nos muestra netstat son los siguientes:

Local Address: dirección de origen, con el formato IP:PUERTO.

Foreign Address: dirección de destino, con el formato IP:PUERTO.

State: Existen varios estados para las conexiones, pero principalmente los que veremos mas comúnmente son ESTABLISHED que indica que hay una conexión establecida, TIME_WAIT que indica que hay una comunicación en proceso de ser cerrada y CLOSE_WAIT que indica que hay una comunicacion cerrada por el extremo remoto y esperando a que el extremo local la finalice.

PID/Program name: indica el PID (identificador de proceso) y el nombre del proceso que esta participando en esa conexión.

En esta ocasión podemos observar que hay dos programas que tienen alguna conexión establecida, uno de ellos es telnet, y el otro es ftp, en este caso podemos ver que telnet esta conectado a través del puerto 23 con la dirección 192.168.120.30, osea que esta conectado a un dispositivo que esta en mi red, y el ftp esta conectado a través del puerto 21 con la dirección 208.118.235.20 que se corresponde con la dirección ip de ftp.gnu.org, en esta ocasión podría habernos beneficiado el quitar la opción -n para poder ver el nombre de dominio.

En el ejemplo anterior la salida se ve muy clara, ya que los programas solo establecen una conexión cada uno, pero por otra parte tendremos que tener cuidado con otros programas, como por ejemplo navegadores web o programas P2P, ya que estos programas suelen establecer varias conexiones y a la hora de hacer una consulta con netstat puede resultar un poco confuso y extraño, pero en realidad es algo normal, ya que por ejemplo cuando un navegador solicita una pagina web tiene que realizar varias conexiones a distintos sitios para poder obtener algunos elementos de la pagina web, como pueden ser imágenes o vídeos por ejemplo.

Si tenemos un navegador web abierto podríamos obtener una salida tal que así:





Como podemos ver en este caso el navegador tiene 3 conexiones establecidas, dos de ella son a través de https (puerto 443) y otra a través de http (puerto 80).

En caso de que queramos detectar algún programa no autorizado haciendo uso de la red podemos cerrar todos los programas que nosotros sabemos que realmente están haciendo uso de la red, como pueden ser el navegador web, un cliente ftp, programas p2p, cliente de correo...etc. una vez cerrados todos los programas, al ejecutar netstat nos debería de mostrar una salida vacía tal que así:





Si se nos mostrase algo, tendríamos que analizar exactamente de que programa se trata.

Nota: OJO! si acabáis de cerrar programas quizás se sigan mostrando con el netstat, probablemente con el estado TIME_WAIT o CLOSE_WAIT, en este caso solo tendríais que esperar a que las conexiones finalizasen del todo.

Quizá podría tratarse simplemente de algo inofensivo, como un programa del sistema buscando actualizaciones o algo parecido, de todos modos en caso de que se muestre algo y no sepáis exactamente de que programa se trata os recomiendo que primero busquéis información en Google sobre el nombre del proceso, si aun así no conseguís resolver las dudas os recomiendo matar el proceso, podéis hacerlo usando el comando kill y el numero identificador de proceso (PID) que muestra el netstat, de manera que si por ejemplo el proceso tuviese el PID 5430 lo mataríamos usando:


kill -s 9 5430


la opción -s 9 se usa para matar directamente el proceso.


y hasta aquí por ahora, espero que os haya gustado

Saludos :D


Número áureo (cálculo alternativo)

Holas, hace unas semanas publiqué una entrada en la que explicaba lo que era el número áureo y como se calculaba a partir de la secuencia de Fibonacci.

En esta entrada os mostraré una manera alternativa de calcular el número áureo, lo cierto es que esta manera de calcularlo me parece super curiosa, mas que nada por las operaciones que se realizan...

El cálculo en cuestión es el siguiente:


1+(1/1+(1/1+(1/1+(1/1+(1/1+(1/1))))))


La operación a simple vista puede parecer un poco engorrosa, pero realmente es una operación muy sencilla, lo único que estamos haciendo es sumar uno mas uno, y después dividir el segundo operando de la suma (el segundo uno) entre uno mas uno, y así seguido, la operación se puede repetir hasta el infinito, de manera que cuantos mas bucles realicemos mas preciso será el número áureo que obtengamos.

Y al igual que con el otro método, en esta ocasión también he diseñado un código para calcular el número áureo usando este método, os lo dejo a continuación:



#include <stdio.h>

int main(int argc, char *argv[])
{

 if(argc<2)
 {
  printf("\nSe necesita un argumento\n\n");
 
  return -1;
 }

 if(!(atoi(argv[1]) > 0 && atoi(argv[1]) <=37))
 {
  printf("\nEl argumento debe estar entre 0 y 37\n\n");

  return -1; 
 }

 int max, i=0;

 double inc = 1;

 max = atoi(argv[1]);

 for(i=0; i < max; i++)
 {
  inc=(double)1/((double)1+inc);

 }

printf("\nNumero Aureo: %.50lf\n\n", (double)1+inc);


}


Para usar el programa solo hay que indicarle como argumento el número de bucles que realizará el programa para calcular el número áureo.

y esto es todo por ahora.

Saludos =)


domingo, 27 de enero de 2013

Visor hexadecimal

Buenas, en esta entrada os traigo algo que tenía ganas de hacer hace tiempo, un programa para ver los datos de un archivo en formato hexadecimal.

Este tipo de programas es algo que suelo usar bastante, así que ademas de servirme como práctica de programación también es algo a lo que le voy a dar bastante uso.

La verdad es que me gusta la simplicidad con la que he diseñado el programa. De momento el programa solo visualiza los datos, pero probablemente modifique el programa para que también permita editarlos.

Cuando ejecutéis el programa os saldrán dos columnas, a la izquierda os aparecerán los datos en hexadecimal y a la derecha los caracteres ASCII imprimibles.

En la columna de la derecha, donde se visualizan los caracteres imprimibles, he decidido poner solo los caracteres básicos, del ASCII 33 al 126, y no los extendidos, ya que varían según la codificación que se use.

Os dejo el código a continuación:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
 FILE *arc;

 int i=0, k=0, h=0, j=0, m=0, x=0;
 int **car = NULL;


 if(argc<2)
 {
  printf("\nFaltan un argumento\n\nModo de uso: %s \n\n", argv[0]);
 
  exit(-1);
 }


 if((arc = fopen(argv[1], "r")) == NULL)
 {
  printf("\nError al abrir el archivo\n\n");
 
  exit(-1);
 }


 while(!ferror(arc) && !feof(arc))
 {

  if ((car = (int **)realloc(car, (i+1) * sizeof(int *))) == NULL)
  {
   printf("\nError al asignar memoria\n\n");
   exit(-1);
  }


  if((car[i] = (int *)malloc(16 * sizeof(int))) == NULL)
  {
   printf("\nError al asignar memoria\n\n");

   exit(-1);
  }


  for(k=0; k<16; k++)
  {
  
   car[i][k] = fgetc(arc);

  }

  i++;

 }

 if(ferror(arc))
 {
  perror("\nSe ha producido un error durante la lectura\n\n");
 }


 printf("\n\n");


 for(h=0; h<i; h++)
 {
  for(j=0; j<16; j++)
  {
  
   if(car[h][j]==-1)
   {
    for(x=0; x < (16-j); x++)
     printf("   ");

    break;
   }
   else
   {
    if(car[h][j]<16)
    {
     printf("0%X ",car[h][j]);
    }
    else
    {
   
     printf("%X ", car[h][j]);
    }
   
   
   }

  }

  printf("\t");

  for(j=0; j<16; j++)
  {
 
   if(car[h][j]==-1)
   {
    break;
   }
   else
   {
   
    if((car[h][j] > 32) && (car[h][j] < 127))
    {
    
     printf("%c",car[h][j]);
   
    }
    else
    {
    
     printf(".");

    }
   }
  }


 printf("\n");
 
 }

 printf("\n\n");


 for(m=0; m<i; m++)
  free(car[m]);


 free(car);

 fclose(arc);


 return 0;

}
 


lo compilamos con:


cc hexa.c -o hexa


Para ejecutarlo solo tenemos que indicar como argumento el nombre de archivo que queremos visualizar:


./hexa <nombre_archivo>


Si el archivo a visualizar es demasiado grande probablemente el shell os trunque el principio de los datos, en esos casos os recomiendo redireccionar la salida del programa a un archivo tal que así:


./hexa archivo.jpg > prueba


y a continuación visualizar el archivo resultante desde un editor de texto.

espero que os haya gustado

Saludos =)



domingo, 20 de enero de 2013

La proporción áurea y la secuencia de Fibonacci

La proporción áurea es una proporción que se encuentra en la naturaleza y que tiene una característica especial, todos los objetos que tienen una proporción áurea nos resultan mas agradables a la vista.



El rectángulo anterior tiene una proporción áurea, ya que si dividimos su largo por su alto nos da 1,6 que es aproximadamente la proporción áurea.

Dada esta característica, la proporción áurea es habitualmente usada en el mundo del arte y en muchos objetos cotidianos, para que nos parezcan "mas bonitos".

Una de las maneras de calcular el número áureo es usando la secuencia de Fibonacci, que es una secuencia de números que también se encuentra en la naturaleza.

Para calcular la secuencia de Fibonacci solo tenemos que realizar la suma de un número de la secuencia mas el número anterior a ese en la secuencia, siendo los dos primeros números de la secuencia el 0 y el 1, de manera que los primeros números de la secuencia son:


0 1 1 2 3 5 8 13...


y para calcular el número áureo solo tenemos que dividir un número de la secuencia entre el número anterior a ese en la secuencia, teniendo en cuenta que el número áureo sera mas preciso cuanto mas avanzada esté la secuencia de Fibonacci, de manera que obtendremos un número áureo mas preciso si dividimos por ejemplo 13/8 que si dividimos 8/5.

Aprovechando la ocasión he creado un programa que calcula la secuencia de Fibonacci y opcionalmente muestra el número áureo calculado con los dos últimos números de la secuencia.

Os dejo el código a continuación:


#include <stdio.h>
#include <stdlib.h>

int fibonacci(unsigned long **, long);

int main(int argc, char *argv[])
{
unsigned long *num, i=0, max;
double aur;

if(argc==1)
{
printf("\nFalta tamaño de la secuencia\n\n");
printf("Modo de uso: %s <tamaño secuencia> [a]\n\n",argv[0]);
exit(-1);
}

max = atoi(argv[1]);

if(max>=95)
{
 printf("\nEl tamaño maximo es 94\n\n");

 exit(-1);
}


printf("\n");

fibonacci(&num, max);

i=0;

for(i=0;i<max;i++)
 printf("%lu\n\n",num[i]);


if(argc==3 && argv[2][0]=='a')
{
aur = (double)num[i-1]/(double)num[i-2];

printf("\nNumero aureo: %.50lf\n\n", aur);
}

free(num);

}


int fibonacci(unsigned long **num, long max)
{
  int i=0;
  
  *num = (unsigned long *)malloc(max * sizeof(long));

 for(i=0; i<max; i++)
 {
  if(i==0)
  {
   (*num)[i]=0;
  }
  else if(i==1)
  {
   (*num)[i]=1;
  }
  else
  {
  (*num)[i] = ((*num)[i-1]+(*num)[i-2]);

  }
 }
}



El programa lo compilamos usando:


gcc fibonacci.c -o fibonacci


Para ejecutar el programa tenemos que indicar un parámetro, que es la cantidad de números que queremos que tenga la secuencia, por ejemplo


./fibonacci 7


El ejemplo anterior nos mostrara los 7 primeros números de la secuencia de Fibonacci

Opcionalmente podemos indicar un segundo parámetro para que el programa calcule el número aureo usando los dos últimos números de la secuencia, para ello solo tenemos que indicar la letra 'a' como segundo parámetro, por ejemplo:


./fibonacci 7 a


Espero que os haya gustado

Saludos =)



sábado, 12 de enero de 2013

Cifrado del César

La criptografía es algo que me llama bastante la atención, es una de esas cosas en las que me gustaría profundizar en un futuro (preferiblemente un futuro cercano jeje).

Así que en base a esto se me ocurrió hacer un programa que usase un cifrado simple para cifrar cadenas de caracteres, y que mejor para un novato que usar una de las técnicas criptograficas mas simples que existen, el cifrado del César.

Para los que no lo conozcáis, el cifrado del Cesar es un algoritmo criptografico que consiste simplemente en coger una cadena de caracteres y desplazar cada uno de sus caracteres una cantidad fija de posiciones en el alfabeto, probablemente sea el algoritmo criptografico mas simple que existe.

Poniendo un ejemplo, si cogiésemos la cadena "hola" y desplazásemos todos sus caracteres 5 posiciones hacia adelante en el alfabeto nos quedaría la cadena "mtqf", en el caso de que quisiésemos descifrar la cadena para obtener de nuevo la cadena original pues tendríamos que hacer el proceso inverso y desplazar todos los caracteres 5 posiciones hacia atrás.

Antes de ni siquiera empezar a pensar en el código del programa pensé que me llevaría bastantes lineas de código realizarlo, pero para mi sorpresa cuando me puse a programarlo me di cuenta de que el programa se podía realizar con una pequeña cantidad de lineas de codigo, es curioso como a veces algo que piensas que puede ser complicado al final resulta sencillo.

Os dejo el código del programa a continuación:


#include <stdio.h>

int main(int argc, char *argv[])
{
char c;

if(argc==1)
{
 printf("\nModo de uso: %s \n\n",argv[0]);

 return 0;
}

while((c=getchar()) != EOF)
{
if(c=='\n')
{
 printf("\n");
}
else if(c==' ')
{
 printf(" ");
}
else
{
 printf("%c",c+atoi(argv[1]));

}
}
return 0;
}



Para compilar el programa simplemente lo guardáis en un archivo "cesar.c" y ejecutáis el compilador tal que así:


gcc cesar.c -o cesar


Para usar el programa tendréis que ejecutarlo con un parámetro, este parámetro es el numero de cifrado que queréis usar (lo que equivaldría al desplazamiento de las letras en el alfabeto)

Imaginaros que queremos realizar el ejemplo que os ponía antes, pues lo haríamos de la siguiente manera, primero ejecutamos el programa tal que así:


./cesar 5


Después de ejecutarlo, el programa se queda a la espera de que introduzcamos una cadena de caracteres, así que introducimos "hola" y pulsamos enter y el programa a continuación nos muestra el resultado encriptado:



Si lo deseamos podemos seguir introduciendo cadenas de caracteres y el programa las ira traduciendo una a una, cuando queramos finalizar la ejecución del programa podemos hacerlo con control+c o control+d.

Para desencriptar este mensaje seguiríamos el mismo proceso, pero esta vez en vez de poner 5 como parámetro pondríamos -5, así desharíamos la encriptacion:



El numero de cifrado puede oscilar entre 0 y 255, en este aspecto podríamos decir que es una mejora del cifrado del César ya que no solo usa los caracteres del alfabeto sino que uso todos los caracteres ASCII.

También podéis usar el programa para cifrar archivos (archivos de texto plano), podéis hacerlo usando una doble redirección en el shell tal que así:


./cesar 24 < prueba > prueba_cifrado


Donde prueba es el archivo que queremos cifrar y prueba_cifrado es el archivo resultante ya cifrado.

Para descifrar el archivo lo haríamos así:


./cesar -24 < prueba_cifrado > prueba_descifrado


Donde prueba_cifrado es el archivo que ciframos anteriormente y prueba_descifrado el archivo ya descifrado, osea el archivo original.

Espero que os haya gustado, Saludos =D