Cliente VNC no refresca

Hoy me ha ocurrido un efecto curioso. Conectaba al portatil de mi casa por VNC y solo me mostraba el primer pantallazo inicial, no refrescaba nada …

Volví a casa y haciendo pruebas vi que me ocurre desde que active el compiz (solo lo utilizo por el scale). Entonces la solución aunque no es la mejor, es buena, desactivar el composite/compiz.

Por cierto si vais mal de subida, el visor de escritorio remoto va a Full Color y realmente se toma su tiempo cada frame. Instalar “xvnc4viewer”, y simplemente con “vncviewer xx.xx.xx.xx” conectamos en 8 bits, funciona muy fluido, y para administración es más que suficiente. No obstante si quereis 24 bits (Full Color) añadir el parametro “-FullColor”.

Pasar secuencia de imagenes a video

En concreto lo estoy utilizando para las animaciones generadas por blender en archivos png:

ffmpeg -y -f image2 -i %4d.png -b 10800k render.avi && gnome-open render.avi

Obtener información de Binarios y librerías compartidas (nm/objdump)

nm – Listado de funciones de un objeto

Si queremos obtener un listado de funciones que tiene un código objeto o una librería compartida se utiliza “nm”, que lo descubrí de casualidad.
Este comando lista todos los símbolos que contiene el código objeto o la librería dinámica.
Por ejemplo vamos a crear una librería dinámica con solo una función llamada “factorial”.
Este es el código:

#include <stdio.h>

int factorial(int n)
{
    return n == 0 ? 1 : n * factorial(n-1);
}

Lo compilo así:

gcc factorial.c -o libfactorial.so -shared -fPIC

Ahora analizamos la librería con el comando “nm”:

nm -D libfactorial.so

Obtenemos esto:

         w _Jv_RegisterClasses
00002010 A __bss_start
         w __cxa_finalize
         w __gmon_start__
00002010 A _edata
00002018 A _end
000004c8 T _fini
00000314 T _init
0000044c T factorial

Vemos que nuestro función en código maquina esta en el offset del archivo 0x44c.
Si leemos el man, obtenemos el significado de los símbolos:

Symbol Type Description
A The symbol’s value is absolute, and will not be changed by further linking.
B Un-initialized data section
D Initialized data section
T Normal code section
U Undefined symbol used but not defined. Dependency on another library.
W Doubly defined symbol. If found, allow definition in another library to resolve dependency.

Las funciones T son las linkables, exceptuando “_fini” y “_init” que son funciones comunes a cualquier librería dinámica. (Esto es una suposición mía, aunque muy lógica por otra parte).

Un ejemplo de código de linkado típico:

#include <stdio.h>

int factorial(int n);

int main()
{
 printf("5! = %d\n", factorial(5));
 return 0;
}

Se compila así:

gcc link.c -o link -L. -lfactorial

Y como la librería no esta en una ruta estándar, se ejecutaría así:

export LD_LIBRARY_PATH="." && ./link
5! = 120

Vamos a probar un código que linke dinamicamente, pero en lugar de el fácil “-lname”, lo haré con el dload, que nos sirve de ejercicio para entender como funcionan las librerías dinámicas. El código es el siguiente:

#include <stdio.h> // para fprintf
#include <stdlib.h> // para exit
#include <dlfcn.h>  // para dlopen, dlsym, dlerror, dlclose

int factorial(int n);

int main(int argc, char **argv)
{
 void *lib_handle;
 int (*factorial)(int);
 int x;
 char *error;

 lib_handle = dlopen("libfactorial.so", RTLD_LAZY);
 if (!lib_handle)
 {
 fprintf(stderr, "%s\n", dlerror());
 exit(1);
 }

 factorial = dlsym(lib_handle, "factorial");
 if ((error = dlerror()) != NULL)
 {
 fprintf(stderr, "%s\n", error);
 exit(1);
 }

 x = factorial(5);
 printf("5! = %d\n",x);

 dlclose(lib_handle);
 return 0;
}

El código hay que mirarlo detenidamente, especialmente el puntero a función, pero por lo demás, es sencillo y se autocomenta.
Se compila así:

gcc -rdynamic -o dlopen dlopen.c -ldl

Probamos el ejecutable:

export LD_LIBRARY_PATH="." && ./dlopen
5! = 120

objdump – Desensamblando de binarios

Con este comando podemos obtener el código en ensamblador a partir del código maquina. El comando es el siguiente:

objdump -d libfactorial.so

Si además lo compilamos introduciendo los símbolos de debugeo (parámetro -g), podemos ver el código en ensamblador combinado con el código fuente. Se añadiría el parametro -S:

objdump -d -S libfactorial.so

Ya sabíamos que nuestra función “factorial” estaba en el offset 0x44c, por tanto lo busco en la salida de objdump y pasteo la salida (en este caso, con símbolos de debugeo):

0000044c <factorial>:
#include <stdio.h>

int factorial(int n)
{
 44c:	55                   	push   %ebp
 44d:	89 e5                	mov    %esp,%ebp
 44f:	53                   	push   %ebx
 450:	83 ec 14             	sub    $0x14,%esp
 453:	e8 ef ff ff ff       	call   447 <__i686.get_pc_thunk.bx>
 458:	81 c3 9c 1b 00 00    	add    $0x1b9c,%ebx
    return n == 0 ? 1 : n * factorial(n-1);
 45e:	83 7d 08 00          	cmpl   $0x0,0x8(%ebp)
 462:	74 14                	je     478 <factorial+0x2c>
 464:	8b 45 08             	mov    0x8(%ebp),%eax
 467:	83 e8 01             	sub    $0x1,%eax
 46a:	89 04 24             	mov    %eax,(%esp)
 46d:	e8 f2 fe ff ff       	call   364 <factorial@plt>
 472:	0f af 45 08          	imul   0x8(%ebp),%eax
 476:	eb 05                	jmp    47d <factorial+0x31>
 478:	b8 01 00 00 00       	mov    $0x1,%eax
}
 47d:	83 c4 14             	add    $0x14,%esp
 480:	5b                   	pop    %ebx
 481:	5d                   	pop    %ebp
 482:	c3                   	ret

Con el poco ensamblador que me enseñan en la uni, puedo deducir los siguientes offsets:

45e: Es la comparación de n con 0
462: Si la igualdad anterior se cumple, salta a la línea 44c + 2c = 478
478: Es el interior del IF, iguala el parámetro que viene de la pila con 1. Definiendo 0! = 1
464: Se ejecutaría si la comparación de 45e no se da. Se asigna la vuelta de la recursión
467: Se resta 1 a n
46a: Se prepara e parámetro n-1 en eax, previo a una llamada.
46d: Se hace la llamada recursiva a si mismo.
472: Se multiplica por 8 la vuelta de la recursión.
476: Estamos en el else, por tanto esta jmp se salta el interior del if. 44c + 31 = 47d
47d: De aquí en adelante prepara el return, deja la pila como estaba antes de la llamada y se restaura el IP.

Vamos a hacer algo fácil “crackear”(si se le puede llamar crackeo a esto xD) el programa para cambiar la asignación de:
0!=1 por 0!=4

Por tanto el 5! en lugar de dar 120 va dar 4 veces más, 480.

Para hello abrimos con algún editor de hexadecimal:

ghex2 libfactorial.so

Vamos al OFFSET 479 (478 + 1) y cambiamos el 01 por 04.

Hacemos la prueba de fuego:

export LD_LIBRARY_PATH="." && ./dlopen

Y efectivamente:

5! = 480

OuYeah!


Bueno con esto acabo, este articulo es sobre todo didáctico por lo que si alguno puede completar más el articulo con sus comentarios, se le agradeceremos todos.

Fuentes:
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
http://unixhelp.ed.ac.uk/CGI/man-cgi?nm
http://node1.yo-linux.com/cgi-bin/man2html?cgi_command=ld
http://node1.yo-linux.com/cgi-bin/man2html?cgi_command=ldconfig

Espacio en disco ocupado por un directorio

Un comando muy útil es du. Sirve para calcular el espacio que ocupa un disco un diretorio. Para ello calcula todo lo que tiene dentro del directorio, (recursivamente para el caso de los directorios). El uso simple es pasando el directorio como primer y único parámetro. Por ejemplo:

makiolo@blog:~$ du /home/makiolo/videos/The\ Big\ bang\ Theory/temp2
3048960    /home/makiolo/videos/The Big bang Theory/temp2

Para poner las unidades comprensibles añadimos el parametro -h:

makiolo@blog:~$ du -h /home/makiolo/videos/The\ Big\ bang\ Theory/temp2
3,0G    /home/makiolo/videos/The Big bang Theory/temp2

Mostrando solo los GB libres:

makiolo@blog:~$ du -h /home/makiolo/videos/The\ Big\ bang\ Theory/temp2 | tail -n1 | cut -f1
3,0G

Jugando más con las tuberías:

makiolo@blog:~$ du -h /home/makiolo/videos/The\ Big\ bang\ Theory/temp2 | tail -n1 | awk ‘{print “El directorio “$2” ocupa “$1}’
El directorio /home/makiolo/videos/The Big bang Theory/temp2 ocupa 3,0G

Me hago un script final que es el que usaré, gedit espacioLibre.sh y pasteamos:

#!/bin/sh

if [ $# = 0 ]; then
DIRECTORIO=`pwd`
else
DIRECTORIO=$1
fi;

du -h $DIRECTORIO | tail -n 1 | awk ‘{print “El directorio ” $2 ” ocupa ” $1}’

Procesar y borrar elementos de una lista en O(n)

Voy a explicar que elección de diseño he elegido en mi juego para la gestión de la lista de entidades.

En todo videojuego hay una lista de entidades que necesitan hacer en su máximo nivel de abstracción 2 cosas:

  1. Procesar todos los elementos. Esto es que cada elemente tiene un metodo, tipicamente refrescar() o update() que abstrae toda la secuencia de proceso que tiene que hacer.
  2. Borrar los elementos que han muerto o a terminado su ciclo de vida.

Poder borrar el elemento de lista me dificulta la implementación, asi que he optado por que el nodo tenga un método en el que solicita la liberación. Cuando llege su turno será eliminado. Esto tambien lo hago así por que physX exige borrar sus entidades en puntos muy concretos de muy código. Cuando no lo hacía así cada 5 min de juego tenía un “segmentation fault” que me crasheaba el juego.

Hay infinitos ejemplos por los que hay que borrar una entidad. Un bot que ha cumplido su objetivo.
Por ejemplo, suponer que una entidad (un proyectil en concreto) que se mueve, esto lo hace durante el refresco, se sale del mapa, cuando se salga queremos borrarlo. Por tanto en pseucódigo será.

if(estoyDentroDeLimites())
	avanzar();
else
	pedirLiberacion();

Cuando a otro nivel llamamos al proceso de las entidades, el proceso debería quedar algo así.

void procesarSeleccionados ( list<Nodo*> * lista )
{
	Nodo * aux = NULL;
	list::iterator it = lista->begin();
	while(it != lista->end())
	{
		aux = *it;
		if(aux->getPedirLiberacion() && aux->liberar())
		{
			delete aux;
			it = lista->erase(it);
		}
		else
		{
			aux->refrescar();
			i++;
		}
	}
}

Estoy utilizando una lista del STD.  Comentar:

  • El if() podríamos sustituirlo por la condición de borrado. En este ejemplo significa:
    • si quieres que te borren. getPedirLiberacion()
    • Y te has borrado correctamente. && aux->liberar()
  • La función erase() borra a lo que apunta el iterador y automaticamente te avanza el iterador, teniendo siempre un iterador válido. Por eso el i++ esta en el else, si lo pusioramos fuera nos saltariamos un elemento de la lista cada vez que borremos.

Compactar BDD sqlite de Firefox 3

Bueno por fin he acabado los examenes y tengo bastantes posts acumulados(en mi cabeza) y que iré publicando cuando tenga tiempo.

Lei en Barrapunto que compactando la BDD de sqlite de Firefox 3 teóricamente debería acelerar las consultas, inserciones, borrados y todas las operaciones que conlleva una base de datos. Si esto es cierto, deberíamos ejecutar este script de vez en cuando. Hablo de teóricamente por que no he hecho benchmarkings pero tener más que fe que esto acelera un cierto tipo de consultas, y si no al menos reducimos el espacio en disco. Creaamos con gedit compactarFirefox.sh y pasteamos:

#!/bin/sh

for f in ~/.mozilla/firefox/*/*.sqlite; do sqlite3 $f 'VACUUM;'; done

Realmente espero que en  futuras versiones de firefox, el mismo se automantenga cada cierto tiempo, ya que estas cosas a las que ya hace años nos mal acostumbro M*cro**ft con al access. Y pienso que el aumantenimiento de las base de datos incrustadas debería ser un proceso totalmente transparente al usuario.

sed – stream editor for filtering and transforming text

Este comando junto con awk(que uso más todavía que este) es obligatorio que aprendais a usarlos poco a poco. En concreto sed permite cosas como borrar líneas, registros o sustituir cadenas de caracteres dentro de las líneas. Típicamente se usa en tuberías, aunque es un programa totalemente autónomo.

* Para borrar una línea hacemos lo siguiente:

sed ‘nº_de_línead’ fichero

* Podemos indicar un número de línea concreto. Por ejemplo:

sed ‘1d’ fichero

* Podemos indicar un intervalo de líneas a borrar. Por ejemplo:

sed ‘3,5d’ fichero

* También podemos indicar que queremos borrar desde una determinada línea en adelante:

sed ‘3,$d’ fichero

* Otro ejemplo útil es borrar las líneas en blanco de un fichero:

sed ‘/^$/d’ fichero

A la hora de borrar, también podemos especificar una cadena, de tal forma que el comando borrará todas las líneas que contengan esa cadena. Ejemplo:

cat fichero | sed ‘/^[ ]*$/d’ > ficherodestino

Lo anterior borrará todas las líneas en blanco de fichero.

Otro de los usos más interesantes de sed es sustituir cadenas. Podemos sustituir una cadena por otra de la siguiente manera:

sed ‘s/cadena1/cadena2/’ fichero

Al ejecutar el comando anterior, se sustituye la primera cadena que encuentra por la segunda. Pero, si lo que queremos es sustituir todas las cadenas que encuentre, en cada una de las líneas, añadimos el parámetro g :

sed ‘s/cadena1/cadena2/g’ fichero

De aqui podemos encontrar una aplicación particular que me ha sido útil. Es un poco confuso pero no es más que la sustitución de todos los espacios por “\ “(contrabarra+espacio). Es es muy util en bash cuando a veces pasas por parametro ficheros y por algún motivo no sirve mterlo entre comillas.

sed ‘s/\ /\\ /g’

Por otra parte, también podemos hacer que sustituya la cadena1 por la cadena2 en un número de línea concreto:

sed ‘5 s/USUARIO/usuario/g’ fichero

Con cadenas de texto normales la cosa es sencilla, pero al que más y al que menos le resulta complicado cuando lo que hay que sustituir son caracteres especiales como el tabulador: \t o el caracter de nueva línea: \n. Pero veamos como tampoco es complicado: Imaginemos que tenemos un fichero con campos en los que el separador es el tabulador y queremos sustuir este caracter separador por otro caracter separador, como por ejemplo el punto y coma (;). Lo haremos de la siguiente manera:

sed ‘s/\t/;/g’ fichero

Fuente:
http://enavas.blogspot.com/2008/03/el-shell-de-linux-comando-sed.html