207f 2008 January
Jan 24

Interesantes proyectos, los de esta semana, para cerrar el viernes uno de telefonía.

Este viernes 25 de Enero del 2008 entrego mi primer Call Center del año, este proyecto es para una residencia, con este servidor Asterisk sustituiré un viejo conmutador.

Este equipo tendrá funciones básicas

IVR
2 FXO y 2 FXS via Hardware digium
Por medio de la red, Vozip con ATAS para extensiones “ilimitadas”
Buzón de voz
Cuarto de conferencia
Extensiones remotas con software o hardware atas, como un IAXY

Funciones adicionales, Capacidad de grabar llamadas

Hardware
Dell Optiplex GX760
Sistema Operativo GNU/Linux
Software de PBX Asterisk

Video mientras se prueba su funcionalidad, antes de la instalación

Para saber mas acerca de lo que Asterisk es bajar esta presentacion.

whatisasterisk.exe

217e
Jan 21

La semana pasada ha sido una semana muy productiva, aunque me dejo muy poco tiempo para escribir en el blog, empezando por la instalación de mi nuevo servidor donde ahora vive la cueva y el broche de oro la consultoría a gran corporativo en el estado de Veracruz.

La misión original era construir un canal seguro entre ellos y Banamex por internet, la cual ha sido un éxito.

Con algo de tiempo les ayude también a migrar unos equipos viejos en FreeBSD a GNU/Linux, estos equipos tenían misiones variadas.

Desde DNS hasta control por listas de acceso a lo mas de 500 usuarios de la oficina, así como la migración del servidor corporativo de correo a GNU/Linux

Por último había que crear un canal seguro entre la oficina corporativa en el puerto de Veracruz con sus consultores en Houston y Monterrey.

Al final, me anoto otro caso de éxito y regrese con un ofrecimiento de trabajo.

Creo que de esta aventura la mejor parte es no haber podido tomar el vuelo de regreso a mi ciudad y tener que regresar por tierra en un autobús de la línea uno. Por qué digo la mejor parte, porque ya tenía varios días sin dormir 8 horas continuas y me sentía ya algo agotado. El viaje de regreso toma 9 horas por tierra y regresar 9 horas sin nada que hacer más que acostarse en el asiento de un UNO y dormirlas, no tiene precio. Jamás me he sentido tan feliz de perder un vuelo.

Aprovechare este articulo para mostrar algunas partes del viaje, me gustaría mostrarles lo que es despegar desde una de las pistas mas chicas de México, yo vivo en una Isla en el golfo de México y no hay tiempo para los errores, nuestros pilotos o hacen despejar la nave o terminara en el golfo de México, como se ve en este video donde despegaba a Veracruz y por cierto el piloto fue muy bueno al llegar a Veracruz, había un frente frio y un viento de no menos de 100 kilómetros por hora, casi me arrebata la laptop en un descuido al salir del avión. Mis felicitaciones para el piloto que logro aterrizar la nave sin tanta sacudida en esas condiciones.

Siempre había querido filmar un despegue, pero no había conseguido una funda capas de bloquear cualquier radiación del aparato, por aquello de la seguridad aeronáutica, así que no, nunca estuvo en riesgo el avión, al menos no por mí.
Estas son unas fotos del viaje.

Vista al Malecon

Vista al Malecon

Site de servidor del corporativo

Site de servidor del corporativo

Site de servidor del corporativo

Jan 21

A principio de la semana pasada y gracias al artículo de desbloqueo de mi Iphone en http://www.lastdragon.net/?p=185 me llegaron 3 personas, casi simultaneas por que habían comprado Iphone y no sabían cómo desbloquearlos y usarlos en México, los 3 Iphone con el firmware 1.1.2 aun no pueden ser liberados por software hasta donde sé, sin embargo. Buscando información en la red encontré varias opciones, desde turbo sim, hasta llegar a la que me convenció el next sim

Aquí está el primer Iphone 1.1.2 que libere.

Es interesante el mundo de las finanzas y los negocios informáticos, nunca sabes por dónde va llegar el próximo billete =) , por lo general me dedico a seguridad informática pero una lana de los iphone no caen mal

Jan 15

Necesito de su ayuda

King of chaos es un juego multiplayer de internet y se trata de defender tu pueblo de los enemigos, así como volverte fuerte para atacar a los demás.

También se pueden formar alianzas

Necesito que entres aquí

http://www.kingsofchaos.com/recruit.php?uniqid=39fsk8f2

le des click a al numero que aparece y si gustas jugar en mi alianza registrarte, claro esto ultimo solo si quieres jugar, si no con un soldado recluta al dar click en ese url me conformo.

Gracias =)

Jan 14

El fin de semana pasado una amiga me pidió ayuda con su programa de fin de semestre, asi que me visito en mi oficina para ayudarla, el unico equipo disponible con compilador de C que tenia era una estación con GNU/Linux.

Desenfundo su memoria USB e inmediatamente trato de mostrarme el programa, por supuesto el .EXE precompilado que tenia, no funciono, asi que intento recompilar en Linux para hacer un ejecutable propio del sistema, pero no compilo.

Revise el código y el 90% era código ANSI, pero el manejo de la consola, no era así, no era portable porque conio.h es una librería de borland C y está prácticamente amarrada al MSDOS, jamás iba a funcionarle el código en Linux, a menos que se modificara y reescribiera una subversión para Linux y pues al final no es difícil portarlo, asi que la ayude con eso también, ahora tiene un programa que compila y funciona en DOS como en Linux

El problema que hay aun en algunas universidades es que siguen enseñando Turbo C y sus librerías privativas como la conio.h y no se les puede culpar de todo, al final de cuentas el manejo de la consola es diferente en cada plataforma, asi que cada plataforma tiene que tener sus propias librerías.

Para el viejo MSDOS, esta el conio y eso estaba bien cuando DOS reinaba, en los tipos de unix como Linux curses no es un estandart por la ANSI sin embargo es un standart defacto en cada unix.

Aquí tratare de mostrar como portar programas de conio.h a ncurses.h

Curses es mucho mas rico que conio, por ejemplo curses soporta underline osea subrayar letras en la consola ademas del clásico blink que las letras aparezcan y desaparezcan. El conio.h solo trae soporte a blink

Curses es solo un poco mas difícil de manipular que conio.h esto se debe a que se puede considerar a curses como una capa sobre la terminal, denominada ventana y sobre esta ventana se llevan a cabo los colores y efectos de la terminal, esta ventana debe ser inicializada, al mismo tiempo que es un buffer y debe ser tratado como tal.

Podemos inicializar la ventana con las siguientes funciones

initscr();
savetty();

y terminar la ventana para volver a la consola stadart con

echo ();
resetty();
endwin();

En realidad solo con resetty y endwin es suficiente, pero usamos echo para asegurarnos que quedara activado el echo, de lo contrario no se verán los caracteres porque no tendrán echo, si es que en el programa hicimos un noecho();

Despues deinicializar la ventana con curses.h la programación se torna similar a conio.h pero con algunas variantes, mostrare las fuciones mas comunes en conio.h en su versión curses

Conio.h ncurses.h

Limpiar pantalla
Clrscr(); – erase ();

Mover el cursor en la plantalla
Gotoxy (x,y) - move (y,x);
Nótese que las X y las Y están invertidas en curses, fuera de ese detalle el comportamiento es el mismo

Imprimir caracteres en pantalla
Cprintf (); - addch (); o si se trata de una cadena addstr ();

El manejo de color en curses es un poco mas complicado por que hay que verificar si la consola soporta color e inicializar el color, así como la paleta de colores que vamos a usar, la usaremos en pares 2 colores por vez ósea el color de frente y el de fondo
En conio.h textcolor y textbackground son 2 funciones separadas en curses se usan al mismo tiempo

Primero se inicializa con la función start_color ();
Después se asignan los colores con las funciones
init_pair (1,COLOR_CYAN,COLOR_BLACK);

en init_pair le decimos el color de frente que es CYAN y el de fondo que es negro
attron (COLOR_PAIR (1) | A_UNDERLINE);
con attron lo asignamos a la ventana, y además si queremos agregamos | A_UNDERLINE para que las letras esten subrayadas o usar A_BLINK para hacer que aparezcan y desaparezcan entre otras opciones como A_BOLD para hacerlas negritas, como dije curses es mas rico en elementos visuales para la consola.

Ahora escribiré un programa con estas funciones básicas que será exactamente igual a la hora de ejecutarse en DOS usando conio.h y en GNU/Linux usando curses.

Version DOS y Conio.h

#include <conio.h>
#include <stdio.h>

int cuadro (int a,int b,int c,int d)
{
    int x;

    for (x = a; x != c; x++)
    {
        gotoxy (x,b);
        putchar (205);
    }

    for (x = b; x != d; x++)
    {
        gotoxy (c,x);
        putchar (186);
    }

    for (x = c; x != a; x–)
    {
        gotoxy (x,d);
        putchar(205);
    }

    for (x = d; x != b; x–)
    {
        gotoxy (a,x);
        putchar(186);
    }

    gotoxy (a,b); putchar(201);
    gotoxy (c,b); putchar(187);
    gotoxy (c,d); putchar(188);
    gotoxy (a,d); putchar(200);
    return 0;
}

int main ()
{
    clrscr ();
    cuadro (5,5,70,20);
    cuadro (6,7,69,19);

    gotoxy (15,6);
    textcolor (CYAN);
    cprintf (”Hola MS/DOS, visita
http://www.lastdragon.net”);
    getchar ();

    return 0;
}

Version GNU/Linux y ncurses.h
#include <ncurses.h>

int cuadro (int a,int b,int c,int d)
{
        int x;

        for (x = a; x != c; x++)
        {
               
move (b,x);
               
addch(’-');
        }

        for (x = b; x != d; x++)
        {
               
move (x,c);
               
addch(’|');
        }

        for (x = c; x != a; x–)
        {
               
move (d,x);
               
addch(’-');
        }

        for (x = d; x != b; x–)
        {
               
move (x,a);
               
addch(’|');
        }

        move (b,a); addch(’+');
        move (b,c); addch(’+');
        move (d,c); addch(’+');
        move (d,a); addch(’+');
        return 0;
}

int main ()
{
        initscr();
        savetty();
        erase ();

        cuadro (5,5,70,20);
        cuadro (6,7,69,19);

        start_color ();
        init_pair
(1,COLOR_CYAN,COLOR_BLACK);
        attron (COLOR_PAIR (1) |
A_UNDERLINE);

        move (6,15);
        addstr (”Hola GNU/Linux,
visita http://www.lastdragon.net”);
        refresh ();

        getch ();
        echo ();
        resetty();
        endwin();

        return 0;

Video demostrando como corren ambos programas

Espero que este artículo ayude a todos los que aprendieron C en ambientes de Microsoft y DOS a migrar sus programas a GNU/Linux y otros NIX usando curses

2985

Jan 05

El principal problema de las interfaces graficas son su limitado campo de acción, no todas las interfaces dan las opciones que hay en la línea de comandos, aun hoy, pienso que la consola es mucho más poderosa que una interface grafica y no es que sea poco amigable, es que dichas consolas escogen bien a sus amigos.

Actualmente hay discos duros muy grandes y algunas personas no entienden porque al usarlos con GNU/Linux una parte del espacio desaparece de la vista.

El espacio en realidad no desaparece, simplemente se reserva, antes no era tan notorio, pues por ejemplo de un disco de 1GB si le reservamos el 10% tendremos que solo nos permitirá almacenar 900MB ¿y los otros 100MB donde están?

Siguen ahí pero están reservados para uso exclusivo de root, esto es porque si los usuarios comunes y otros programas saturan el disco duro no quedara espacio ni para los logs ni para que root pueda hacer movimientos administrativos, sin esta reservación podría quedar bloqueado el mismo root por falta de espacio para trabajar

Comúnmente solo se reserva el 5% de una partición del disco duro, aunque por medio de parámetros a la hora de formatear nos permiten modificar esto, antes no era tan notorio este espacio reservado, no es igual perder un par de megas en un disco de un 1GB a perder cientos de megas en discos que sobre pasan los 200GB actuales

Lo que hare será particionar un disco de un 1GB, luego lo particionare y lo formateare
Con un usuario sin privilegios, el usuario david, escribiré hasta donde el sistema operativo me lo permita, al llegar al límite si quiero escribir mas el sistema operativo dirá que no hay espacio, aunque quede el 5% disponible
Al a usar el usuario root podrá obtener los últimos 5% de espacio sin ningún problema hasta que realmente haya ocupado todo el espacio disponible

El video de la demostración

Jan 04

Me han mandado un E-mail con una pregunta interesante pidiéndome un ejemplo práctico del problema de los punteros.

Me dicen que no entiende porque siempre lee en todos los manuales de C lo útil y peligroso de los punteros, cuando solo los manejan como una variable mas.

Bueno ya que ando en mi rato de escribir sobre programación, responder con un ejemplo practico como se me ha solicitado, no sin antes tirar mi rollo acerca del problema =)

Los teóricamente son variables sin tipo, porque un puntero tendra el tipo de la zona de memoria a la que apunta, como su nombre en ingles dice pointer o puntero, este tipo de variable es eso, un apuntador y a punta a donde sea

Su utilidad radica en que podemos accesar por medio de ellos a zonas de memoria donde de otra forma no podríamos, su punto débil es que en tiempo de ejecución C no comprueba los punteros esto es simples, no tiene porque y luego C es un lenguaje nivel medio, con menos ganas tiene porque.

Sin embargo podemos confiar en el sistema operativo en que no permitirá que un mal puntero uno dejado por ahí por un programador termine modificando valores de otros programas, al menos podemos confiar en GNU/Linux y otros tipos de Unix =), claro que es una mala práctica de programación dejar punteros sueltos por ahí. En el mejor de los casos modificaremos valores de memoria de nuestro programa y causaremos que falle.

Lo peor que puede pasarnos en un programa de producción, es que nuestro puntero apunte a una zona de memoria de nuestro programa y modifique cosas que no debe, si lo hace el programa no fallara, debería, pero no lo hará, debería darnos un fallo de segmento pero en lugar de eso como apunta a una zona de memoria en la que tiene “permiso” continuara ejecutándose pero con información poco confiable y es esto el riesgo de los punteros, el programa no falla pero ya no puedes confiar en lo que el programa procesa y peor aún, al no existir un fallo palpable depurar un programa con un mal puntero se vuelve una tarea titánica, mas si el programa de mas cientos de líneas de código.
Ahora que hare para comprobar esto, deliberadamente escribiré un programa que manipule un puntero que no retendrá los valores en la memoria ram.

¿Por qué fallara y por que casi nadie se mete en líos con los punteros?

No se meten en líos por suerte, porque muchas personas usan los punteros en variables que no caducan en todo el programa o el puntero caduca junto con la variable eliminando el riesgo.

Nuestro programa fallara porque voy a apuntar a una zona “volátil” y como lo hare.

Bueno no es un secreto que cada que un programa llama una función a ejecutarse, esta reserva la memoria para que se ejecute además reserva la memoria para las variables locales de dicha función y al terminar de ejecutarse antes de continuar la ejecución de un programa se libera toda la memoria ocupada y se destruyen las variables o lo que es igual se liberan los segmentos de variables ocupadas por la función y quedan a disposición de nuevas funciones y nuevas variables

El programa que hará lo siguiente.

Un puntero global o que se mantendrá vivo durante toda la ejecución del programa sera llamado dentro de una función y se le asignara la dirección de memoria de una variable dentro de esa función, al terminar de ejecutarse la función como dije anteriormente los datos serán destruidos pero nuestro puntero seguirá vivo a apuntando a una variable “muerta”, esto es una mala práctica de programación con punteros.

El programa accesara inmediatamente a la zona muerta y leera el valor de dicha zona si este no ha sido modificado aunque la variable este muerta quedara el valor residual y podremos leerlo, después de eso, deliberadamente lanzare una función para fines practicos un sleep, esta reciclara la memoria y cuando intentemos leer la zona… ZAS los datos o están corruptos o no están.

Luego le hare una asignación manual de un valor y este se escribirá en esa zona de memoria por que nuestro apuntador apunta ahí, si existiría algún dato importante de otra variable ahí, seria destruido y luego consultare el valor, hay que recordar que esa zona se considera libre y puede ser usada en cualquier momento por otra función, entonces, lanzare otra función , otro sleep que volverá a usarla y a pisotear lo que había almacenado ahí.

Para fines practico nada de lo que almaceno en esa zona esta seguro de no ser destruido peor aun, nada en esa zona esta seguro por que igual por medio del puntero puedo destruir la información de otra función que en ese momento este en esa zona de memoria causando que el programa haga cosas raras.

El código

#include <stdio.h>

int *puntero = NULL;
int mem = 0;

int funcion1()
{
        int entero = 100;
        mem = &entero;
        printf (”Direccion local %p
almacenada %p\n”,&entero,mem);
        return 0;
}

int main ()
{
funcion1 ();

puntero = mem;
printf (”Valor en el Puntero %d en %p\n”,*puntero,mem);

sleep (2);

printf (”Valor en el Puntero %d en %p\n”,*puntero,mem);

*puntero = 10;

printf (”Valor en el Puntero %d en %p\n”,*puntero,mem);

sleep (2);

printf (”Valor en el Puntero %d en %p\n”,*puntero,mem);

return 0;
}

Ojo, aunque confió en la protección de memoria de Linux, nunca ejecutes este código como root que aunque se ve tan inofensivo, y no debería pasar nada malo al final el programa no se sale de su propia asignación de ram, sin embargo no hay que abusar de la suerte y terminemos con un programa inestable y con acceso root, eso sí es malo, muy malo para nuestro GNU/Linux

El video de la práctica.

2a11

Jan 02

La memoria compartida es muy útil para programas que subprocesos con fork, sin embargo no necesariamente es ese su límite, la memoria compartida igual puede ser usada por programas totalmente distintos como un medio para enviarse señales y compartir información en común.

Solo hay un problema, todo kernel decente tiene protección de memoria, esto significa que un programa no puede interferir con otro, así que el hecho de que 2 o más programas intenten entrar a la misma zona de memoria es contradictorio, por lo que el sistema operativo así de gusto no lo va a permitir, salvo sea el mismo sistema operativo quien nos ayude a esto.

Para mostrar cómo es posible hacer esto, hare 3 programas, podrían ser al menos 2, pero la intención es mostrar que muchos programas pueden operar con los mismos segmentos de memoria.

El primer programa reservada la memoria y será el encargado de liberarla también, mientras este programa este corriendo los otros 2 podrán accesar a la memoria compartida.

El segundo programa accesara a la memoria compartida e irá haciendo modificaciones en dicha zona, será un contador.

El tercer programa leerá la zona de memoria y nos mostrara el valor actual que hay en ella.

Los 3 programas serán muy similares, las funciones se explican a continuación.

Para que programas completamente independientes compartan información, deben tener un acceso común a un recursos del sistema, estos programas crean si no existe un archivo en el temporal y se ligaran a el para crear una llave

La llave se asigna a una variable tipo key_t usando la función ftok, ftok requiere 2 parametros , el archivo en común que hemos creado y un entero, esto debe coincidir en cada programa que vaya a usar la zona de memoria, de lo contrario el sistema operativo les negara el acceso tal cual debe ser.

Obtenemos la clave con el siguiente ejemplo.

key_t clavecompartida = ftok (”/tmp/acompartido”,33);

una vez con la clave solicitamos al sistema operativo cree una zona de memoria de 400 bytes, un apuntador tipo char de 100 veces su tamaño. Esto nos devolverá un entero con el identificador del segmento de memoria, si la asignación tuvo éxito.
int mem = shmget (clavecompartida,sizeof(char *)*100,0777 | IPC_CREAT);

Nótese que la protección de memoria es similar a la protección de acceso a archives, el parámetro 0777 tiene el mismo significado que los permisos de archivo, de esta forma estamos declarando que nuestra memoria será de acceso total para todos, también podríamos dar permisos de solo lectura para determinados programas que corran con X usuario, como solo lectura o negarle el acceso a cualquier otro usuario que quiera entrar a nuestra memoria compartida, el IPC_CREAT Solo lo usamos al momento de buscar reservar o crear el espacio, para leer o modificar la memoria en otros programas no será necesario, porque ya existirá.

Ya con el identificador entraremos a la zona de memoria vía punteros, al puntero lo alimentamos con la función shmat a la cual le pasamos como parámetro el identificador de nuestra zona de memoria

char *mcompartida = (char *) shmat (mem,NULL,0);

En este punto, el puntero char mcompartida está ligado a la memoria compartida y lo que le hagamos a ese puntero, lo estamos haciendo en esa zona de memoria.

Aclarando que es mas fácil mover cadenas de caracteres por ese punto, por lo que si queremos pasar números, por ejemplo un 10, sera mas fácil enviar una cadena de caracteres “10” y al recibirla en otro programa, convertirla en un entero, por ejemplo

Strcpy (mcompartida,”10”);

Liberando la memoria compartida y borrando el archivo en común, con la función shmctl y pasándole el primer parámetro la variable entera que tiene el identificador de la zona de memoria

shmctl (mem, IPC_RMID, (struct shmid_ds *)NULL);

unlink (“archivo”);

unlink borra archives del sistema operativo

Si el programa terminara de forma incorrecta o por interrupción del usuario, la memoria compartida se quedara en el sistema operativo indefinidamente, ya que el programa nunca le notifico al sistema operativo que debía liberarla.

En el caso de GNU/Linux los comandos ipcs nos ayudaran a administrar manualmente las zonas compartidas de memoria.

Si queremos ver cuántas memorias compartidas hay, usamos el comando ipcs

Por ejemplo si queremos borrar la zona 1234 usamos el Ipcrm –m 1234

Ahora el código de 3 programas que demuestran el acceso a la memoria compartida.

Asignar.c Este programa reserva y libera la memoria, mientras se ejecute los otros 2 programas tendrán acceso a la memoria.
#include <stdio.h>
#include <sys/shm.h>

int main ()
{
        FILE *archivocompartido;
        key_t clavecompartida;
        int mem = 0;
        char *mcompartida = NULL;

        archivocompartido = fopen
(”/tmp/acompartido”,”w+”);
        clavecompartida = ftok
(”/tmp/acompartido”,33);

        mem = shmget
(clavecompartida,sizeof(char *)*100,0777 | IPC_CREAT);
        mcompartida = (char *) shmat
(mem,NULL,0);

        printf (”Creando el segmento
%d de memoria compartida\n\n”,mem);
        printf (”Precione ENTER para
liberar los recursos compartidos\n”);

        getchar ();

        shmctl (mem, IPC_RMID,
(struct shmid_ds *)NULL);
        unlink (”/tmp/acompartido”);
        return 0;
}

Modificar.c Este programa modifica la zona de memoria asignada por asignar.c
#include <stdio.h>
#include <sys/shm.h>

int main ()
{
        FILE *archivocompartido;
        key_t clavecompartida;
        int mem = 0;
        int contador = 0;
        char *mcompartida = NULL;

        archivocompartido = fopen
(”/tmp/acompartido”,”w+”);
        clavecompartida = ftok
(”/tmp/acompartido”,33);

        mem =  shmget
(clavecompartida,sizeof(char *)*100,0777);
        mcompartida = (char *) 
shmat (mem,NULL,0);

        printf (”Trabjando con el
segmento: %d\n”,mem);
        printf (”Cada segundo se
actualiza el valor compartido, el programa dura un minuto\n”);

        while (contador != 60)
        {
               
contador = contador + 1;
               
sprintf (mcompartida,”%d”,contador);
               
sleep (1);
        }

        return 0;
}
Obtener.c este programa obtiene el valor actual de la zona de memoria compartida

#include <stdio.h>
#include <sys/shm.h>

int main ()
{
        FILE *archivocompartido;
        key_t clavecompartida;
        int mem = 0;
        char *mcompartida = NULL;

        archivocompartido = fopen
(”/tmp/acompartido”,”w+”);
        clavecompartida = ftok
(”/tmp/acompartido”,33);

        mem =  shmget
(clavecompartida,sizeof(char *)*100,0777);
        mcompartida = (char *) 
shmat (mem,NULL,0);

        printf (”Trabajando con el
segmento: %d\n”,mem);
        printf (”El valor compartido
es: %s\n”, mcompartida);

        return 0;
}

Un video mostrando la ejecución de los 3 códigos.

Codigo fuente
http://www.lastdragon.net/misarchivos/memcompartida.tar.gz

1b9d

0