Enseñar Software Libre: Obligación de las universidades

Noviembre 19, 2009 por rtmex

Lamentablemente, en la mayoría de las universidades sólo enseñan herramientas de software privativo y no mencionan en absoluto el software libre. Desde luego hay paises en los que en algunas universidades no sólo lo mencionan sino que además promueven su uso; lástima que México no sea uno de esos países.

Pienso que las universidades tienen la obligación moral de enseñar software libre. No estoy diciendo que sólo se enseñe software libre, no estoy en contra de que se eneseñe software privativo, pero si estoy en contra de que únicamente se enseñe software privativo.

Para que quede claro, en la mayoría de las universidades (al menos de México, pero no dudo que sea el caso de muchos otros países) a los estudiantes de sistemas/informática, etc. prácticamente sólo se les enseña a usar software de Microsoft (a excepción de Java que es de Sun y no hace mucho se publicó bajo licencia GPL2), y si bien les va de Borland, y a los estudiantes de otras carreras sólo la suite de oficina de Microsoft (Office).

¿Porque digo que las universidades tienen la obligación moral de enseñar software libre?

Las universidades públicas reciben un presupuesto del gobierno porque éste está obligado a proporcionar educación a los ciudadanos, todo ciudadano debería tener la oportunidad de recibir educación de calidad que le permita desempeñar un trabajo de calidad y estar preparado para competir en éste mundo cada vez más globalizado, independientemente de su situación financiera, es decir, en teoría, un estudiante de pocos recursos económicos debería estar tan preparado como uno que tenga padres millonarios.

Pero ¿qué pasa si al estudiante de informática de una universidad pública, que en ocasiones no tiene ni para el pasaje del transporte público para ir de su casa a la universidad sólo le enseñan a usar Microsoft Office y a programar en Visual Studio versión x?. Supongamos que ese estudiante tuviera la fortuna de haber logrado comprar una computadora con el sacrificio de sus padres, o el suyo propio porque trabaja en las noches en x o y fábrica; dicha computadora si acaso viene con la licencia de Windows versión x instalado, pero no trae Microsoft Office y mucho menos Visual Studio, la universidad estaría casi obligando a este estudiante a desembolsar un dinero extra (considerable además) para que adquiriera las licencias de dichos paquetes, porque desde luego que no esperamos que una universidad fomente la actividad a la cual las empresas desarrolladoras de software privativo más grandes del mundo llaman “piratería”.

No se debe condicionar el aprendizaje a quienes pueden pagar las licencias de uso de software privativo. Cabe mencionar que software libre no significa software grátis, pero afortunadamente, la gran mayoría del software libre resulta que es también grátis.

Dejando de lado la cuestión económica (recordemos también que la principal ventaja del software libre no es el ahorro en el costo de la licencia, sino la independencia tecnológica que nos brinda), el estudiante tiene derecho a saber que existen otras opciones y más aún debería tener la oportunidad de conocerlas y decidir libremente que sistema operativo, suite de oficina o herramienta de programación usar en el futuro (me refiero a su vida profesional).

Las universidades privadas que no enseñan software libre están limitando las opciones de desarrollo profesional de sus estudiantes ya que muchas de las instituciones y empresas líderes en diferentes ramos usan software libre, tal es el caso de la NASA, Google, Cisco Systems, IBM, Intel, Oracle, Yahoo, Silicon Graphics, Dreamworks, SAP, Merril Lynch (recientemente adquirida por Bank Of America) por mencionar sólo algunas.

El hecho de que los servidores de Yahoo corran FreeBSD no es porque Yahoo no pueda pagar las licencias de algún sistema operativo privativo, sino por la estabilidad, seguridad, etc. que FreeBSD ofrece.

Aquí un par de enlaces que pueden ser de interés, el primero es de hace ya algún tiempo pero fue escrito por uno de los co-fundadores de Yahoo

http://zer0.org/daemons/yahoobsd.html

http://www.freebsd.org/doc/es/books/handbook/nutshell.html

Aglunas empresas “regalan” licencias de sus paquetes a las universidades e incluso a escuelas de niveles educativos inferiores (preparatorias, secundarias y hasta primarias), realmente esas empresas no consideran que están regalando las licencias de sus paquetes, lo que están haciendo es que están invirtiendo en publicidad y mercadotecnia, están creando futuros consumidores de sus productos. Si un niño aprende a usar únicamente un sistema operativo y una única suite de oficina, no querrá aprender a usar otra cosa en el futuro, por que no querrá invertir tiempo en ello, y hay quienes estarán dispuestos a pagar lo que les pidan con tal de no invertir tiempo en aprender a usar otra cosa, sin importar si ese otro sistema operativo sea mejor que el único que el sabe usar.

Esta práctica es la que emplean con mucho éxito los narcomenudistas, regalan las primeras dósis para “enganchar” a quien será su futuro cliente incondicional.

No dejemos que el sistema educativo de todo un país dependa de una empresa, que nuestros alumnos no sean “clientes” de ninguna corporación (nacional o extranjera). Enseñar software libre en las universidades garantiza la independencia tecnológica de los ciudadanos que serán los pilares del país en el futuro.

Agregar archivos a una imágen de disco

Octubre 5, 2009 por rtmex

Quienes no sepan que es una imágen de disco pueden encontrar información al respecto en el siguiente enlace http://en.wikipedia.org/wiki/Disk_image.

A continuación voy a poner un ejemplo de cómo agregar y borrar archivos a una imágen de disco desde GNU/Linux.

Para este ejemplo, vamos a utilizar una imágen de disco de FreeDOS llamada balder10.img (se puede decargar de aquí: http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/unofficial/balder/); esta es una imágen de disco de 1.44Mb con formato DOS.

Primero debemos crear un directorio para montar la imágen de disco (en este caso creé un directorio llamado imagendisco en mi home).

mkdir /home/salomon/imagendisco

Ahora montamos la imágen de disco indicando el tipo de sistema de archivos (en este caso vfat porque es formato DOS) y que la montaremos con permisos de lectura y escritura (rw).

sudo mount -t vfat -o loop,rw,umask=0002 balder10.img /home/salomon/imagendisco

Si hacemos un ls al directorio /home/salomon/imagendisco veremos el contenido de la imágen de disco

append.exe    defrag.hlp    fdapm.com     keyb.exe      share.com
assign.com    deltree.com   fdconfig.sys  keyboard.sys  shrdrv86.exe
attrib.com    devload.com   fdisk.exe     keybrd2.sys   shsucdhd.exe
autoexec.bat  diskcomp.com  fdisk.ini     label.exe     shsucdx.com
cdrcache.sys  diskcopy.exe  fdiskpt.ini   lbacache.com  subst.exe
chkdsk.exe    diskcopy.ini  fdshield.com  loadcd.bat    sys.com
choice.exe    display.exe   fdxms286.sys  mem.exe       tickle.com
command.com   dosfsck.exe   find.com      mode.com      tree.com
comp.com      drvon.com     format.exe    more.exe      unzip.exe
country.sys   edit.exe      graph-hp.com  move.exe      xcdrom.sys
ctmouse.exe   edit.hlp      graphpin.com  nansi.sys     xcopy.exe
cwsdpmi.exe   edlin.exe     graph-ps.com  nlsfunc.exe   xdma.sys
debug.com     emm386.exe    himem.exe     pcisleep.com  zip.exe
defrag.exe    fc.exe        kernel.sys    replace.exe

supongamos que queremos agregar un archivo llamado leeme.txt, basta con copiar el archivo al directorio en donde montamos la imágen de disco

sudo cp leeme.txt /home/salomon/imagendisco

si ahora hacemos un ls vemos que el archivo ha sido agregado

append.exe    defrag.hlp    fdapm.com     keyb.exe      replace.exe
assign.com    deltree.com   fdconfig.sys  keyboard.sys  share.com
attrib.com    devload.com   fdisk.exe     keybrd2.sys   shrdrv86.exe
autoexec.bat  diskcomp.com  fdisk.ini     label.exe     shsucdhd.exe
cdrcache.sys  diskcopy.exe  fdiskpt.ini   lbacache.com  shsucdx.com
chkdsk.exe    diskcopy.ini  fdshield.com  leeme.txt subst.exe
choice.exe    display.exe   fdxms286.sys  loadcd.bat    sys.com
command.com   dosfsck.exe   find.com      mem.exe       tickle.com
comp.com      drvon.com     format.exe    mode.com      tree.com
country.sys   edit.exe      graph-hp.com  more.exe      unzip.exe
ctmouse.exe   edit.hlp      graphpin.com  move.exe      xcdrom.sys
cwsdpmi.exe   edlin.exe     graph-ps.com  nansi.sys     xcopy.exe
debug.com     emm386.exe    himem.exe     nlsfunc.exe   xdma.sys
defrag.exe    fc.exe        kernel.sys    pcisleep.com  zip.exe

Ahorsa sólo desmontamos la imágen de disco

sudo umount /home/salomon/imagendisco

y eso es todo.

El borrado de archivos de la imágen de disco una vez montada es igualmente simple, supongamos que quisieramos borrar el archivo unzip.exe, bastaría con hacer

sudo rm /home/salomon/imagendisco/unzip.exe

Podemos montar la imágen con permisos de sólo lectura si sólo queremos ver el contedido y no vamos a aregar ni borrar archivos de la misma.

sudo mount -t vfat -o loop,ro,umask=0222 balder10.img /home/salomon/imagendisco

Educando a los usuarios

Agosto 28, 2009 por rtmex

Cuando desarrollamos un software a la medida, es común encontrar que el usuario (la empresa o persona) a quien se le desarrolla la aplicación, no tiene ni la más remota idea de cómo es el proceso de desarrollo de software; es más, muchos no saben ni como copiar archivos de una carpeta a otra en una PC, pero bueno, eso ya es otro tema.

Lo que yo he optado por hacer y hasta ahora me ha funcionado, es explicarles que el proceso de desarrollo de una aplicación es parecido al proceso de construcción de una casa. Primero le decimos al arquitecto lo que tenemos en mente para que el haga el plano, nos lo muestre y nosotros lo aprobemos o le indiquemos si queremos que le haga algunos cambios.

En el caso de que le hayamos indicado que haga cambios al plano, el arquitecto debe hacer un nuevo plano con los cambios y volver a mostrarnoslo para que lo aprobemos. Este proceso se repite hasta que nosotros aprobemos el plano. Es hasta que el plano (arquitectónico) está aprobado por nosotros que el arquitecto empieza a crear los demás planos que se requieren (eléctrico, hidráulico, etc.)

De igual forma, después de que el usuario nos dice que tiene en mente, lo que debemos hacer es la especificación de requisitos, que será la base para el desarrollo de la aplicación. En este documento se describe la funcionalidad que tendrá la aplicación y debe ser aprobado por el usuario. Una vez que la especificación de requisitos es aprobada por el usuario, empezamos a hacer el diagrama entidad-relación de la base de datos, etc.

El que el usuario espere ver la primer pantalla de la aplicación un dia después de que nos dijo cuáles son sus necesidades, es tanto como esperar que el arquitecto levante la primera barda inmediatamente después de que le dijimos lo que tenemos en mente, sin que haga un plano que nos muestre para que lo aprobemos, es ilógico ¿no creen?

Así como en el proceso de construcción de una casa, no le preguntamos al arquitecto a la mitad de la obra “¿en dónde va a estar ubicada la cancha de tenis?”, siendo que en el plano que nos mostró y que nosotros aprobamos no aparece ninguna cancha de tenis, está por demás explicarle al usuario que no esperamos que a la mitad del desarrollo de la aplicación nos pregunte “¿En qué menú estará la opción de facturación?”, cuando en la especificación de requisitos que le mostramos y que aprobó no se habla en ningún momento de un módulo de facturación.

Otra analogía entre el desarrollo de una aplicación y la construcción de una casa que utilizo es para hacerles entender que cuesta mas agregar funcionalidad a un módulo ya hecho que incluir dicha funcionalidad en el módulo desde un principio.

Supongamos que el arquitecto ya terminó la planta baja de nuestra casa, está construyendo la planta alta y le decimos que queremos que el medio baño de la planta baja, que está junto a la sala, ahora sea baño completo. “¿Se puede hacer esa modificación?”, probablemente si, pero desde luego costará más de lo que hubiera costado si desde que nos mostró el plano para que lo aprobaramos le hubieramos pedido esto, cuesta más porque ahora hay que instalar más tubería para que llegue agua caliente a la regadera que se instalaŕa en ese baño, y probablemente habrá que tirar algún muro para que haya espacio para la ducha en ese baño.

De igual forma, generalmente el agregar a un módulo ya hecho funcionalidad que no se contempló desde un inicio, cuesta más porque implica más trabajo. Así de simple.

En conclusión, debemos hacer entender al usuario que no debe asumir que la aplicación tendrá funcionalidad que en la especificación de requisitos no se dijo que tendría. Nada de que “yo pensé”, “es que es obvio”, y otras frases por el estilo.

Si desarrollas software a medida, te recomiendo hacer la especificación de requisitos y que el usuario la firme como aprobada antes de empezar con el desarrollo. Evitarás malos entendidos y problemas posteriores.

Y si tu eres usuario final, desconfia de la capacidad de cualquier “profesional de sistemas” que te prometa mostrarte avances de la aplicación sin antes haber hecho la especificación de requisitos y sobre todo, antes de haber construido el diagrama entidad-relación de la base de datos y demás “planos”. Es equivalente a que el arquitecto que construirá tu casa te diga que verás la primera barda sin antes haberte mostrado el plano.

Reviviendo PC’s “obsoletas”, (según para que)

Agosto 4, 2009 por rtmex

Desde hace algún tiempo quería instalar un sistema operativo tipo Unix en 2 PC’s antiguas que tenía por ahi sin usar; ya sea alguna distribución de GNU/Linux o algún BSD (FreeBSD, NetBSD, etc.). Después de varios días de pruebas e investigación, logré dicho propósito.

Equipo 1

PC con procesador AMD 386SX a 40Mhz, sin FPU (coprocesador matemático), 4MB de memoria RAM, de los cuales el motherboard toma los 640K de memoria base. El motherboard tiene 2 bancos de memoria de 2 slots cada uno (utliza SIMMS de 30 pins) y soporta un máximo de 16MB de RAM. Floppy de 3.5″ 1.44MB y CD-ROM SCSI conectado a tarjeta de sonido Pro Audio 16.

Equipo 2

PC con procesador Cyrix 486DLC a 40Mhz, con FPU y también 4MB de memoria RAM, este motherboard tiene 2 bancos de 4 slots cada uno, también utiliza SIMMS de 30 pins y soporta un máximo de 32MB de RAM. Floppy de 3.5″ 1.44MB y no tiene CD-ROM.

Antecedentes

De alguna forma, la mayoría de la información que encontré en internet no satisfacía mis requerimientos.

Mucha información de distribuciones GNU/Linux para “equipos antiguos” o “con pocos recursos” se refería a PC’s Pentium I con 128MB de RAM o a equipos mas recientes, si bien el Pentium I no es el procesador más potente en este año 2009, hay muchas distribuciones GNU/Linux con las que ese equipo puede funcionar de manera bastante aceptable; pero para una 386SX las opciones disminuyen considerablemente.

Las opciones mas viables eran distribuciones del tipo DSL (Damm Small Linux), Gray Cat Linux, BasicLinux, MuLinux, etc., pero yo no quería un livecd, ni una distribución que funcionara en RAM, en un loop, desde floppy o instalada sobre DOS, ni cosas por el estilo, sino un sistema operativo que se instalara en disco duro, que arrancara desde ahi y utilizara su partición swap, etc., es decir, una instalación “normal”. No me importaba que fuera sólo consola, sin las X (el ambiente gráfico).

Recopilando hardware faltante para llevar a cabo la misión

Ninguno de los Bios de los 2 motherboards trae la opción para arrancar desde CD. Asi que tenía que ser una instalación por red, desde luego otra opción era instalar conectando otra PC por el puerto serial y desde ahi hacer la instalación, o poner el disco duro en una PC “moderna”, instalar ahi y regresar el disco, pero eso para mi es tanto como evitar el desafío, y de paso perderse la diversión.

También me di cuenta que con menos de 4MB de RAM reales (recuerden que comenté que de esos 4MB, el motherboard toma 640K para la memoria base), era practicamente imposible instalar un sistema operativo tipo Unix que no estuviera “tan” desactualizado; así que compré por internet 2 tarjetas de red ISA Ethernet 10baseT usadas y un lote de módulos de memoria en donde venían SIMMS de 30 pins de 1MB y de 4MB, también incluía unos SIMMS de 72 pins y uno que otro DIMM de 168 pins.

Tenía varios discos duros antiguos de los cuales seleccione para la 386SX uno de 630MB y uno de poco mas de 200MB; para la 486DLC elegi uno de 2GB (varios Motherboards antiguos tienen un Bios que no reconoce discos de mas de 2GB, y algunos otros no reconocen discos de mas de 500MB).

Finalmente la 386SX quedó con 16MB de RAM

386sx_screen

y la 486DLC con 32MB

486dlc_screen

Las pruebas

Las tarjetas de red que consegui son una 3com modelo 3C509B-TPO y una AT/LANTIC con chip DP83905AVQ, que es un clon de las tarjetas NE2000.

Ninguna de estas tarjetas es configurable via jumpers, sólo se pueden configurar mediante un programa hecho por el respectivo fabricante. Bueno, la AT/LANTIC tiene una entrada para un jumper, si pones el jumper en dicha entrada, la tarjeta queda configurada en la dirección io=0×300, irq=3; de lo contratio, tomará la io e irq que se le haya configurado mediante el software mencionado.

FreeBSD quitó el soporte para el procesador 80386 desde la versión 5.0 (http://www.freebsd.org/releases/5.0R/relnotes-i386.html), así que tenia que probar con una versión anterior. La documentación de FreeBSD versión 4.11 dice que funciona en una PC con procesador 80386 y que el programa de instalación requiere 16MB de RAM así que probé instalarlo en la 386SX, todo funcionó aparentemente bien hasta que terminada la instalación llegó el momento de reiniciar la Pc, ya con FreeBSD 4.11 instalado. En un momento del arranque, empezó a enviar el siguiente mensaje n veces

microuptime() went backwards (44525.3954411 -> 44524.563978)

microuptime() went backwards (57425.4282241 -> 57424.766121)

microuptime() went backwards (57425.4282241 -> 57424.845844)

Los números antes y después del símbolo “>” cambiaban en cada renglón, pero parecía haberse ciclado.

Busqué en internet información al respecto y encontré varios post de otros usuarios reportando lo mismo, a algunos no les pasaba al momento de reincicar la máquina, sino depués, a otros les enviaba el mensaje esporádicamente, etc. pero nunca encontré un post en donde se dijera como solucionarlo, al parecer era un problema en el kernel de algunas versiones de FreeBSD que se presentaba en algunos equipos.

NetBSD por su parte, incluyó la leyenda “Removed support for 80386 level CPUs”  en el anuncio de su versión 5.0 (http://netbsd.org/releases/formal-5/NetBSD-5.0.html) por lo que probé con la versión 4.0.1. A pesar de que en la documentación dice textualmente:

“NetBSD 4.0.1 runs on ISA (AT-Bus), EISA, MCA, PCI, and VL-bus systems with 386-family processors, with or without math coprocessors. The minimal configuration is said to require 4 MB of RAM and 50 MB of disk space, though we do not know of anyone running with a system quite this minimal today”

Probé con sólo 8MB de RAM en la 386SX pero la máquina se reiniciaba después de insertar el segundo floppy, agregué los otros 8MB y probé con 16MB de RAM pero sucedio lo mismo.

Probé entónces con la versión 3.1.1 y esta si logré instalarla

NetBSD_3_1_1Pero, lo que me descepcionó fue que como podrán comprobar en el sitio http://ftp.netbsd.org/pub/NetBSD/NetBSD-archive/NetBSD-3.1.1/i386/ no se encuentran los packages o el arbol de ports, sólo están los paquetes del kernel y los sets básicos, asi que no es posible instalarle programas ya compilados (los packages) ni bajar los fuente de los programas para esa versión para compilarlos. Lo que hice fue bajar de http://ftp.netbsd.org/pub/NetBSD/packages/distfiles/ unos fuente para compilarlos y ver si era viable o no, ya que por la capacidad de la máquina, la compilación iba a tardar bastante, además de que esos fuente no dice si son independientes de la versión, lo más probable es que sean para la versión current (en este caso la 5.0.1) por lo que probablemente no funciarían en esta versión 3.1.1

Empece por compilar el mc (midnight comander) y al ejecutar el ./configure, encontró que no pudo descargar unas dependencias, me parece que una versión de glibc que requería.

Traté entónces con el paquete bash, el ./configure si terminó de ejecutarse correctamente después de varias horas por lo que pase a la compilación con el respectivo make install clean, pero tuve que darle Ctrl-C porque ya llevaba 10 horas compilando y no terminaba. La conclusión es que aunque se pudo instalar, debido a que no existen los packages, la instalación de programas compilando los fuentes no es viable por el tiempo que se lleva.

En verdad no le veo mucho sentido a tener un sitio de archivo de NetBSD, si no van a archivar los packages y el arbol de ports de todas las versiones, FreeBSD y Debian si lo tienen (como debe de ser).

Intenté otras distribuciones como Slackware, Feather, etc. pero ninguna funcionó (no voy a aburrirlos con los detalles de los errores que marcaban).

La distribución GNU/Linux (que cumpliera los requisitos que mencioné al principio del post) con la que logré hacer funcionar la 386SX fue Debian 3.0 (Woody).

debian_3_0

A la 486DLC logré instalarle NetBSD 4.0.1 pero funcionaba extremadamente lento, además de que debido a la política de NetBSD de no guardar los packages de versiones archivadas, una vez que archiven esta versión, no habrá forma “viable” de instalarle programas a esta PC, y como eso definitivamente para mi es inaceptable, opté por FreeBSD.

Probé instalar FreeBSD 5.0 en la 486DLC y funcionó

FreeBSD_5_0

Pude instalar los packages de mc, bash, sudo y nano sin problemas y sin esperar horas y horas.

Desde luego no crean que los primeros intentos por instalar los sistemas operativos con que finalmente quedaron las máquinas funcionaron a la primera, tuve problemas para configurar las tarjetas de red tanto en Debian como en FreeBSD, ya sea porque entraba en conflicto el irq que tenian programado con el irq de algún otro dispositivo como el puerto serial, etc. Estuve cambiando la configuración de las tarjetas, cambiando las tarjetas de una máquina a otra e indicando a la hora de la instalación que cargara el driver correspondiente especificando las direcciones io, etc.

Con FreeBSD sucedió algo curioso, en 2 ocasiones al estar instalando, una con la tajeta de red 3com y otra con la AT/LANTIC al llegar al punto en donde debería empezar a descargar los paquetes, se quedaba “trabado” al intentar logearse al servidor ftp ftp://ftp-archive.freebsd.org/, intenté utilizando un mirror, específicamente el servidor ftp://ftp.ru.freebsd.org/ y funcionó bastante bien, de hecho se descargo rápido (para ser con una tarjeta de red a 10Mbps).

Además de buscar información en internet cada vez que algo no funcionaba con la instalación, entré varias veces a canales de IRC de NetBSD, FreeBSD, Debian, etc. Encontré algunas personas que me proporcionaron información que me ayudó a resolver el problema, otras sugerencias no resultaron efectivas pero igualmente agradezco a aquellas personas que intentaron ayudarme. Desafortunadamente también encontré mucha gente ignorante, y lamentablemente fue en todos los canales de IRC a los que entré, que lejos de ayudar, hacia comentarios ridículos como “Actualmente puedes comprar una Pentium con mucha mas RAM por x cantidad”, o “Eso es una pérdida de tiempo”. Aún cuando comenté que desde luego que cuento con una PC con mejores características que esas máquinas, pero el atractivo del proyecto era por un lado el reto que implicaba, y por otro, demostrar que PC’s como esas sirven “perfectamente” para desarrollar aplicaciones simples en C, o usando C y ncurses, o C++, etc.

Una 386 o 486 con un sistema operativo tipo Unix puede funcionar como servidor de archivos (desde luego no con una carga excesiva), servidor de impresión y muchos otros usos mas. Por ejemplo, pienso hacer pruebas con la 486DLC para ver si puede funcionar como thin client utilizando LTSP, de acuerdo a las especificaciones mínimas descritas en http://wiki.ltsp.org/twiki/bin/view/Ltsp/LTSPTerminal parece que si.

En fin, probablemente quienes no programaron (por lo menos el “hola mundo”) antes de 1990, no vean el atractivo que tienen este tipo de proyectos, y digo probablemente porqe habrá quienes no necesiten mayor explicación para ver lo interesante que son.

Pero la cuestión es muy simple, si yo no lo entiendo, se me hace muy complicado porque no se usar una PC si no tiene ambiente gráfico, mis conocimientos en la materia son muy pocos , o simplemente no me interesa, pues no opino y me quedo callado antes de decir tonterías con las que únicamente logro que las otras personas en el canal se den cuenta de que además de ignorante soy un intolerante.

Les presento a Frank (la 386SX)

386sx_full

y a Frank2 (la 486DLC).

486dlc_full

Los nombres son alusivos a Frankenstain desde luego :).

En las 2 PC tomé el tiempo que pasa desde que se prende la PC hasta que pide el login y estos son los resultados.

La 386SX con 16MB de RAM y Debian 3.0 tarda 3 minutos

La 486DLC con 32MB de RAM y FreeBSD 5.0 tarda 12 minutos

Esto no quiere decir que Debian 3.0 sea mejor que FreeBSD 5.0 ya que están instalados en hardware diferente y el tiempo de arranque sólo nos dice eso, “el tiempo de arranque” y nada mas, sólo quise ponerlo como mero dato informativo.

Y sin hacer caso a los comentarios de aquellos ignorantes e intolerantes que no son dignos representantes de la comunidad de usuarios y desarrolladores de software libre, mucho menos de la comunidad informática, les comento que tengo una PC con procesador 80286 y 4MB de RAM en la que pienso instalar FreeDOS. Tengo también unos motherboards 8088 con 512K de RAM creo, pero tendría que desarmar la 286 para utilizar tarjeta controladora, de video, etc.

http://netbsd.org/releases/formal-5/NetBSD-5.0.html

Capturar sólo números en C++ Builder

Junio 22, 2009 por rtmex

En ocasiones necesitamos validar que en un control TEdit el usuario sólo pueda teclear números. Lo que hay que hacer es poner el siguiente código en el evento OnKeyPress de nuestro TEdit.


void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
 if (!((Key >= '0' && Key <= '9') || Key == '\b'))
    Key = 0;
}

Lo que hace este código es ignorar la tecla pulsada si dicha tecla no está dentro del rango de 0 a 9 y tampoco es el backspace (retroceso). Si queremos que los números estén alineados a la derecha, el truco es no utilizar un TEdit, sino un control TMemo haciendolo del tamaño deseado y seleccionando la opción taRightJustify en la propiedad Alignment e indicando el número máximo de caracteres en la propiedad MaxLength.

Alternativas a GNU/Linux

Mayo 22, 2009 por rtmex

Recibí un comentario de Pedro en la página “Acerca de…” de este blog, y este post es en respuesta a su comentario ya que creo que alguien más puede tener la misma inquietud.

Es cierto que existen otros sistemas operativos y algunos seguramente mejores que GNU/Linux, por ejemplo en mi opinión, los BSD (FreeBSD, NetDBSD, etc.) son un poco mas robustos y eficientes que GNU/Linux.
El que un sistema operativo sea mejor que otro tiene una parte subjetiva, ya que hay que tomar en cuenta el tipo de computadora para la que estemos seleccionando el sistema operativo y también la función que desempeñará la computadora en cuestión.

Por tipo de computadora no me refiero a el procesador, sino a la clasificación, es decir PC’s (notese que en esta categoría entran también las Mac, ya que PC significa computadora personal y la Mac es una computadora personal), mini computadoras (por ejemplo la AS/400), estaciones de trabajo (como la RS/6000), mainframes (como la S/390), etc.
Cuando digo “la función que desempeñará la computadora” me refiero a tomar en cuenta si es una PC que usará un usuario final para navegar en internet, chatear, escuchar música y enviar y recibir mails o si será un servidor que funcionará como servidor web, servidor de correo, servidor FTP, o cualquier otro uso.

Entonces tenemos que para computadoras personales no hay muchos sistemas operativos que valgan la pena entre los cuales elegir, por ejemplo aparte de GNU/Linux tenemos los basados en BSD (FreeBSD, NetBSD, OpenBSD, y los derivados de estos 3 como PC-BSD, DesktopBSD, DragonFly BSD, etc.). Dentro de los que no son software libre ni open source, tenemos a Mac OS X, el sistema operativo de las Mac, que está basado en Darwin. Aunque Mac OS X no es software libre ni open source, y mucho menos gratuito, Darwin si es open source (http://developer.apple.com/Darwin).

Ahora, para quienes tienen PC’s “antiguas” con procesadores desde 8088 con 640k de RAM existe FreeDOS que es una alternativa a los DOS que no son open source, como MS-DOS de Microsoft, DRDOS de la desaparecida Digital Research, PC-DOS de IBM, etc. Para aquellas PC’s con 512k de RAM o menos, probablemente sirva el sitema operativo CP/M que usaban las Apple IIe y pueden descargar desde aqui http://www.cpm.z80.de/ (lean la licencia antes de usarlo)

Como alternativas para servidores (además de GNU/Linux y los BSD) existen varias versiones de Unix como Solaris cuya versión open source es Open Solaris, AIX de IBM, y otros.

Para las mini computadoras, estaciones de trabajo, etc. existen otros sistemas operativos, la mayoría se puede decir que fueron creados para un modelo específico de computadora, como el OS/400 para las AS/400, el OS/390 para las S/370 y S/390, que antes usaban el sistema operativo MVS. Las computadoras VAX utilizan el sistema operativo OpenVMS, antes llamado sólo VMS.

Espero esto sirva como referencia y ya será iniciativa de cada quien investigar más al respecto.

Renombrar archivos usando C++ en GNU/Linux

Mayo 8, 2009 por rtmex

En GNU/Linux (en los sistemas operativos tipo Unix en general, incluidos FreeBSD, etc.) no es recomendable manejar nombres de archivo que contengan espacios.

Puede darse el caso de que copiemos desde otro sistema operativo archivos que contienen espacios en su nombre, a nuestra máquina con GNU/Linux. Entónces, ¿qué hacer en esos casos?

Efectivamente… “lo recomendable” es renombrarlos para eliminar los espacios que contiene el nombre de archivo. Como puede ser una cantidad considerable de archivos, nos tomaría mucho tiempo ir renombrando archivo por archivo.

Exísten diferentes opciones para automatizar esa tarea, haciendo un script para bash, utilizando AWK y muchas otras soluciones.

A continuación un programa en C++ al que le podemos enviar una lista de directorios para que renombre todos los archivos que se encuentran en ellos eliminando los espacios del nombre de archivo.

/****************************************
 * Archivo: renombrar_archivos.cpp               
 * Autor  : SALOMON RINCON TORRES       
 * Fecha  : 08/05/2009 (dd/mm/yyyy)
 */

#include <iostream>
#include <string>
#include <sys/types.h>
#include <dirent.h>

using namespace std;

string QuitaEspacios(string s_cadena)
{
 string s_aux;

 for (int i_pos = 0; i_pos < s_cadena.length(); i_pos++)
     {
       if (s_cadena[i_pos] != ' ')
           s_aux += s_cadena[i_pos];
     }
 return s_aux;
}

int main (int argc, char *argv[])
{
 DIR *dirh;
 struct dirent *dirp;
 string s_dir, s_nombre, s_nuevonombre;
 int i_renombrados = 0, i_ok = 0, i_fallos = 0;

 for(int i = 1; i < argc; i++)
    {
     s_dir = argv[i];
     i_renombrados = 0;
     i_ok = 0;
     i_fallos = 0;

     cout << "******************** Directorio \"" << s_dir << "\" ********************\n" << endl;

     if ((dirh = opendir(s_dir.c_str())) == NULL)
         perror("No se pudo accesar al directorio ");
     else
        {
         for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
             {
              s_nombre = dirp->d_name;

              // Checamo que no sea el directorio . o ..
              if (s_nombre != "." && s_nombre != "..")
                 {
                  cout << "Archivo: " << s_nombre << endl;

                  // Si el nombre del archivo tiene un espacio, lo renombramos
                  if (s_nombre.find(" ") != string::npos)
                     {           
                      s_nuevonombre = QuitaEspacios(s_nombre);

                      if (rename((s_dir+"/"+dirp->d_name).c_str(), (s_dir+"/"+s_nuevonombre).c_str()) == 0)
                         {
                          i_renombrados++;
                          cout << "   === Renombrado como: " << s_nuevonombre.c_str() << endl;
                         }
                      else
                          {
                           i_fallos++;
                           perror("No se pudo renombrar");
                          }
                     } /* if */
                  else
                      {
                       i_ok++;
                       cout << "OK\n";
                      }
                 } /* if */
             } /* for */

         closedir(dirh);
         cout << endl;
         cout << "--- Archivos renombrados: " << i_renombrados << endl;
         cout << "--- Archivos OK: " << i_ok << endl;
         cout << "--- Archivos que no se pudieron renombrar: " << i_fallos << endl << endl;
        } /* else */
    } /* for */
 return 0;
}

Validar Entry en Gtk#

Abril 24, 2009 por rtmex

Recientemente necesitaba validar un “Entry” en gtk-sharp para que el usuario sólo pudiera capturar números. Nunca antes había programado en Mono y tampoco había desarrollado interfaces gráficas usando Gtk o Gtk#, asi que probablemente este post le sea útil únicamente a novatos en Mono y Gtk# ( como yo :) ).

Buscando en internet encontré 2 posts, de los cuales tome código y le hice pequeñas adecuaciones para crear 2 clases que son subclases de la clase Entry.

Lo que hace el código es capturar el evento KeyPress y verificar la tecla que pulsó el usuario, a partir de ahi decide si es una tecla o caracter permitido o no.

Creé una clase llamada EntryEnteros y una clase llamada EntryDecimales. Las clases son casí idénticas, la diferencia es que la segunda acepta el punto como caracter permitido y la primera no. Esto implica que en la segunda clase se agrega el caracter “.” en la cadena s_charvalidos pero también se captura cuando el usuario pulsa el punto del teclado numérico (Gdk.Key.KP_Decimal).

El código del post http://nexus.developarts.com/limitar_la_captura_de_un_entry#comment-769 no funciona si el usuario usa el teclado numérico para introducir datos, sólo acepta los números de la parte superior del teclado; tampoco permite al usuario moverse con las flechas izquierda o derecha. El código que me sirvió de base para incluir eso está en el post http://mbrenes.blogspot.com/2007_02_01_archive.html pero es para Gtk, así que sólo hice los cambios necesarios para pasarlo a Gtk#.

Este ejemplo fue realizado en Debian Lenny

Esta es la clase EntryEnteros

/* Archivo entryenteros.cs */

using System;
using Gtk;

public class EntryEnteros : Entry
{
   public EntryEnteros()
   {
      KeyPressEvent +=  new KeyPressEventHandler(TeclaPulsada);
   }

   // Conectamos el manejador de eventos antes del evento KeyPress
   [GLib.ConnectBefore ()]

   private void TeclaPulsada(object o, KeyPressEventArgs args)
   {
      string s_charvalidos = "0123456789";

      // Para que al pulsar enter el foco se pase al siguiente control
      if (args.Event.Key == Gdk.Key.Return || args.Event.Key == Gdk.Key.KP_Enter)
         {           
          Toplevel.ChildFocus (DirectionType.TabForward);
          args.RetVal = true;
         }
      else
          // Solo se permiten los caracteres en s_charvalidos, los números del teclado numérico (KP_0...),
          // el backspace, el delete, flecha izquierda, flecha derecha
          if (Array.IndexOf(s_charvalidos.ToCharArray(), Convert.ToChar(args.Event.Key)) == -1 && args.Event.Key!=Gdk.Key.BackSpace && args.Event.Key!=Gdk.Key.Delete && args.Event.Key!=Gdk.Key.Left && args.Event.Key!=Gdk.Key.Right && !(args.Event.Key >=Gdk.Key.KP_0 && args.Event.Key <=Gdk.Key.KP_9))
              args.RetVal = true;     
   }
}

Esta es la clase EntryDecimales

/* Archivo entrydecimales.cs */

using System;
using Gtk;

public class EntryDecimales : Entry
{
   public EntryDecimales()
   {
      KeyPressEvent +=  new KeyPressEventHandler(TeclaPulsada);
   }

   // Conectamos el manejador de eventos antes del evento KeyPress
   [GLib.ConnectBefore ()]

   private void TeclaPulsada(object o, KeyPressEventArgs args)
   {
      string s_charvalidos = "0123456789.";

      // Para que al pulsar enter el foco se pase al siguiente control
      if (args.Event.Key == Gdk.Key.Return || args.Event.Key == Gdk.Key.KP_Enter)
         {           
          Toplevel.ChildFocus (DirectionType.TabForward);
          args.RetVal = true;
         }
      else
          // Solo se permiten los caracteres en s_charvalidos, los números del teclado numérico (KP_0...),
          // el backspace, el delete, flecha izquierda, flecha derecha
          if (Array.IndexOf(s_charvalidos.ToCharArray(), Convert.ToChar(args.Event.Key)) == -1 && args.Event.Key!=Gdk.Key.BackSpace && args.Event.Key!=Gdk.Key.Delete && args.Event.Key!=Gdk.Key.Left && args.Event.Key!=Gdk.Key.Right && args.Event.Key!=Gdk.Key.KP_Decimal && !(args.Event.Key >=Gdk.Key.KP_0 && args.Event.Key <=Gdk.Key.KP_9))
              args.RetVal = true;     
   }
}

Con el siguiente programa podemos probar nuestras 2 clases

/* Archivo prueba.cs */

using System;
using Gtk;

public class prueba
{
    public static void Main()
    {
        Application.Init();
        Window w_principal = new Window("Limitar captura en un Entry");
        w_principal.DeleteEvent += delete_event;

        EntryEnteros e_cantidad = new EntryEnteros ();
        EntryDecimales e_precio = new EntryDecimales ();
        HBox hb_cantidad = new HBox (true, 0);
        HBox hb_precio = new HBox (true, 0);
        VBox vb_contenedor = new VBox();

        hb_cantidad.PackStart (new Label ("Cantidad: "), false, false, 0);
        hb_cantidad.PackStart (e_cantidad);
        hb_precio.PackStart (new Label ("Precio: "), false, false, 0);
        hb_precio.PackStart (e_precio);
        vb_contenedor.PackStart (hb_cantidad, true, true, 0);
        vb_contenedor.PackStart (hb_precio, true, true, 0);

        w_principal.Add(vb_contenedor);
        w_principal.ShowAll();
        Application.Run();
    }

    static void delete_event (object obj, DeleteEventArgs args)
    {
        Application.Quit();
    }
}

Compilamos

gmcs -pkg:gtk-sharp-2.0 prueba.cs entryenteros.cs entrydecimales.cs

Con esto tenemos nuestro archivo prueba.exe, el cual ejecutamos tecleando ./prueba.exe

A continuación una captura de la pantalla ya con datos introducidos

prueba

¿Usar GNU/Linux es dificil?

Marzo 24, 2009 por rtmex

Muchas personas (incluso algunas relacionadas con el campo de la informática) tienen la idea de que usar GNU/Linux (cualquier distribución) es dificil.

Yo considero que no es dificil, el problema es que los que tienen esa idea es porque están acostumbrados a usar otro sistema operativo (generalmene alguna versión de Windows) y les da “miedo” o flojera aprender a utilizar un sistema operativo que nunca han usado. Pero lo mismo pasaría si a una persona que aprendió a usar las computadoras y lo hizo utilizando una computadora con GNU/Linux instalado, despues de algunos años se le pide que utilize Windows.

A todos aquellos que no han utilizado GNU/Linux no me queda mas que decirles que no saben de lo que se están perdiendo. Entre algunas de las ventajas que tienen sistemas operativos como GNU/Linux o cualquiera de los BSD (FreeBSD, NetBSD, OpenBSD, etc.) es su estabilidad, el uso eficiente de los recursos, la seguridad, etc.

Si no eres ingeniero/licenciado en sistemas o informática (digamos que eres contador, abogado, estudiante, o cualquiera que sea tu actividad) y estás pensando que es imposible que dejes de usar Windows y empieces a utilizar GNU/Linux, te invito a que sigas leyendo.

Existe una persona en Argentina llamada Maria Elena Casañas que no estudio sistemas, informática ni algo parecido. Después de haber usado Windows por 15 años descubrio (según sus propias palabras) el software libre y decidió de un dia para otro empezar a utilizar Mandriva (una distribución de GNU/Linux).

¿Qué es lo sorprendente de este relato?, bueno, Maria Elena Casañas aprendió a utilizar una computadora despues de los 50 años (esto quiere decir que con mas de 65 años empezó a utilizar GNU/Linux).

En está página pueden leer la reproducción de un post que ella misma escribió

http://www.kriptopolis.org/linux-para-informaticos

Las sorpresas no terminan ahi, Maria Elena Casañas está tan feliz usando software libre y tan convencida de sus beneficios que tiene una página web dedicada a ayudar a personas comunes, sin conocimientos avanzados de informática a descubrir el mundo del software libre.

http://www.casanas.com.ar/

Además tiene un blog

http://elblogdemec.blogspot.com/

En la página podrán encontrar mucho material que además está explicado con un lenguaje fácil de comprender.

Desde luego la migración de software privativo a software libre no tiene que ser de un dia para otro (no tienes que cambiar de Windows a GNU/Linux en 24 horas), lo más recomendable es hacerlo por etapas; puedes por jemplo empezar por utilizar OpenOffice en lugar de Microsoft Office, instalandolo sobre tu PC con Windows sin problema alguno. Open Office además de ser software libre también es gratuito, te permite hacer prácticamente lo mismo que haces con Microsoft Office y puedes leer archivos generados por Microsoft Office y guardar tus archivos con los formatos utilizados por Microsoft Office (.doc. xls, etc.), para que tus archivos los puedan leer personas que no tengan OpenOffice instalado.

Probablemente estes pensando: “Bueno, el caso de Maria Elena Casañas es un caso extraordinario, no creo que algo asi pase muy seguido”.

Así que dejame darte otro ejemplo: “El cocinero que instaló Debian GNU/Linux y tuvo éxito”

http://casidiablo.net/el-cocinero-que-instalo-debian-gnulinux-y-tuvo-exito/

Te invito a que te hagas las siguientes preguntas:

  1. ¿Será realmente tan difícil usar GNU/Linux cuando una persona de mas de 65 años, “no informática” aprendió a usarlo y lo sigue usando actualmente?
  2. ¿Si Maria Elena Casañas pudo dejar de utilizar Windows después de 15 años para utilizar GNU/Linux, no puedo hacerlo yo?

Si te animas, la página de Maria Elena Casañas es un buen punto de partida.

Agregar y borrar usuarios de Firebird desde C++ builder

Febrero 23, 2009 por rtmex

Agregar usuario

En la pestaña InterBase Admin de C++ builder 6 existe el componente TIBSecurityService, este componente sirve para agregar o borrar usuarios de un servidor de base de datos Firebird, así como para mostrar o modificar su información.

Suponiendo que dejamos la contraseña por default del usuario sysdba de Firebird y tenemos en un formulario de C++ Builder 6 (llamado Form1) un componente TButton llamado Button1 y 4 componentes TEdit llamados e_usuario, e_nombre, e_apellido y e_clave respectivamente, podríamos agregar un componente TIBSecurityService llamado IBSecurityService1 y poner el siguiente código en el evento OnClick de Button1 para agregar un usuario al servidor Firebird con los datos que contengan los TEdit.

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  IBSecurityService1->Params->Values["user_name"]="sysdba";
  IBSecurityService1->Params->Values["password"]="masterkey";

  IBSecurityService1->Active = true;
  try
     {
      IBSecurityService1->UserName = e_usuario->Text;
      IBSecurityService1->FirstName = e_nombre->Text;
      IBSecurityService1->LastName = e_apellido->Text;
      IBSecurityService1->Password = e_clave->Text;
      IBSecurityService1->AddUser();
     }
  __finally
           {
            IBSecurityService1->Active = false;
           }
}

Notese que para indicar el usuario y password con el que se conectará el componente TIBSecurityService se usó

IBSecurityService1->Params->Values["user_name"]=”sysdba”;
IBSecurityService1->Params->Values["password"]=”masterkey”;

y no:

IBSecurityService1->Params->Add(“user_name = sysdba”);
IBSecurityService1->Params->Add(“password = masterkey”);

Ya que marcaría un error como “SPB Constant Unknown

Con esto queda agregado el usuario, pero falta hacer los grants para darle permisos de consulta (grant select), inserción (grant insert), borrado (grant delete) y actualización (grant update) sobre las tablas de la base de datos deseada.

Otorgar grants al usuario

Para esto, crearemos un stored procedure (procedimiento almacenado) en la base de datos.

El stored procedure (que llamaremos sp_Grants) otorgará todos los grants a un usuario sobre una tabla determinada; recibirá como parámetros el usuario y el nombre de la tabla.


/* Este procedure otorga todos los permisos al usuario que recibe como parámetro
   sobre la tabla que recibe como parámetro */

set term !! ;
create procedure sp_Grants(s_tabla varchar(65), s_usuario varchar(8))
as
  begin
        execute statement 'grant all on ' || :s_tabla || ' to ' || :s_usuario;
  end !!
set term ; !!

Agregamos a nuestro formulario un componente TIBDatabase llamado IBDatabase1 y un componente TIBStoredProc llamado IBSP_grants. En la propiedad Database del TIBStoredProc ponemos IBDatabase1 y en la propiedad StoredProcName SP_GRANTS (que es el nombre del stored procedure que creamos en la base de datos).

Por último agregamos un componente TListBox al que llamaremos lb_tablas. Lo que haremos será conectarnos a la base de datos, obtener los nombres de todas las tablas y pasarlos al ListBox, después iremos recorriendo el ListBox para otorgar todos los grants sobre todas las tablas al usuario llamando a nuestro stored procedure.

Basta con agregar el siguiente código al final del código que pusimos anteriormente en el evento OnClick del TButton llamado Button1.

En el ejemplo nuestra base de datos se llama prueba.fdb y se encuentra en el directorio llamado prueba de la unidad c:

 // Asigna la ruta a la base de datos
 IBDatabase1->Params->Values["user_name"]="sysdba";
 IBDatabase1->Params->Values["password"]="masterkey";
 IBDatabase1->DatabaseName = "c:\\prueba\\prueba.fdb";

 // Hace la conexión a la base de datos
 IBDatabase1->Connected=true;

 // Pasa los nombres de las tablas de la base de datos al ListBox
 IBDatabase1->GetTableNames(lb_tablas->Items,False);

 // Se desconecta de la base de datos
 IBDatabase1->Connected=false;

 for (int i_x=0; i_x<lb_tablas->Items->Count; i_x++)
     {
      IBSP_grants->ParamByName("s_tabla")->AsString = Trim(lb_tablas->Items->Strings[i_x]);
      IBSP_grants->ParamByName("s_usuario")->AsString = e_usuario->Text;
      IBSP_grants->ExecProc();
      lb_tablas->ItemIndex++;
     }
 lb_tablas->Clear();

Si queremos que no se vea el ListBox sólo debemos poner false en su propiedad Visible

Borrar usuario

Agregamos un componente TButton al que llamaremos Button2 y en su evento OnClick pondremos el siguiente código


void __fastcall TForm1::Button2Click(TObject *Sender)
{
  IBSecurityService1->Params->Values["user_name"]="sysdba";
  IBSecurityService1->Params->Values["password"]="masterkey";

  IBSecurityService1->Active = true;
  try
     {
      IBSecurityService1->UserName = e_usuario->Text;     
      IBSecurityService1->DeleteUser();
     }
  __finally
           {
            IBSecurityService1->Active = false;
           }
}

Nota: En el post la macro de wordpress muestra finally, pero debe ser __finally