KDM/GDM LINUX MAGAZINE
Configuración del arranque X
CCCP
Autores al Gulag con Paul C. Brown
PHP
Ejecución desde la linea de comandos
KRecipe La cocina KDE de cada día
Edición en Castellano
NÚMERO 03
NÚMERO 3 • P.V.P 4,95 €
Firewalls
Seguridad para todo el mundo
Guarddog Analizadores de Registros
FIREWALLS Configuración sencilla con Guarddog p11 Implementa un cortafuegos puente p14 Registros con Logfile p18
Shorewall
Domótica
Bridgewall
Controla tu casa con un Jabberbot Perl p42
Domótica Perl
Ruby Rails
Autopsy
Una infraestructura web diferente p32
Vigilancia KDM/GDM
CSI del CPU
p55
Análisis de equipos comprometidos con Autopsy
WWW.LINUX- MAGAZINE.COM.ES
Shorewall Configura iptables de sin complicaciones p22
Linux va a CeBIT Muestre sus productos y servicios en la sección especial dedicada a Linux en CeBIT 2005:
Por cuarto año consecutivo, un gran número de compañías y proyectos de código abierto van a presentar sus soluciones de software, productos y servicios en LinuxPark. En CeBIT 2005, LinuxPark será de nuevo el punto de visita obligatoria para lo directivos TI, especialmente aquellos provenientes de las PYMEs y de la administración pública. Sólo hay un sitio en CeBIT con toda la información sobre las tecnologías de código abierto más novedosas y como explotarlas de manera efectiva: LinuxPark. Su empresa también puede beneficiarse enormemente de esta plataforma, ideal para la promoción de sus soluciones de código abierto.
La solución perfecta para su presencia ferial: • Comuníquese directamente con una gran variedad de clientes potenciales • Anúnciese en un campaña promocional anterior a la feria de gran envergadura • Realice su propia presentación en el LinuxForum • Aprenda de ponentes de primera categoría • Consolide sus relaciones con la comunidad Linux internacional • Benefíciese del contacto con socios y patrocinadores de reconocido prestigio en el sector • A su disposición: paquetes feriales todo incluido desde 4 m2
Consiga más información en +49 (0) 26 02 16 01374 ó profair@abresch.de
Patrocinado por:
Presentado por:
Escritorios
EDITORIAL
La Amenaza Fantasma Estimado Lector de Linux Magazine
T
odo el mundo piensa que está a salvo. Nadie piensa que le puede tocar a él/ella. Los accidentes de coche ocurren a los demás, los demás contraen enfermedades incurables, a los demás se les ven introducirse virus en sus sistemas. La desgracia tiene un curioso efecto distanciador. Pero que nadie se crea invulnerable, todo lo contrario: como la sección de invulnerabilidades demuestra mes a mes, los fallos de seguridad que “permiten ejecutar código aleatorio” abundan en el sistema operativo Linux. Es cierto, no más que en otros sistemas, pero, como me recuerda a cada oportunidad mi esposa cada vez que hablamos de cambiarnos de casa: “No vayamos a compararnos con lo que no queremos ser”. Y, sí, es una gran ventaja que haya tanta gente auditando y probando el software de manera abierta y se publiquen los resultados para que nos curemos en salud. Defender la protección a través de la ocultación es como defender aquello de, bueno, sí, las alas del avión están pegadas con chicle… pero no se caerán si no se lo decimos a nadie. Sin embargo, el peligro existe en el ámbito de la informática y no sólo viene bajo la forma de virus, troyanos y “jaquens” aburridos, de los que buena cuenta damos en este número y, por tanto, sobre los que no me voy a explayar. Hablo de otro peligro, mucho más insidioso contra el cual no te puedes proteger configurando un firewall, deshabilitando servicios o blindando el sistema. Y no importará el sistema que utilices, ya sea Linux, Windows, Mac o BSD, siempre estarás a la merced de uno de sus ataques, los cuales vienen sin avisar y sin motivo aparente. Hablo de los abogados.
El ataque te puede venir en la forma de carta de SCO reclamándote el pago de un impuesto revolucionario que a santo de qué, o te puede llegar como aviso de citación a juicio por no pagar una factura de un servicio telefónico que por supuesto no has contratado ni mucho menos utilizado. A mí me llegó una de dichas cartas hace un par de días. 69,72 euros es el motivo de que me quieren arrastrar a juicio los ilustres señores letrados. Esta gente son los encargados de perseguir a toda esa panda de sinvergüenzas internautas que rehúsa pagar servicios de ADSL que no funcionan, facturas emitidas después de bajas o misteriosos cobros por servicios no contratados, el cual, como digo, es mi caso. Su cliente, WANADOO S.L., asegura que servidor contrató un servicio de telefonía llamado rimbombantemente “Premier Plus”. Ahora bien, servidor no es ningún lince legal, pero creo que sin contrato firmado no hay tu tía… Y esto lo confirmó mi abogado, que sí lo es. (He de decir que mi abogado es de los buenos. Es un encanto, lo puedes sacar de la jaula y todo y no se pleitea con nadie a no ser que le caiga realmente mal). Ni que decir tiene que ni servidor jamás ha contratado, suscrito, solicitado, ni mucho menos disfrutado de este excelso servicio. Pero eso da igual. Un día vas caminando por la calle, te cae una maceta en la cabeza y te quedas en el sitio; o administras un sistema para una importante firma y un estúpido script-kiddie logra cargarse todo la base de datos de clientes y proveedores, junto con el fichero donde guardabas tus partidas de Quake; o un día estás sentado en tu casa y, mira por donde, te meten un pleito… Y ¡plas! Te has convertido en una estadística. De humano te has transformado en una cifra en las listas de la DGT o de las crecientes casos de abusos por parte de operadores de telefonía. Si no pago 69,72 euros antes del día 11 del corriente (enero), me arrastrarán a juicio, me demostrarán culpable, pedirán
Nos sentimos orgullosos de nuestros orígenes como publicación, que se remonta a los primero días de la revolución Linux. Nuestra revista hermana, la publicación alemana Linux Magazin, fundada en 1994, fue la primera revista dedicada a Linux en Europa. Desde aquellas tempranas fechas hasta hoy, nuestra red y experiencia han crecido y se han expandido a la par que la comunidad Linux a lo ancho y largo del mundo. Como lector de Linux Magazine, te unes a una red de información dedicada a la distribución del conocimiento y experiencia técnica. No nos limitamos a informar sobre el movimiento Linux y de Software Libre, sino que somos parte integral de él.
la pena capital para mi y mis allegados y, de paso, escupirán sobre mi tumba. Lo peor de todo es que para mandarles un burofax jurando que no he sido yo, Correos me cobra 20 euros, perder una mañana de trabajo para ir a juicio puede costar unos 50 euros, aparcar en el centro 4 euros. La minuta del abogado me puede salir por 300 euros. Que el juez me de la razón, no tiene precio, pero para todo lo demás, Mastercard. La solución fácil: pagar los 69,72 euros y olvidarse. Pero, haciendo esto ¿no dejo abiertas la puertas a más chantajes por parte de las operadoras y sus canes legales? Así que ya sabéis: una vez instalado vuestro firewall, deshabilitado servicios innecesarios y blindado vuestro sistema siguiendo los buenos consejos de Linux Magazine… ¡cuidado con los abogados!
Paul C. Brown Director
www.linuxmagazine.com.es
Número 03
3
LINUX MAGAZINE
Contenido
NOTICIAS
11
Inseguridades ....................................................................................6 Negocios ................................................................................................8 Correo ......................................................................................................9 PORTADA
Guarddog
El programa KDE Guarddog promete una configuración fácil del cortafuegos de Linux con tan solo unos cuantos clics. Guarddog ayuda a los usuarios inexpertos a proteger sus máquinas, e incluso redes completas, contra los atacantes.
Especial Cortafuegos ..................................................................10 Guarddog .............................................................................................11 KDE ofrece una aplicación que simplifica en gran medida la configuración de un cortafuegos.
Bridgewall ...........................................................................................14
14
Los cortafuegos pueden implementar como routers, pero también pueden filtrar a nivel de puente.
Normalmente los cortafuegos se implementan como routers, pero no tiene por qué ser así. Los filtros a nivel del bridge tienen una serie de ventajas que puede añadirlas a su red en una etapa más tardía sin necesidad de cambiar la configuración de los componentes de red.
Logfile ....................................................................................................18 Analizar los datos de ataques puede ser tan importante como evitarlos.
Shorewall ............................................................................................22 Shorewall Simplifica la configuración de iptables del kernel.
DESARROLLO
Bridgewall
La librería SDL (III) .........................................................................27 Abordamos el control del protagonista y de los enemigos en nuestro juego.
Ruby Rails
...........................................................................................32
Una infraestructura para aplicaciones web diferente
Interfaces
18 ............................................................................................37
Integramos la librería menu.h en una clase que simplifica la creación de interfaces con el usuario.
Jabberbot ............................................................................................42 Controla las luces de tu casa a distancia con perl y un jabberbot.
PHP en Línea ....................................................................................46 PHP no sólo sirve para programar aplicacionesc web. Vemos como escribir programas para la línea de comandos.
Python y la RAE ..............................................................................49 Creamos un diccionario de interfaz minimal que consulta palabras en la web de la RAE.
4
Número 03
www.linuxmagazine.com.es
Shorewall
Cuando los usuarios piensan en su estación de trabajo en casa olvidan normalmente la seguridad. Pero el peligro acecha, esperando golpear a los desprevenidos. Shorewall ayuda a los usuarios habituales de Linux a mantener a los intrusos fuera.
Contenido
32
LINUX MAGAZINE
SYSADMIN
Ruby Rails
La mayoría de las bibliotecas web hacen que el 90 por ciento del trabajo sea fácil y el resto imposible. Rails, un infraestructura de código abierto programado en Ruby, es lo bastante flexible como para tener éxito con ese 10 por ciento restante.
La Columna de Charly
...............................................................54 Los mejores trucos y consejos del SysAdmin.
Autopsy
................................................................................................55
En esta segunda parte dedicada al análisis forense, estudiamos un ordenador comprometido con Autopsy.
Suspend
...............................................................................................59
La hibernación de un ordenador consiste en volcar la RAM a swap y después recuperarla. Analizamos el software para hacerlo.
LINUX USER
KHotkeys
59
Suspend
Casi todas las placas bases tienen la característica de control de energía, diseñada para apagar el ordenador y ponerlo en modo suspendido. En la vida real, esta característica no siempre funciona. Linux tiene varias alternativas para tratar de solucionar el problema.
............................................................................................64
Implementar gestos de ratón y teclas personalizadas bajo KDE es fácil con KHotkeys.
DeskTOPia: Krecipe
.....................................................................67
Un recetario digital para el escritorio KDE.
Configuración: KDM/GDM .....................................................73 Aprendemos como configurar el arranque gráfico de Linux.
Curso de Programación: XUL (III) .......................................76 Un lenguaje sencillo para programar interfaces web.
Educación: WIMS (III) ..................................................................81 Un ejemplo práctico de clases con WIMS.
Comandos: su y sudo ..................................................................84 Ser root es imprescindible... de vez en cuando. su y sudo ayudan a no abusar.
64
KHotkeys
Los gestos con el ratón y los atajos con el teclado añaden velocidad y simplicidad a las operaciones con el PC. Los gestos de ratón solían ser coto privado de los usuarios de Opera y de Mozilla, pero KHotKeys las ofrece ahora a Konqueror para usuarios de KDE 3.2 o superior. Incluso podemos lanzar programas no-KDE con KHotKeys.
Tipografía con LaTeX (III)..........................................................87 Documentos de aspecto profesional con LaTeX.
COMUNIDAD
Humor ...................................................................................................92 Proyectos
............................................................................................95
Eventos .................................................................................................97 Contacto ..............................................................................................97 Próximo Número ..........................................................................98
www.linuxmagazine.com.es
Número 03
5
NOTICIAS
Inseguridades
Inseguridades ■ Cyrus-imapd El servidor Cyrus IMAP es un servidor de correo electrónico eficiente y altamente escalable. Se han descubierto múltiples vulnerabilidades en los analizadores de argumentos de los comandos partial y fetch del servidor. El proyecto de Vulnerabilidades y Exposiciones Comunes (Common Vulnerabilities and Exposures o CVE - http://cve.mitre.org) ha asignado el nombre CAN-2004-1012 y CAN-2004-1013 a este problema. También existen problemas de desbordamiento de búfers en el código ‘imap magic plus’ que son vulnerables de ser explotados (CAN-2004-1011 y CAN-20041015). Un atacante podría explotar estas vulnerabilidades para ejecutar código arbitrario con los permisos del usuario que ejecuta el servidor Cyrus IMAP. No existe ninguna solución por el momento para este problema. Todos los usuarios de Cyrus IMAP deberán actualizar sus ■ servidores a la última versión. -Referencia Debian: DSA-597-1 cyrus-imapd -Referencia Gentoo: GLSA 200411-34 /cyrus-imapd -Referencia Suse: SUSE-SA:2004:043
■ Ruby Ruby es un lenguaje de scripts interpretado para la creación de programas orientados a objetos de manera fácil y rápida. El módulo CGI de Ruby puede ser utilizado para crear aplicaciones web. Los desarrolladores de Ruby encontraron y arreglaron un fallo del módulo CGI que permitía su activación remota. Esta vulnerabilidad podía, en teoría, provocar un bucle infinito. Una atacante remoto podría activar la vulnerabilidad a través de una aplicación web Ruby expuesta y provocar que el servidor utilizara recursos de CPU innecesarios, lo que podría causar un ataque por denegación de servicio. Mitre ha asignado el nombre CAN-2004-0983 a este problema. No existe solución para este problema en el módulo CGI de Ruby. Todos los
6
Número 03
usuarios de Ruby 1.6.x deberán actualizar sus versiones. ■ -Referencia Mandrake: MDKSA-2004:128
■ Kernel El kernel Linux se encarga de llevar a cabo las funciones básicas del sistema operativo. Se ha descubierto un fallo de ausencia de serialización en unix_dgram_recvmsg que afecta a kernels anteriores al 2.4.28. Un usuario local podría potencialmente aprovecharse de una condición de carrera para hacerse con privilegios de root. Se pueden consultar más detalles sobre estos problemas en la base de datos del proyecto de Vulnerabilidades y Exposiciones Comunes (Common Vulnerabilities and Exposures o CVE http://cve.mitre.org). Véase CAN-20041068. Paul Starzetz de iSEC descubrió varios fallos en el cargador binario ELF, fallos que afectan a kernels anteriores a 2.4.28. Un usuario local podría utilizar estos fallos para conseguir acceso de lectura a binarios sólo ejecutables o posiblemente conseguir privilegios (CAN-2004-1070, CAN-2004-1071, CAN-2004-1072 y CAN2004-1073). Se descubrió un fallo en la configuración de límites TSS que afecta a los kernels para las arquitecturas AMD AMD64 e Intel EM64T anteriores a 2.4.23. Un usuario local podría provocar una ataque de denegación de servicio o cuelgue del sistema o, posiblemente, conseguir privilegios (CAN-2004-0812). Se ha descubierto un fallo de desbordamiento de entero en la función ubsec_keysetup en el driver Broadcom 5820 cryptonet. En los sistemas que utilicen este driver, un usuario local podría provocar un ataque de denegación de servicio (o cuelgue del sistema) o utilizar el fallo para adquirir privilegios (CAN2004-0619). Stefan Esser descubrió varios fallos, incluyendo desbordamientos de búfers en el driver smbfs en kernels anteriores a
www.linuxmagazine.com.es
2.4.28. Un usuario local podría provocar un ataque de denegación de servicio (cuelgue) o utilizar el fallo para escalar privilegios. Para poder explotar este fallo, el atacante necesitaría tener el control de un servidor Samba (CAN-20040883 y CAN-2004-0949). SGI descubrió un error en el cargador elf que afecta a los kernels anteriores a 2.4.25 que podría activarse con un binario malformado. En arquitecturas diferentes a x86, un usuario local podría crear un binario malicioso que provocara un ataque de denegación de servicio o cuelgue (CAN-2004-0136). Conectiva descubrió fallos en drivers USB que afectaban los kernels anteriores a 2.4.27 que utilizaban las funciones copy_to_user en estructuras no inicializadas. Estos fallos podrían permitir a usuarios leer pequeñas cantidades de la memoria del kernel (CAN-2004-0685). ■ -Referencia Red Hat: RHSA 2004:549-10 -Referencia Suse: SUSE-SA:2004:042
■ Plugin Java de Sun La seguridad en los entornos del plugin Java de Sun y Blackdown Java puede ser sobreseído para conseguir el acceso a paquetes arbitrarios, lo que permitiría que applets sin confianza llevaran a cabo acciones sin restricciones en sistema huésped. El proyecto de Vulnerabilidades y Exposiciones Comunes (Common Vulnerabilities and Exposures o CVE http://cve.mitre.org) ha asignado el nombre CAN-2004-1012 y CAN-20041029 a este problema. Tanto Sun como Blackdown proporcionan implementaciones del Kit de Desarrollo Java (JDK) y el entorno de ejecución Java (JRE). Ambas implementaciones contienen un plugin Java que permite la ejecución de applets Java en un entorno restringido en navegadores web. Todos los plugins Java están sujetos a una vulnerabilidad que permite el acceso no restringido a paquetes Java. Un atacante remoto podría embeber un applet Java malicioso en una página web y engañar a un víctima para que la visualizase. Este applet podría sobreseer las restricciones de seguridad y ejecutar cualquier comando o acceder a cualquier fichero con los permisos del usuario visualizando la página web.
Inseguridades
La solución inmediata es deshabilitar los applets Java en los navegadores web. Todos los usuarios de Sun JDK deberán actualizar sus versiones. ■ -Referencia Gentoo: GLSA 200411-38/Java
■ BNC BNC es un proxy de devolución de sesiones IRB. Leon Juranic descubrió que BNC no siempre protege a los búfers de la sobreescritura. Esto podía ser explotado por un servidor malicioso IRC para desbordar un búfer de tamaño limitado y ejecutar código arbitrario en el host cliente. El proyecto de Vulnerabilidades y Exposiciones Comunes (Common Vulnerabilities and Exposures o CVE - http://cve.mitre.org) ha asignado el nombre CAN-2004-1052 a ■ este problema. -Referencia Debian: DSA-595-1 bnc -Referencia Gentoo: GLSA 200411-24/ BNC.
■ ez-ipupdate ez-ipupdate es una utilidad para actualizar información de nombres de hosts para un gran número de servicios de DNS dinámicos. Ulf Harnhammar, del Proyecto de Auditorías de Seguridad de Debian, descubrió una vulnerabilidad de formato de cadena en ez-ipupdate. A este problema se la ha asignado el Mitre ■ CVE CAN-2004-0980. -Referencia Debian: DSA-592-1 ez-ipu date -Referencia Gentoo: GLSA 200411-20/ ez-ipupdate
■ Samba Samba es una implementación SMB/CIFS abierto y libre que permite una interoperabilidad sin fisuras de servicios de ficheros e impresión con clientes SMB/ CIFS. Se han identificado varias vulnerabilidades en Samba recientemente. Existe un problema con el demonio del servicio de compartición de ficheros de Samba, el que permite a un usuario remoto hacer que el servicio consuma mucha potencia de computación, lo que podría conllevar potencialmente un cuelgue al consultar nombres de ficheros con comodines especiales. Este ataque puede tener éxito si el demonio Samba está en ejecución y un
usuario remoto tiene acceso a una compartición (aunque sólo sea en modo lectura). A este problema se la ha asignado el Mitre CVE CAN-2004-0930. Stefan Esser descubrió un problema en el manejo de cadenas Unicode en el manejo de ficheros Samba que podría conllevar un desbordamiento de pila remoto y podría permitir a usuarios remotos inyectar código en el proceso smbd. A este problema se le ha asignado el Mitre CVE CAN-2004-0882. Los paquetes actualizados no son vulnerables a estos problemas. Se recomienda que todos los usuarios de Samba se ■ actualicen a la última versión. -Referencia Gentoo: GLSA 200411-21/ samba -Referencia Mandrake: MDKSA-2004:136 -Referencia Red Hat: RHSA-2004:632-17 -Referencia Suse: SUSE-SA:2004:040.
NOTICIAS
■ sudo sudo es un programa que aporta privilegios de superusuario limitados a usuarios específicos. Liam Helmer notó que sudo no limpia el entorno lo suficiente. Algunas funciones de bash y la variable CDPATH se siguen pasando al programa en ejecución como usuario privilegiado. Este hecho deja el sistema vulnerable a la posibilidad de que un atacante pueda encontrar una manera de sobrecargar las rutinas del sistema. A este problema se le ha asignado el Mitre CVE CAN-2004-1051. Estas vulnerabilidades sólo pueden ser explotadas por usuarios a quienes se les haya otorgado privilegios de superusuario limitados. Se recomienda actua■ lizar los paquetes sudo instalados. -Referencia Debian: DSA-596-2 sudo -Referencia Mandrake: MDKSA-2004:133
Políticas de seguridad de la Distribuciones Mayoritarias Distribuidor
Fuente Seguridad
Debian
Info:http://www.debian.org/security/ Lista:http://www.debian.org/debian-security-announce/ Referencia:DSA-…1)
Gentoo
Mandrake
Red Hat
Slackware
Suse
Comentario
Los avisos de seguridad actuales se incluyen en la página de inicio. Los avisos se proveen como páginas HTML con enlaces a los parches. Los avisos también incluyen una referencia a la lista de correo. Info:http://www.gentoo.org/security/en/index.xml Los avisos de seguridad actuales para Foro:http://forums.gentoo.org/ la lista Gentoo en el sitio web de Lista:http://www.gentoo.org/main/en/lists.xml seguridad de Gentoo enlazan desde la Referencia:GLSA:… 1) página principal. Los avisos se presentan en HTML con códigos para fusionar las versiones corregidas. Info:http://www.mandrakesecure.net Mandrakesoft posee su propios sitio web Lista:http://www.mandrakesecure.net/en/mlist.php que versa sobre temas relacionadas con Referencia:MDKSA:… 1) la seguridad. Entre otras cosas,incluye de avisos seguridad y referencias a las listas de correo. Los avisos son páginas HTML, pero no contienen enlaces a los parches. Info:http://www.redhat.com/errata/ Red Hat archiva los fallos de seguridad Lista:http://www.redhat.com/mailman/listinfo/ bajo lo que denominan erratas. A Referencia:RHSA-… 1) continuación los problemas para cada versión de Red Hat se agrupan. Los avisos de seguridad se proveen como una página HTML con enlaces a los parches. Info:http://www.slackware.com/security La página de inicio contiene enlaces al Lista:http://www.slackware.com/lists/(slackware-security) archivo de seguridad de la lista de correo. Referencia:[slackware-security]… 1) No existe información adicional sobre seguridad en Slackware. Info:http://www.suse.de/en/private/support/ Ya no existe un enlace a la página de security/index.html seguridad tras un remodelado en el sitio Parches:http://www.suse.de/en/private/ web de SuSE. Existe información en la download/updates Lista:suse-security-announce lista de correos y los avisos. Los parches de Referencia:SUSE-SA… 1) seguridad para versiones individuales de SuSE Linux se muestran de color rojo en el sitio de actualizaciones generales. Contiene una corta descripción de la vulnerabilidad que el parche soluciona.
1) Todos los distribuidores muestran correos de seguridad en el campo Subject.
www.linuxmagazine.com.es
Número 03
7
NOTICIAS
Negocios
Negocios ■ IBM Dona Patentes IBM es año sí y año también la compañía que más patentes registra a nivel mundial. El año 2004 no fue una excepción: el Gran Azul registró 3.248 patentes, 1.314 más que los de cualquier otra empresa. Afortunadamente, IBM también tiene un compromiso contraído con la comunidad del software libre y, en virtud de ello, el 11 de enero de este año, publicaron una nota de prensa declarando que donaban 500 de estos patentes a los desarrolladores del código abierto, para ser utilizados “en cualquier proyecto que se conforme a la definición de software de fuente abierta acuñada por la Open Source Initiative (OSI)”. Algunos de los patentes cedidos van desde lo peregrino (“US6199070 Uso de bases de datos para registros de progra-
mas”) hasta lo ininteligible (“US5634006 Sistema y método para asegurar QOS en una red token ring utilizando un regulador de acceso en cada nodo para la asignación del tamaño de marco para aplicaciones de transmisión virtuales basadas en información negociada y prioridad en la red”) ¿Qué sería mucho mejor que IBM donara TODOS sus patentes o que directamente abandonara su política de registro masivo de patentes? Hombre, eso sería lo ideal… en un mundo ideal, donde nadie más intentara acaparar lo que IBM no registra. Mientras tanto, 500 patentes dona■ dos… pues es un comienzo. http://www-1.ibm.com/press/ Press ServletForm.wss?TemplateName=ShowPre ssReleaseTemplate&SelectString=t1.docunid=7473”.
■ Mandrake para la Empresa Mandrake estuvo a punto de ser financieramente guillotinado en el 2002 cuando se declaró en bancarrota ante un tribunal de cuentas. Pero hete que nuevos vientos soplan para la empresa gala y ya se encuentra casi recuperada de un fatídica gestión por parte de “una plantilla de directivos de categoría mundial con experiencia” (uno ya se puede imaginar el daño que hace un
individuo con semejante título a una compañía, no querremos ni pensar en toda una plantilla). Afortunadamente “los directivos” fueron sumariamente despedidos cuando fue obvio que sus ambiciosos planes lo único que producían eran enormes gastos. En la actualidad, Mandrake ha vuelto a sus orígenes y concentra sus esfuerzos en la producción de buenos productos de código abierto. A la línea de SOs de consumo, y sus ya reputadas distros para fines específicos (p.e.: Multi Network
8
Número 03
Firewall), se suma ahora un tándem de distros diseñado para asaltar la Bastilla de los escritorios corporativos. El dúo de productos se denominan Corporate Desktop y Corporate Server respectivamente. El doblete está diseñado para que ambas partes se integren perfectamente la una con la otra. Por un lado, Corporate Desktop viene con el software necesario para disponer de un escritorio Linux y ser productivo en el área de la ofimática en poco tiempo. Corporate Server, por otro lado, trae todos los servidores necesarios para soportar la carga de un red empresarial. Las dos distribuciones vienen con una serie de los ya habituales asistentes Mandrake para la configuración por separado de cada una, pero también vienen con otra serie de asistentes para integrar los clientes con los servidores y viceversa. El software de escritorio cuesta 99 euros y el servidor 329 euros. Ambos vienen con soporte técnico y con asistentes (como no) para actualizaciones. ■ http://www.mandrakesoft.com/ products.
www.linuxmagazine.com.es
■ El FUD No es Necesariamente Malo... Especialmente si no significa “Fear, Uncertainty and Doubt” (“Miedo, Incertidumbre y Duda”), sino “Fedora Users and Developers” (“Usuarios y Desarrolladores de Fedora”), la asociación de los cuales va a celebrar su primera conferencia internacional el 18 de febrero del 2005 en la Massachusetts Institute of Technology, justo después de la LinuxWorld Conference and Expo. Una de las razones por las que Red Hat, la empresa detrás de la iniciativa, desea promocionar este evento, es por que, sin ser un absoluto fracaso, las aportaciones de la comunidad del código abierto a Fedora ha sido menor del esperado. Greg Dekoenigsberg, director de relaciones con la comunidad de Red Hat, dice que se debe a que “Simplemente no había mucho que pudieran hacer” ya que Red Hat no podía hacer mucho más que aceptar informes de errores. “(Esta vez) queremos asegurarnos de que tenemos los sistemas y procesos que permita a la gente contribuir”. Aparte de la conferencia, Red Hat ha tomado los pasos necesarios para hacer que la contribución por parte de los usuarios sea una realidad. Por un lado ha abierto el CVS para que los usuarios puedan acceder a software en fase de desarrollo. En breve, los desarrolladores externos también podrán aprobar contribuciones al árbol de desarrollo. Asimismo, la empresa ha empezado un proyecto llamado “Fedora Extras”, que permite a terceros mantener paquetes que se hallan fuera de la responsabilidad directa de Fedora. Y, por último, ofrecen servidores accesibles públicamente que permiten automatizar el proceso de construcción de software Fedora y los extras mencionados. Estos servidores permitirán evaluar posibles conflictos ■ entre componentes. http://fedora.redhat.com/ http:// fedoraproject.org/wiki/FUDCon1.
Buzón del Lector
CORREO
Correo del Lector
Acceso de Escritura ■ De Vuelta al Cole, Paul Hace unos días que cayó en mis manos el número 1 de vuestra revista y tras leerlo por completo decidí comprar el número 2 y realizar la suscripción de prueba para los 3 siguientes números. La revista me parece bien elaborada en cuanto a contenidos, algo pobre en cuanto a diseño gráfico aunque aceptable si lo comparamos con el resto de revistas de similar temática pero sobre todo me pareció muy decepcionante en lo referente a ortografía, gramática y expresión. A lo largo de las páginas de ambos números hay tildes que no están puestas, errores gramaticales, frases que no llegan a término, confusiones entre “a ver” y “haber”, errores de guionado y lo que me ha impulsado a escribir este correo: el título del artículo de la página 83 del segundo número que dice “Bienvenidos a la Aula Virtual”. El título es digno de ser usado como comentario de texto en un aula presencial de un curso no superior a quinto de primaria, pero su autor ha necesitado largos años de estudio, una amplia experiencia laboral y, seguramente, el paso por la universidad para cometer semejante tropelía lingüística. Yo comprendo que los costes de producción de una revista y los escasos márgenes comerciales (?) que deja, no permiten mantener en plantilla a un corector de estilo, pero incorrecciones como la de ese título ni siquiera traspasan por la “ventana” de los correctores ortográficos de procesadores de
texto, por lo que tampoco debieran pasar de largo a los ojos del maquetista, el editor o incluso el director editorial (y no digamos del autor). Pero eso sí, jamás debiera ser el lector quien tenga que padecer tales incorrecciones. En definitiva, la técnica no está reñida, ni debe estarlo nunca, con la lingüistica y la mejor forma de expresar y transmitir el conocimiento técnico es hacerlo con corrección y rigor lingüístico. Muchas gracias por leer mi correo y espero que la revista eleve el listón de la calidad de las publicaciones técnicas. Un saludo. Fernando Bueno
Puedes enviar tus comentarios y sugerencias a
LM Tienes toda la razón. Lamentablemente (y sirva de excusa) en estos momentos contamos con un equipo de esqueleto de correctores (una sola persona) que ha de corregir las cien páginas de la revista en un tiempo récord, mientras compagina sus tareas con otros menesteres. En cuanto al garrafal titular que mencionas, he de decir en defensa del autor, Juan Rafael Fernández, que Juan Rafael no comete errores. Es un profesor de largo historial y ahora coordina cursos de Guadalinex para profesores de centros educativos para la Junta de Andalucía. Es escrupuloso tanto en lo que se refiere al contenido técnico de sus artículos, como en lo que se refiere a su ortografía y gramática.
Por tanto, descartando al redactor como autor del fallo ¿a quien hay que culpar? Pues al director, a servidor, al que suscribe. ¡Sí, fui yo! ¡Paul C. Brown! ¡Lo admito! En un arrebato de megalomanía, decidí modificar el título original de Juan Rafael (muy largo para mi gusto) por otro con más gancho y, a la postre, un fallo gramatical horroroso. Espero que tanto los lectores como el autor sepan disculparme y prometo pensármelo dos veces antes de meterle mano a otro titular sin consultarlo ■ primero.
LM Lamentamos informaros a todos los que nos habéis preguntado lo mismo que de momento Linux Magazine no puede servir suscripciones contrareembolso, ni prevemos hacerlo en el futuro. Sin embargo, existe una solución: la transferencia bancaria. Para todos aquellos que desean realizar un pago controlado, podéis mandarnos un correo a subs@linuxmagazine.com.es y os facilitaremos los detalles para realizar la transacción.
Para los que han expresado preocupación sobre la seguridad del sistema, informaros que el formulario donde se consignan los datos en la web está protegido contra abusos y los detalles que viajan por correo hasta nuestro buzón de suscripciones se encriptan con una clave PGP de 1024 bits, por tanto, al menos hasta que se popularicen los ordenadores cuánticos, podemos decir que ■ vuestros datos están seguros.
correo@linuxmagazine.com.es
■ Subscripción El mes pasado, compré en la calle el número 1 de la revista Linux magazine. Me gustaría beneficiarme de la oferta de tres primeros números de prueba al precio de 5 euros pero solamente haciendo el pago contra reembolso. Me gustaría saber lo antes posible si puedo hacerlo de esta forma. Gracias, Un saludo. Lucas Jiménez
www.linuxmagazine.com.es
Número 03
9
PORTADA
Introducción
Cortafuegos para el día a día
No Sólo para Expertos Los cortafuegos son cada vez más complejos. Por suerte, las herramientas para su manejo son cada vez más simples y más accesibles para los usuarios normales. POR JOE CASAD Y ACHIM LEITNER
S
u ordenador le permite ver el mundo, pero usted no quiere que el mundo le vea. Los intrusos son cada vez más sofisticados y cabe esperar a que alguno se de cuenta tarde o temprano de que su equipo está sin protección. Si se conecta a Internet, necesita estar detrás de algún tipo de cortafuegos. Hay cortafuegos de muchos tamaños, formas, precios y diseños. Es Bastante interesante notar que, lo que se solía llamar cortafuegos, ahora tan solo es uno más de la gran gama de productos de
EN PORTADA Guarddog.........................................11 a utilidad de KDE Guarddog proporciona un interfaz intuitivo para la configuración de cortafuegos en Linux.
Brigdewall ......................................14 Un cortafuegos a nivel de bridge puede proporcionar una solución simple con un mínimo de reconfiguración.
Analizadores Registros ...........18 Herramientas para analizar los ficheros de log y que nos ayudan a entender el estado de la red.
Shorewall .......................................22 Shorewall es un conjunto de ficheros para la configuración de cortafuegos basados en filtros de red.
seguridad. El cortafuegos tradicional es una especie de router que reside en la Capa 3 del modelo de referencia OSI. La Capa 3 es la capa de la pila que escucha al Protocolo de Internet, lee direcciones IP y toma decisiones sobre donde dirigir los datagramas IP. Un cortafuegos además inspecciona las cabeceras de la Capa 4 (TCP o UDP) para identificar servicios y evaluar flags. Pero los productos de cortafuegos modernos pueden operar en otros niveles de la pila de protocolos (Figura 1). Esta metodología multinivel puede extenderse de modo descendente a la Capa 2, donde encontrará el llamado bridgewall. Mientras que un bridge (o switch) simplemente evaluará la dirección MAC, el bridgewall inspeccionará los paquetes de la Capa 2 hasta la Capa 4. El bridgewall es un filtrador de paquetes hecho y derecho, tan flexible como un switch. Un gateway a nivel de aplicación proporciona una capa adicional de seguridad al más alto nivel. El gateway captura la conexión TCP actuando como un proxy entre el cliente y el servidor. Esto permite al cortafuegos antes de finalizar mirar el protocolo de aplicación y detectar los paquetes ilegales que incumplan las reglas del protocolo basadas en RFC.
Figura 1: Los cortafuegos modernos puede actuar como bridges (izquierda), routers (centro) o gateways a nivel de aplicación (derecha).
10
Número 03
www.linuxmagazine.com.es
Por supuesto que la mayoría de las variantes de cortafuegos son productos caros para grandes redes y configuraciones complejas. Nosotros estamos más interesados en lo que podemos hacer sólo con Linux y con un software de cortafuegos fácil de encontrar. Como veremos en el tema de portada de este mes, Linux tiene una buena colección de cortafuegos, incluyendo algunas utilidades poderosas que simplifican el proceso de configuración de modo que no hace falta ser un experto para manejar uno. En nuestro artículo sobre Guarddog vamos a mostrar como usar este programa KDE para realizar configuraciones de cortafuegos IPTables o IPChains. En nuestro siguiente artículo, sobre Bridgewall, hablamos de los instrumentos para configurar un cortafuegos a nivel de la Capa 2. Un problema en el manejo de cortafuegos es la cantidad de datos que maneja y que se acumulan en los registros del software de protección. En nuestro tercer artículo se habla de herramientas para el manejo y análisis de los registros de los cortafuegos. Y nuestra última historia describe Shorewall, otra utilidad que no es un cortafuegos propiamente hablando, sino un instrumento para simplificar la ■ configuración de un cortafuegos.
Guarddog
PORTADA
Configuraciones de cortafuegos con Guarddog
¡Cuidado con el Perro! El programa KDE Guarddog promete una configuración fácil del cortafuegos de Linux con tan solo unos cuantos clics. Guarddog ayuda a los usuarios inexpertos a proteger sus máquinas, e incluso redes completas, contra los atacantes. POR HOLGER JUNGE
L
as herramientas IPChains (Linux 2.2) e IPTables (Linux 2.4) configuran el cortafuegos de Linux, pero estas herramientas de línea de comandos pueden ser algo crípticas para los recién llegados a Linux. Simon Edwards desarrolló Guarddog [1] para simplificar la tarea de configurar el cortafuegos. Guarddog es una utilidad basada en GUI para manejar los cortafuegos. La utilidad Guarddog viene con licencia GPL y funciona tanto en KDE 2 como KDE 3. Los usuarios se pueden descargar la versión estable 2.2.0 desde [2]. Además de los fuentes, el sitio tiene también disponible los binarios ya listos para ser ejecutados para Mandrake, Red Hat y Debian. Si desea probar las últimas características, pruebe la versión 2.3.2 desde [2]. Pero antes de hacerlo, compruebe los pros y los contras en el cuadro “Para los Valientes”.
Guarddog está diseñado para usuarios domésticos o de redes privadas. Aunque distribuciones como Red Hat, Mandrake y Suse tienen herramientas simples basadas en GUI para los cortafuegos, carecen de la posibilidad de manejar sistemas distribuidos. Los usuarios más exigentes que requieran una configuración más detallada, probablemente preferirán usar Guarddog.
Agujeros de Seguridad Los usuarios inexpertos tienen que ser muy cuidadosos cuando configuren un
cortafuegos con Guarddog. La facilidad que supone escoger una opción y hacer clicen ella de la GUI a menudo lleva a los usuarios a abrir más puertos de los necesarios. Por otro lado, es bastante fácil “reforzar” una máquina hasta tal punto que algunos servicios dejen de funcionar. También hay que tener en cuenta que Guarddog es una aplicación KDE y no debería ejecutarse en un servidor en el sentido tradicional de la palabra. Si tiene un servidor dedicado en su LAN, lo propio es crear una configuración con
Para los Valientes La versión de desarrollo actual de Guarddog es la 2.3.2. Hay varias reticencias para usar esta versión en entornos productivos. Por un lado, el usuario valiente puede encontrar algunas características nuevas. La versión 2.3.2 soporta áreas de puertos para los protocolos definidos por el usuario. Los desarrolladores han modificado también la versión para soportar Linux 2.6 y han añadido algunos protocolos nuevos a la lista, como RSync, Distcc, GKRellm, Bittorrent, PGP Key Server, Jabber sobre SSL y el protocolo Microsoft Media Server.
www.linuxmagazine.com.es
Número 03
11
PORTADA
Guarddog
Figura 1: El GUI de Guarddog después de ser ejecutado con dos zonas de red
Figura 2: La solapa Protocol permite especificar el protocolo permitido o dene-
preconfiguradas: Internet y Local.
gado por el cortafuegos. No hay que preocuparse por los números de puerto.
Guarddog en un ordenador distinto y luego copiar el script resultante al servidor. Como Guarddog está basado en IPChains o en IPTables, los usuarios deben asegurarse que los módulos necesarios del kernel estén disponibles en el servidor. La mayoría de las distribuciones se hacen cargo de esto automáticamente. Si su distribución no lo hace, necesitará recompilar el kernel para que incluya IPTables o IPChains. Guarddog usa comandos filtros orientados al protocolo. Los usuarios no necesitan especificar los números de puertos, lo que ayuda a evitar errores de configuración. Asimismo Guarddog soporta grupos de máquinas o zonas y permite a los usuarios la opción de establecer zonas desmilitarizadas (DMZ).
que no esté incluida en cualquier otra zona. Local incluye las direcciones de la tarjeta de red local. Una máquina individual estará bien con tan solo estas dos zonas. Se puede usar la solapa Protocol (Figura 2) para permitir o denegar protocolos específicos. La estructura en árbol del lado derecho de la ventana organiza los protocolos por categorías. Normalmente el servicio DNS es el primero que se necesita habilitar. La entrada DNS está ubicada en la categoría Network. Haciendo clic en la caja de verificación de DNS – Domain Name Server se coloca una marca de verificación que indica que el servicio está permitido.
(Asegúrese que se aplican los cambios pulsando Apply). Si se pulsa de nuevo la caja de verificación la marca se transforma en una X para indicar que el cortafuegos denegará de forma explícita las conexiones que usen este protocolo. Una caja de verificación vacía indica que el cortafuegos ignorará cualquier petición al puerto. Los protocolos HTTP, FTP (en la categoría File Transfer) y los protocolos de correo SMTP y POP3 son otros protocolos que se usan habitualmente.
Registro de Protocolos La solapa Logging (véase la Figura 3) proporciona opciones detalladas para el
La GUI Se debe ejecutar Guarddog con los privilegios de root para permitir al programa aplicar las reglas del cortafuegos. La Figura 1 muestra Guarddog justo después de haber sido ejecutado. Desafortunadamente, la GUI de Guarddog no es muy intuitiva. La GUI de Guarddog tiene cuatro solapas. La primera de estas solapas, la solapa Zones, permite a los usuarios agrupar las máquinas en zonas. Zone Properties acepta direcciones IP o rangos de direcciones para la zona. Hay dos zonas preconfiguradas llamadas Internet y Local que el usuario no puede borrar. La zona Internet automáticamente incluye cualquier dirección IP
12
Número 03
Figura 3: Los administradores pueden usar la solapa Logging para especificar que clase de registro debe proporcionar el cortafuegos.
www.linuxmagazine.com.es
Guarddog
PORTADA
sencillo y almacenarlo en /etc/rc.firewall. Como los servidores normalmente no ejecutan KDE, los administradores pueden simplemente pulsar el botón Export para exportar un script, copiar este script al servidor y ejecutarlo en él.
Puerta de Enlace al Mundo
Figura 4: Guarddog soporta configuraciones del cortafuegos detalladas. Por ejemplo, los usuarios pueden definir protocolos y exportar e importar scripts.
registro de Guarddog en syslog. El registro proporciona a los usuarios una herramienta para detectar escaneos de puertos. Los usuarios de Guarddog pueden establecer la tasa de registro para restringir el número de entradas en los registros del cortafuegos. Un límite para el número máximo de entradas ayudará a evitar un ataque potencial por denegación de servicios, que a veces es causado por una tormenta de paquetes IP que llenan el syslog y sobrecarga el disco duro. Si necesita detalles de todos los paquetes IP y TCP entrantes, puede seleccionarse la opción para registrar todos los paquetes y los números de secuencia TCP en la base de la ventana. La solapa Advanced (véase la Figura 4) permite a los administradores experimentados ajustar con precisión las
opciones del cortafuegos para reflejar sus necesidades. Si algo va mal, no se preocupe: siempre se puede pulsar en Restore to factory defaults… para restaurar las opciones por defecto de Guarddog. Las opciones por defecto para Local Dynamic Port Range están bien en la mayoría de los casos. Especifica que rango de puertos puede usar Linux para las conexiones salientes. Si echa en falta algún protocolo en la solapa Protocol, puede pulsar New Protocol e introducir el nombre del protocolo, establecer si el protocolo es TCP o UDP y especificar los números de puertos que usa. Guarddog tiene una opción útil para importar y exportar los scripts de cortafuegos creados con la herramienta. Guarddog puede exportar la configuración actual a un script de la shell
Desde luego, los cortafuegos de Linux no se usan típicamente para los sistemas aislados, sino que se usan como parte de la estructura de seguridad de una red completa. En este caso, la máquina Linux actúa como una puerta de enlace y tiene dos tarjetas de red, una de cara a Internet y otra de cara a la red interna (véase la Figura 5). Es bastante simple configurar Guarddog para este escenario, sin embargo se necesita un sistema con la versión 2.4 del kernel. Además de configurar IP masquerading antes de instalar el cortafuegos. Guarddog no puede ayudarle en este paso, pero sí la herramienta Guidedog en [4]. El primer paso es crear una zona Guarddog nueva para la red local. Para hacerlo, pulse New Zone en la solapa Zone. Se puede llamar a la zona “LAN”, por ejemplo. Después púlsese New Address para establecer la dirección IP, tal como 192.168.1.0/24. Ahora púlsese en Internet y Local en Connection para asegurar que la LAN está conectada a Internet y al ordenador local. Seleccione Internet en la solapa Protocol y marque las cajas para los protocolos requeridos en la columna de la LAN. Finalmente, pulse Apply para almacenar la configuración en /etc/rc.firewall y lance el cortafuegos. ■
INFO [1] Guarddog:http://www.simonzone.com/ software/guarddog [2] Descarga: http://www.simonzone.com/ software/guarddog/#download [3] Manual online: http://www.simonzone. com/software/guarddog/#manual
Figura 5: El ordenador cortafuegos de Linux actúa como puerta de enlace para la red interna.
EL AUTOR
[4] Guidedog: http://www.simonzone.com/ software/guidedog/
Holger Junge trabaja para Lifemedien, donde se encarga de los servidores de dominio, de los servidores Web, el servidor de base de datos MySQL y el servidor de base de datos Oracle.
www.linuxmagazine.com.es
Número 03
13
PORTADA
Bridgewall
Implementando un cortafuegos a nivel de bridge
Puente Levadizo
Normalmente los cortafuegos se implementan como routers, pero no tiene por qué ser así. Los filtros a nivel del bridge tienen una serie de ventajas que puede añadirlas a su red en una etapa más tardía sin necesidad de cambiar la configuración de los componentes de red. POR RALF SPENNEBERG
L
inux se ha ganado una buena reputación como plataforma para implementar un cortafuegos. El kernel posee un poderoso filtro de paquetes basado en Netfilter/IPTables. En un escenario clásico de cortafuegos, Netfilter está en el router, donde divide la red en dos o más subredes. Pero el añadir un cortafuegos a una red ya instalada puede suponer cambiar la infraestructura de la misma. Este
14
Número 03
esfuerzo supone cambiar las direcciones IP y modificar los controles de accesos a los servicios internos. Es bastante sencillo añadir un bridge. Los bridges actúan en la capa 2 del Modelo de Referencia OSI y normalmente inspeccionan las direcciones MAC en vez de las direcciones IP (véase el cuadro titulado “Construyendo Puentes”). Linux realiza esta tarea de forma inteligente efectuando un filtrado
www.linuxmagazine.com.es
transparente como cortafuegos de la red. Por supuesto, el puente evalúa los paquetes de los protocolos de las capas superiores (direcciones IP, puertos TCP) en su rol de cortafuegos. Pero los hosts de la red no notarán nada, a menos que intenten enviar paquetes ilegales.
Configuración del Kernel Lennert Buytenhek y Bart de Schuymer desarrollaron un parche que
Bridgewall
PORTADA
Figura 1: Para permitir el modo bridge con el kernel 2.6, los administradores
Figura 2: La opción Bridged IP/ARP packets filtering en la configuración de fil-
necesitan seleccionar 802.1d Ethernet Bridging en Networking Support.
trado de red del kernel debe estar habilitada.
añade la funcionalidad de cortafuegos a nivel de bridge al kernel 2.4 de Linux. El kernel 2.6 lleva el parche instalado por defecto y los administradores simplemente tienen que configurar el kernel correctamente (véanse las Figuras 1 y 2). Todas las opciones del bridge en el grupo netfilter son importantes, por ejemplo, ARPtables soporta IP_NF_ARPTABLES, IP_NF_ARPFILTER y IP_NF_ARP_MANGLE. Estas funciones pueden implementarse como módulos o bien ir incluidas dentro del kernel. El soporte de Physdev match también es importante: IP_NF_MATCH_PHYSDEV. Esta opción es necesaria en el kernel 2.6 o posteriores para comprobar el interfaz físico cuando filtre paquetes en el bridge. Una vez que se haya compilado e instalado el nuevo kernel de forma satisfactoria, tan solo serán necesarias algunas herramientas de usuario. Aunque la mayoría de las distribuciones traen el programa iptables, habrá que instalar arptables y ebtables. Si se está ejecutando el kernel 2.6 o uno anterior, también habrá que instalar una versión más reciente del comando iptables. El paquete bridge-utils [2] es necesario para configurar el bridge. Las distribuciones modernas normalmente instalan
este paquete por defecto. El paquete contiene el comando brctl, cuyo uso está reservado al usuario root. El comando brctl addbr br0 crea un bridge llamado br0. El comando ip link show br0 confirma la existencia del bridge. Como el bridge tiene un nombre, se pueden ejecutar múltiples bridges virtuales en una misma máquina Linux. A continuación el bridge necesita saber qué tarjetas Ethernet (NICs) tiene que controlar. El comando brctl permite asignar las NICs al bridge: brctl addif br0 eth0 brctl addif br0 eth1
Las tarjetas de red no deben estar configuradas en este punto; es decir, no deben estar UP o tener una dirección IP. La idea es habilitar las tarjetas después de habérselas asignado al bridge: ip link set eth0 up ip link set eth1 up ip link set br0 up
El bridge ya está listo para entrar en acción, como el comando ip link show muestra (Figura 3). El bridge redirige los paquetes y mantiene su propia caché ARP; usa la caché para registrar las entradas mostrando qué dirección MAC tiene asignada cada interfaz
Tabla 1: Physdev Match Opción
Significado
--physdev-in Nombre regla.
Especifica el puerto por el que el paquete tiene que llegar al bridge para que se le aplique esta
--physdev-out Nombre Especifica el puerto por el que el paquete tiene que salir del bridge para que se le aplique esta regla. --physdev-is-in
El paquete viene desde un interfaz conectado al bridge.
--physdev-is-out
El paquete saldrá del ordenador vía un interfaz conectado al bridge.
--physdev-is-bridged
El paquete viaja a través del bridge.
(véase el Puentes”).
cuadro
“Construyendo
Bloqueando el Puente Como cualquier otro cortafuegos, el bridge tiene un conjunto de reglas que describen qué paquetes debe permitir y cuales debe denegar. Hay tres comandos para crear dichas reglas: • iptables • ebtables • arptables Todos los paquetes que el puente redirige pasan por el filtro de red FORDWARD. Hay algunas cosas a destacar cuando se usan las bien conocidas iptables en un bridge. Si una regla especifica que los paquetes pueden pasar por el bridge en una única dirección, es importante usar -m physdev (véase la Tabla 1). Esto permite a la política identificar el puerto del bridge por el cual el paquete llega o comprobar si incluso debe ser manipulado por el bridge. El siguiente ejemplo está diseñado para permitir conexiones SSH a la dirección IP 192.168.0.16 (puerto TCP 22) en una única dirección. El servidor SSH está accesible por eth1. Las conexiones sólo pueden establecerse por clientes conectados por eth0. Se necesitan dos comandos iptables para definir dicha política: iptables -A FORWARD -m physdev --physdev-in eth0 U --physdev-out eth1 --dport 22 -d 192.168.0.16 U -m state --state NEW -j ACCEPT iptables -A FORWARD -m physdev --physdev-is-bridged -m state --state ESTABLISHED,RELATED U -j ACCEPT
www.linuxmagazine.com.es
Número 03
15
PORTADA
Bridgewall
perteneciente a esta conexión pasar por el bridge.
Colección de Direcciones Los cortafuegos a nivel de bridge se utilizan muy a menudo para añadir seguridad a las redes, eliminando la Figura 3: El bridge virtual está ejecutándose. La salida de ip necesidad de cambiar la link show muestra los datos del bridge seguidos de la etiqueta infraestructura de la red y las :4 bro:. direcciones IP. Un punto posible de inserción es justo El primer comando se encarga del delante del router que el administrador establecimiento de las conexiones, que no pueda cambiar o que no posea funestá restringido en la dirección deseada. cionalidades de cortafuegos. Pero lo El segundo permite a cualquier paquete mejor que hacen los cortafuegos a nivel
de brigde es subdividir redes que anteriormente estaban contiguas. En este caso, las direcciones IP en cada lado del bridge no pueden ser de rangos específicos ya que han sido asignadas de forma arbitraria. El comando ipset proporciona a los administradores un medio para subdividir la red: ipset crea un conjunto de direcciones del que los administradores pueden coleccionar direcciones IP arbitrarias. Las siguientes líneas crean un conjunto de direcciones llamado left y añade tres direcciones IP al conjunto: ipset -F; ipset -X; ipset -N U left iphash
Construyendo Puentes El término bridge se refiere a una categoría de dispositivos que manejan directamente el reenvío de paquetes de red en la capa 2 del modelo OSI. (Los dispositivos conocidos como switch son un tipo de bridge). Para reenviar paquetes de la capa 2, el bridge tiene que obtener las direcciones MAC de la red local y recordar que interfaces y puertos pertenecen a qué ordenador. Cuando el bridge recibe un paquete con un destino cuya dirección MAC es conocida, simplemente lo reenvía al interfaz correcto y de este modo evita el tráfico innecesario. Si el bridge no conoce la dirección MAC del destino, tendrá que reenviarlo por todos los interfaces. El comando brctl showmacs bro lista todas las direcciones MAC conocidas de un bridge. El comando proporciona una tabla de entradas. La primera columna contiene el número de puerto para la entrega de paquetes del ordenador y la segunda columna tiene la dirección MAC. Le siguen más columnas con información de configuración.
olvidara las direcciones MAC no usadas inmediatamente. En vez de ello, el bridge etiqueta primero las entradas no usadas como inválidas y luego las elimina a intervalos regulares (conocidos como intervalos de recolección de basura). Se puede establecer dicho intervalo introduciendo el comando: brctl setgcint bro segundos. Por defecto es 0 segundos. El protocolo Spanning Tree Los switches modernos usan el protocolo spanning tree para proporcionar una configuración avanzada. Si dos o más switches conectan dos subredes, descubren todas las rutas posibles de una red a otra. Después de elegir un switch como raíz , el switch raíz define caminos activos e inactivos a través de la red y propaga esta información a todos los switches que haya en la red. Los switches bloquean los caminos y los interfaces inactivos, impidiendo el duplicado de paquetes (paquetes que vayan por dos
caminos) que puedan llegar a la red destino (véase la Figura 4). Si un switch falla, el resto de los switches descubren de nuevo qué caminos están aún disponibles y evitan el paso por el switch caído. Linux soporta el protocolo spanning tree, sin embargo, los administradores necesitan introducir el comando brctl stp bro on para activarlo. Los bridges pueden asignarse con una prioridad de 0 a 65535: brctl setbridgeprio bro prioridad. El bridge con la prioridad más baja asume la función de raíz. Test de Función Los bridges comprueban si los otros bridges están funcionando enviando un mensaje “hello” a intervalos regulares. Los administradores pueden establecer el intervalo de intercambios de mensajes “hello” introduciendo brctl sethello bro segundos. El comando brctl setmaxage bro segundos especifica cuánto tiempo el otro bridge debe esperar si no recibe un mensaje “hello”. Pasado este intervalo, el bridge asume que el otro está fuera de servicio. Cuando un bridge está conectado a una red,debe esperar un período de tiempo antes de empezar a reenviar paquetes. Tiene que usar este período para comprobar si la red usa el protocolo STP. El siguiente comando establece el retraso inicial:brctl setfd bro segundos.
Olvido de Tablas Para estar al corriente, el bridge elimina las entradas de direcciones MAC antiguas de su base de datos de reenvios. Los administradores pueden especificar cuánto tiempo debe mantenerse una dirección MAC no usada en la base de datos antes de deshacerse de ella. El comando para esto es brctl setageingtime bro segundos. El esfuerzo computacional interno sería excesiva e innecesariamente alto, si el bridge
16
Número 03
Figura 4: Los bridges 1 y 2 conectan las redes A y B. El bridge con la prioridad más baja usa STP para definir caminos válidos para los paquetes enviados desde A a B.
www.linuxmagazine.com.es
STP debe estar desactivado en un bridge de filtrado: brctl stp bro off. El cortafuegos tiene que confiar en sus propias reglas y debe evitar ser deshabilitado por un ataque STP.
Bridgewall
PORTADA
Listado 1: MAC-NAT
Figura 5: La página de Sourceforge para EBtables proporciona documentación y ejemplos del mundo real.
ipset -A left 192.168.0.5 ipset -A left 192.168.0.17 ipset -A left 192.168.0.18
El nuevo conjunto puede utilizarse por las reglas IPtables. Con la opción -m set se maneja esto. -set Nombre especifica el conjunto: iptables -A FORWARD -m physdev --physdev-in eth0 U --physdev-out eth1 --dport 22 -m set U --set left -m state --state NEW -j ACCEPT
Además de los paquetes IP, los paquetes ARP son también objetivo de las reglas del cortafuegos. Muchos ataques a través de redes internas están basados en la manipulación de peticiones y respuestas ARP.
ARPtables El comando arptables filtra paquetes ARP. Fuera de las operaciones del bridge, el comando sólo tiene sentido en las cadenas INPUT y OUTPUT, ya que los routers no redirigen los paquetes ARP. Pero en un bridge, ARPtables puede filtrar paquetes en la cadena FORWARD. La sintaxis del comando es similar a iptables. ARPtables usa los objetivos ACCEPT y DROP, la opción REJECT no tiene sentido aquí. arptables -A FORWARD -s ! U 192.168.0.15
--destination-mac U fe:fd:0:0:0:1 -j DROP
Esta sintaxis elimina todas los paquetes respuestas ARP enviados al ordenador con la dirección MAC fe:fd:0:0:0:1 que no son originados desde el ordenador con la IP 192.168.0.15. El paquete de respuesta ARP le dice a una entidad solicitante la dirección MAC asociada con la dirección IP especificada. Aquí el ordenador con la dirección MAC fe:fd:0:0:0:1, que está en la red al otro lado del bridge, sólo consigue ver la dirección MAC del ordenador con la dirección IP 192.168.0.15.
EBtables El comando ebtables es mucho más potente que el ARPtables. El comando ebtables soporta NAT para las direcciones MAC del bridge. El bridge incluso puede impedir a los atacantes averiguar la dirección MAC de un ordenador conectado a otro puerto. El bridge envía su propia dirección MAC en respuesta a solicitudes ARP y proporciona MACNAT para todos los paquetes IP. El primer comando en el Listado 1 le dice al bridge que responda con su propia dirección MAC (0:ff:90:2b:a6:16) a cualquier solicitud ARP que quiera saber la dirección MAC para la IP 192.168.0.16. La dirección IP del ordenador que se desea esconder detrás del bridge necesita seguir: --arp-ip-dst. --arpreply-mac es la dirección MAC del bridge. Para los
01 01 ebtables -t nat -A PREROUTING -p ARP --arp-ip-dst -j arpreply 02 --arpreply-mac 0:ff:90:2b:a6:16 03 02 ebtables -t nat -A PREROUTING -p IPv4 -d 0:ff:90:2b:a6:16 --ip-dst 04 192.168.0.16 -j dnat --to-dst fe:fd:0:0:0:1 --dnat-target ACCEPT 05 03 ebtables -t nat -A POSTROUTING 06 -p IPv4 -s fe:fd:0:0:0:1 -j snat --to-src 0:ff:90:2b:a6:16 07 --snat-target ACCEPT
paquetes IP de MAC-NAT, adicionalmente se necesitan las líneas 2 y 3 del Listado 1. En nuestro ejemplo 192.168.0.16 es la dirección IP del ordenador que se esconderá detrás del bridge, y su dirección MAC es fe:fd:0:0:0:1. La excelente documentación en la página Web de EBtables en [3] proporciona más información sobre las capacidades del comando ebtables.
En las Profundidades de la Red Un cortafuegos a nivel de bridge proporciona a los administradores una nueva clase de filtrado de paquetes que permite mayor control sobre la capa 2. Lo realmente práctico de los cortafuegos de tipo bridge es que pueden añadirse de forma transparente a una red existente. El bridge simplemente reemplaza a un hub, switch o cable cruzado en una red. Si se necesita bloquear unos cuantos ordenadores con apariencia sospechosa detrás de un cortafuegos, se puede hacer sin tener que reconfigurar la red entera simplemente añadiendo un cortafuegos a nivel ■ de bridge.
INFO [1] IPtables: http://www.iptables.org [2] Linux bridge: http://bridge.sf.net [3] EBtables: http://ebtables.sf.net
www.linuxmagazine.com.es
Número 03
17
PORTADA
Analizadores de Registros de Cortafuegos
Herramientas de Análisis para Ficheros de Registros de Cortafuegos
Análisis Final El cortafuegos Netfilter crea ficheros de registros muy detallados que realmente nadie quiere inspeccionar a mano. Las herramientas de análisis de ficheros de registros como IPtables Log Analyzer,Wallfire Wflogs y FWlogwatch ayudan a los administradores a seguir la pista de acontecimientos y de filtros para mensajes importantes. POR RALF SPENNEBERG
E
n un entorno protegido por un cortafuegos, el administrador debe seguir la pista de los acontecimientos mediante el registro de tantas transacciones como sean posibles. Al mismo tiempo, los administradores quieren evitar inspeccionar ficheros de registros de cientos de megabytes porque sólo están interesados en algunos en concreto.
Asistentes para los Ficheros de Registros Las herramientas de análisis de protocolo proporcionan una solución a este dilema. Los usuarios de Linux tienen varias opciones a la hora de elegir un programa de análisis de cortafuegos. En
18
Número 03
este artículo, veremos tres alternativas: IPtables Log Analyzer [1], WFlogs del proyecto Wallfire [2] y FWlogwatch [3]. Los tres programas soportan una amplia gama de protocolos y muestran los resultados como páginas HTML muy bien formateadas; WFlogs y FWlogwatch además tienen modos en tiempo real. IPtables Log Analyzer es la única herramienta que utiliza bases de datos para el almacenamiento de mensajes. IPtables Log Analyzer se basa en un sistema de entrada especial. Ulogd de Harald Weltes [4] maneja esto de forma nativa, sustituyendo el sistema de syslog que trae por defecto. Desafortunadamente, las herramientas de análisis gratuitas que soportan las bases de
www.linuxmagazine.com.es
datos Ulog son raras. Ulogd-php [5] es uno de los primeros. Al contrario que los otros sistemas de registros, Ulogd puede registrar los eventos que causaron una alerta en el cortafuegos en su base de datos.
IPtables Log Analyzer IPtables Log Analyzer presta servicio a los registros de IPtables para Linux 2.4 o 2.6 en formato de páginas HTML (Ver Figura 1). La herramienta incluye tres componentes. El sistema de entrada de la base de datos almacena los eventos en una base de datos MySQL; los administradores pueden usar el interfaz web para acceder a la base de datos. El sistema de entrada de la base de datos, la
Analizadores de Registros de Cortafuegos
PORTADA
Listado 1: Base de Datos MySQL
Figura 1: IPtables Log Analyzer da al administrador una clara visión de los ficheros de registros del corta-
01 # mysql -u root -p 02 mysql> create database 03 iptables; 04 mysql> grant 05 create,select,insert on 06 iptables.* to 07 iptables_admin@localhost 08 identified by 'g3h31m'; 09 mysql> grant create,select on 10 iptables.* to 11 iptables_user@localhost 12 identified by 'auchgeheim'; 13 mysql> quit 14 # cat sql/db.sql | mysql -u 15 iptables_admin -p iptables
fuegos.
base de datos y el interfaz web pueden ejecutarse todos en la misma máquina o en máquinas distintas. Por otro lado, la base de datos puede almacenar ficheros de registros de varios cortafuegos. Después de decidir la arquitectura, el administrador necesita crear una base de datos MySQl denominada iptables, permitir a los usuarios el acceso a iptables_admin e iptables_user y generar tablas en la base de datos (Listado 1). También es necesario definir las reglas de IPtables. Dos cadenas definidas por el usuario es la mejor forma (Listado 2).
Creando Cadenas En vez de -j ACCEPT, IPtables ahora usará -j LOG_ACCEPT. Estas modificaciones no son necesarias para Shorewall [6] o Suse Firewall en CD [7]. Sin embargo Suse dice que no dará soporte a su producto de cortafuegos en el futuro, que es otra razón para que los administradores escojan herramientas y actualizaciones del mundo de código abierto. El siguiente paso es instalar el interfaz web. Para hacer esto, el administrador necesita mover el directorio web al directorio raíz del servidor web y modificar config.php para reflejar los
parámetros de la base de datos y la configuración del servidor web (usuario, password, URL). El último paso es instalar y activar el sistema de entrada de la base de datos. Será necesario de nuevo modificar las credenciales de los usuarios de la base de datos. IPtables Log Analyzer tiene tres variantes del sistema de entrada de la base de datos denominadas feed_db.pl, feed_db-shore-wall.pl y feed_dbsuse.php. Para lanzar el sistema de entrada automáticamente, el administrador necesita mover el script de arranque, scripts/iptablelog, a /etc/init.d y crear los enlaces en rc.
WFlogs WFlogs es la herramienta de análisis que pertenece al proyecto Wallfire [2], aunque puede usarse independientemente. El módulo del programa analiza y procesa Netfilter, Ipchains, IPfilter, Cisco PIX, Cisco IOS y ficheros de registro Snort, mostrando los resultados como texto, HTML, XML o en tiempo real. WFlogs no tiene soporte de base de datos, pero puede convertir formatos de ficheros de registros entre Netfilter, IPchains e IPfilter. Instalar WFlogs en Debian es muy fácil. Debian Sid incluye WFlogs y los
paquetes para Woody están disponibles en [8]. Los usuarios de otras distribuciones pueden compilar WFlogs desde el código fuente. Wflogs también necesita la biblioteca WFnetobjs, otro componente de Wallfire [2]. La librería alternativa DNS, adns [9], también se recomienda para la resolución de nombres de forma asíncrona DNS. Para compilar Wflogs, se siguen los pasos típicos ./configure; make; make install; se necesitará especificar el directorio de WFnetobjs en los pasos de configuración.
De Netfilter a HTML WFlogs puede procesar los registros del cortafuegos de forma online u offline. Los siguientes comandos crean una vista en formato HTML de un fichero de registro de Netfilter (Figura 2): wflogs -i netfilter -o htmlU netfilter.log > logs.html
En el modo tiempo real, WFlogs analiza las nuevas entradas del fichero de registros y muestra por pantalla estas entradas. Los administradores pueden usar la shell para modificar interactivamente el comportamiento de WFlogs. Los siguientes comandos le dicen a
www.linuxmagazine.com.es
Número 03
19
PORTADA
Analizadores de Registros de Cortafuegos
WFlogs que monitorice interactivamente un fichero denominado /var/log/warn en tiempo real: wflogs -RI -o humanU /var/log/warn
La opción -P le dice a WFlogs que procese los mensajes más antiguos del fichero. WFlogs no se lanza por mensajes que no sean del cortafuegos.
Filtrado Las opciones de filtrado pueden restringir la salida a mensajes específicos. El filtro siguiente es de la documentación de WFlogs; lista las conexiones Telnet y SSH denegadas para los últimos tres días de la red 10.0.0.0/8:
Figura 2: La página del Resumen de WFlogs muestra cuantos paquetes han sido registrados para cada fuente.
wflogs -f '$start_time >= U this 3 days ago] &&$start_timeU < [this 2 days ago] && U $chainlabel =~ /(DROP|REJECT)/U && $sipaddr == 10.0.0.0/8 && U $protocol == tcp && ($dport ==U ssh || $dport == telnet) && U ($tcpflags & SYN)' -i U netfilter -o text U --summary=no
FWlogwatch Boris Wesslowski desarrolló FWlogwatch para RUS-CERT en la Universidad de Stuttgart, Alemania. La versión 1.0 [3] de la herramienta de análisis ahora ha sido lanzada bajo licencia GPL. FWlogwatch tiene tres modos de operación: Modo Log Summary, Modo Interactive Report y Modo Realtime Response. En el modo Log Summary, el programa genera texto o páginas HTML con el resumen del análisis de los ficheros de registros del cortafuegos (Figura 3). En el modo Interactive Report, FWlogwatch genera automáticamente informes de incidencias que los administradores pueden reenviar a quienes hayan sido afectados por el incidente. En el modo Realtime, FWlogwatch responde a ataques ejecutando scripts,
20
Número 03
procesos make && make install && make install-config. Boris Wesslowski tiene los paquetes para Red Hat y Debian en la página principal del sitio web de Fwlogwatch. Los administradores pueden configurar el comportamiento de FWlogwatch usando el archivo de configuración, que viene sumamente comentado. También pueden configurar FWlogwatch mediante la línea de comandos. En las páginas de ayuda (comando man) vienen explicadas las opciones. Por ejemplo, el siguiente comando ejecuta FWlogwatch en modo resumen:
enviando mensajes de correo o automáticamente modificando las reglas del cortafuegos. Los administradores pueden usar el servidor web integrado para supervisar el estado de FWlogwatch desde un navegador web. FWlogwatch soporta IPchains (opción i), Netfilter (n), Ipfilter (f), IPFW (b), Cisco IOS (c), Cisco PIX (p), Netscreen (e), Windows XP (w), Elsa Lancom (l) y formatos Snort (s). La instalación es tan fácil como lanzar los
Listado 2: Analizador de Registros de IPtables 01 02 03 04 05 06 07 08 09 10 11 12 13
iptables -N LOG_DROP
iptables -A LOG_DROP -j LOG -log-tcp-options --log-ipoptions --log-prefix '[IPTABLES DROP] :' iptables -A LOG_DROP -j DROP iptables -N LOG_ACCEPT iptables -A LOG_ACCEPT -j LOG --log-tcp-options --log-ipoptions --log-prefix '[IPTABLES ACCEPT] : ' iptables -A LOG_ACCEPT -j ACCEPT
www.linuxmagazine.com.es
fwlogwatch -b -Pn -U U 'Spenneberg.Com'-p -n -N -o U output.html -t -w U /var/log/messages
La opción -Pn habilita el analizador de Netfilter. -U permite al usuario especificar una cabecera para el resumen. La opción -o especifica el fichero de salida; w estipula la salida HTML. -n y -N permite la resolución de nombres de hosts y servicios. El resultado es un resumen en formato HTML del fichero de registros del cortafuegos.
Respuesta Rápida La opción de ejecución de FWlogwatch en modo tiempo real permite a los administradores reaccionar ante mensajes del fichero de registros y a la vez mostrar el estado actual en la ventana del navegador. FWlogwatch se ejecuta en segundo plano como un servicio y monitoriza el fichero de registros, analizando de nuevo el archivo de configuración si se recibe un SIGHUP. SIGUSR1 le indica al servicio que vuelva a abrir el fichero de registros. Esta característica es útil para ir rotando ficheros de registros, por ejemplo. Los administradores pueden especificar el valor umbral para que FWlogwatch reaccione a mensajes del fichero de registros disparando alarmas o respondiendo con scripts. Hay dos
Analizadores de Registros de Cortafuegos
PORTADA
opciones de configuración importantes: recent (-l) define el período de tiempo a monitorizar y alert_threshold (-a) define el número de eventos que en este tiempo tienen que suceder para lanzar una respuesta. El Listado 3 muestra su configuración. Este ejemplo configura FWlogwatch para el modo en tiempo real
Listado 3: Fwlogwatch en Modo Tiempo Real realtime_response = yes
02 03 04 05 06 07 08 09
parser = n run_as = fwloguser recent = 600 alert_threshold = 5 notify = yes notification_script = /usr/ sbin/fwlw_notify server_status = yes
10 11 12 13 14 15
bind_to = 127.0.0.1 listen_port = 8888 status_user = ralf status_password = i0QlAmOg4PrAA refresh = 10
Figura 3: En Modo Resumen, FWlogwatch da a los administradores una vista de la actividad del fichero de registro del cortafuegos.
con el analizador Netfilter. El proceso se ejecuta bajo la identificación de usuario fwloguser. Si se excede el umbral de cinco conexiones en 600 segundos, Fwlogwatch realiza una acción configurable. Fwlogwatch monta un servidor de web en 127.0.0.1:8888, donde un usuario ralf puede conectarse con la contraseña password. FWlogwatch utiliza contraseñas encriptadas con DES, que pueden generarse tecleando htpasswd -nb usuario
INFO [1] IPtables Log Analyzer: http://www.gege. org/iptables/ Figura 4: El servidor web integrado en FWlogwatch permite a los administradores monitorizar
[2] Proyecto Wallfire (WFlogs y WFnetobjs): http://www.wallfire.org [3] FWlogwatch: http://fwlogwatch. inside-security.de
el estado actual del cortafuegos.
[4] Ulogd: http://gnumonks.org/projects/ ulogd [5] Ulogd PHP:http://www.inl.fr/download/ ulog-php.html [6] Cortafuegos Shorewall: http://shorewall. sourceforge.net [7] Cortafuegos Suse:http://www.suse.de/ en/ business/products/suse_business/ firewall/ Figura 5: Los administradores pueden utilizar un navegador para configurar FWlogwatch. El Alert Threshold especifica el número de mensajes nece-
[8] Paquetes WFlogs,Debian Woody: http:// people.debian.org/~kelbert/ [9] GNU adns:http://www.chiark.greenend. org.uk/~ian/adns/
contraseña. Cuando el usuario se registra en esta página, aparece lo mostrado en la Figura 4. Esta página conduce a otras páginas con una amplia gama de opciones de configuración de Fwlogwatch (Figura 5).
Opciones FWlogwatch tiene una enorme variedad de características, que van desde un simple resumen hasta un modo en tiempo real con respuestas configurables. Pero las otras herramientas que se comentan en este artículo merecen también una buena consideración. Si necesita filtros potentes, WFlogs puede ser una buena opción para su red. El IPtables Log Analyzer es una opción interesante para algunas situaciones por su soporte de base de datos. El IPtables Log Analyzer da a los administradores de sistemas la opción de utilización de sentencias SQL para buscar los mensajes del cortafuegos, en vez de tener que lanzar las búsquedas desde ■ una interfaz web.
EL AUTOR
01
Ralf Spenneberg es un freelance de Unix/Linux, profesor y autor. El año pasado vió la luz su primer libro:“Sistemas de Intrusión y Detección para Servidores Linux”. Ralf también ha desarrollado varios trabajos de educación.
sarios para lanzar la respuesta de FWlogwatch.
E
www.linuxmagazine.com.es
Número 03
21
PORTADA
Shorewall
Configuración de Netfilter y tablas ip con Shorewall
La Mesa Servida Cuando los usuarios piensan en su estación de trabajo en casa olvidan normalmente la seguridad. Pero el peligro acecha, esperando golpear a los desprevenidos. Shorewall ayuda a los usuarios habituales de Linux a mantener a los intrusos fuera. POR JAMES MOHR
L
a única forma de que nuestro sistema sea completamente seguro frente a ataques es no conectarlo nunca a Internet. Cada vez que abrimos la puerta para salir también la abrimos para que hackers potenciales entren. Algunos usuarios tienen la equivocada creencia de que los intrusos solo atacan sitios de alto renombre y no están interesados en estaciones de trabajo personales. La verdad es que todas las estaciones de trabajo conectadas a Internet están en peligro de ser atacadas, incluso las que se conectan mediante teléfono analógico normal. En muchos casos estos ataques son aleatorios, de fuerza bruta, donde el atacante utiliza una larga lista de conocidos agujeros de seguridad. Para frustrar a los atacantes simplemente podríamos deshabilitar todos los puertos de entrada, haciendo en esencia nuestro equipo invisible al mundo. Sin embargo, cuando necesitamos o simplemente queremos proporcionar servicios desde nuestro ordenador debemos usar otro tipo de protección.
22
Número 03
Incluso el más pequeño de los negocios necesita la protección que proporciona un cortafuegos. La mayoría de los usuarios no puede permitirse los miles de dólares que cuesta un cortafuegos comercial. Afortunadamente hay soluciones de código abierto que ofrecen la protección adecuada. Una de esas soluciones es Shorewall.
Entre Bastidores Shorewall es el nombre común del cortafuegos Shoreline Firewall. Desde la perspectiva del usuario, Shorewall es un conjunto de archivos fáciles de configurar que se utilizan para configurar Netfilter [1]. Netfilter es una función del núcleo de Linux 2.4.x y 2.6.x que permite a los módulos del núcleo acceder al conjunto de protocolos de red en distintos lugares. El módulo del núcleo puede hacer casi todos con el paquete de red, incluyendo simplemente dejarlos caer o manipularlo. Netfilter también soporta las antiguas ipchains, la instalación empaquetada de filtro en núcleos 2.2. Netfilter nece-
www.linuxmagazine.com.es
sita ser específicamente configurado en el modo “compatibles con ipchains” para que trabaje con éstas. Podemos descargar la última versión de Shorewall desde la página Web de Shorewall Web [2] bien como código o como paquete RPM. Debemos saber que la versión RPM no ha sido comprobada con cada una de las distribuciones, si bien sí ha sido comprobada con las principales como SuSE, Redhat y Mandrake. Si no estamos seguros debemos comprobarlo en la página de Shorewall. Para que Shorewall funcione necesitamos los paquetes de iptables e iproute/ iproute2. Estos paquetes son proporcionados habitualmente por defecto en la mayoría de las distribuciones por lo que no debería ser un problema. La razón por la que necesitamos las iptables es porque Shorewall no es realmente un cortafuegos en sí mismo. Shorewall no es responsable de comprobar, filtrar y gestionar paquetes. Shorewall simplemente coge sus archivos de configuración y usa el comando iptables para cargarlas en el núcleo.
Shorewall
PORTADA
conecta directamente a Internet podríamos añadir un cortafuegos directamente a nuestro equipo. Mi red consiste en un ordenador con tarjeta DSL que se conecta a Internet, una máquina con Windows XP y otra con Linux. Cada una tiene una función específica y permito diferentes conexiones desde y hasta estas máquinas. Tan simple como es la configuración de mi red, solo tengo que cambiar un par de archivos de configuración para usar Shorewall. Debido a que esta es una configuración común y simple, es un buen punto de partida.
Configuración Básica
Figura 1: Una configuración Shorewall para entornos empresariales. Nótese las distintas zonas de seguridad.
Debido a que iptables asume la tarea de manipular tablas dentro del núcleo, Shorewall no se necesita más una vez lo hemos ejecutado. Incluso podemos ver que esta ocurriendo echando un vistazo al propio programa Shorewall. No es necesario rebuscar a través de mucho código. El programa Shorewall (normalmente /sbin/shorewall) es un archivo de comandos. Para que iptables sepa lo que debe hacer debemos indicarle al núcleo las reglas. Las llamadas rulesets se definen dentro de las iptables y están compuestas de una conexión y una serie de “clasificadores”. Esto determina si una conexión en particular se permite y si y como debe ser manipulado o redirigido
el paquete. Este concepto es básicamente común en todo software cortafuegos y puede utilizarse en redes con decenas, incluso cientos de ordenadores, si bien es probable que, con muchos ordenadores hablando entre ellos, prefiramos subdividir nuestra red en pequeños segmentos. Cada segmento también puede ser gestionado por su propio cortafuegos Shorewall. Algo que debemos saber es que no necesitamos dedicar un equipo específicamente como cortafuegos. Si bien esto es una práctica común y generalmente una buena idea, los usuarios domésticos no dispongan del espacio necesario para usar un equipo específico para cada función. Si nuestra estación de trabajo se
El archivo principal de configuración es /etc/shorewall/shorewall.conf. shorewall.conf nos permite configurar todo, desde el comportamiento al arranque hasta el comportamiento al apagarlo. Si bien podemos configurar muchos valores distintos en este archivo aún no he encontrado ninguna razón para cambiar ninguno de ellos en mi sistema. Puede que ya estemos familiarizados con el término “segmento” para denominarporciones específicas de una red. Shorewall usa el término “zona”. En mi configuración tengo cuatro zonas: fw (el propio cortafuegos y mi estación de trabajo), net (Internet) y loc (la red local). Los nombres de las zonas deben ser cortos (5 caracteres o menos) y pueden contener letras o números. Debemos saber que no podemos usar el nombre de zona especial all. Tampoco nos podemos referir a una zona distinta a la del cortafuegos mediante la variable FW del archivo shorewall.conf. Este nombre cambia por defecto a fw. Aunque no proporcionamos ningún servicio a ordenadores fuera de nuestra red local necesitamos la zona Internet. Recordemos que las reglas iptable se definen mediante una conexión específica, o lo que es lo mismo, definida por dos puntos finales. Uno de los puntos puede ser nuestra estación de trabajo, siendo el otro Internet. Por tanto necesitamos definir una zona específicamente como Internet. Debemos saber que estos nombres son solo un acuerdo. Si bien son los que Shorewall usa por defecto para estas zonas, las podemos llamar como queramos mientras que seamos consistentes
www.linuxmagazine.com.es
Número 03
23
PORTADA
Shorewall
Listado 1: Archivo de zones de ejemplo 01 02 03 04 05
#ZONE DISPLAY COMMENT net Net the Internet zone loc Local the local network fw FW the firewall #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
a los largo de los archivos de configuración. Los permisos en el directorio /etc/shorewall está puesto en 700 por defecto, lo que significa que solo el propietario (raíz) tiene acceso. Incluso el permiso de lectura puede ser peligroso puesto que alguien puede ser capaz de ver un agujero en la seguridad y explotarlo. Las zonas están definidas en el archivo /etc/shorewall/zones. Cada entrada tiene tres valores: nombre de la zona (usado para referirse a ésta en los otros archivos), nombre a mostrar (aparece cuando shorewall esta cargando las reglas) y un comentario. El listado 1 nos muestra el archivo zones básico.
Definición de los Caminos de Comunicación Si bien hemos definido las zonas, el cortafuegos aún no sabe como comunicarse con cada zona. Esto es debido a que aún no hay asociación entre los nombres de las zonas y la propia red. Esto se hace usando el archivo /etc/shorewall/interfaces, compuesto de cuatro columnas: zona, interfaz, difusión y opciones. En mi sistema, el archivo interfaces es parecido al que aparece en el listado 2. La zona es simplemente el nombre de la zona cogido del archivo zones. El interfaz es el nombre de la interfaz de la red. Por ejemplo, en mi conexión DSL, que usa el protocolo punto a punto (PPP), el nombre de la interfaz es ppp0. El nombre del interfaz para la tarjeta de red es eth0. Para saber que interfaces tenemos debemos usar el comando /sbin/ifconfig. La columna difusión es la dirección de difusión de la red anexa a esa interfaz. Como habrás podido imaginar, la columna opciones especifica cualquier opción que deseemos usar. En mi sistema aparecen dos entradas como las siguientes:
24
Número 03
net ppp0 routefilter,norfc1918 loc eth0 detect -
Como podemos observar, la zona Internet está conectada a la interfaz ppp0 y la zona local está conectada a la interfaz eth0. Debido a que tengo tres zonas, puede que nos preguntemos por qué no hay ninguna línea para la zona del cortafuegos. Bueno, es sencillo, el cortafuegos se conecta a las otras zonas a través de una de las interfaces ya especificadas. Por tanto quizás sea mejor pensar en el archivo interface como el lugar donde se define que interfaz usa el firewall para hablar con las otras zonas. En el caso de la interfaz ppp0 la columna difusión tiene un guión (-). Debido a que la conexión PPP no tiene difusión, podríamos haberlo dejado en blanco. No obstante, como deseaba especificar algunas opciones adicionales, necesitaba ocupar el espacio de alguna manera. Si no hubiera opciones simplemente podríamos haber dejado los dos espacios en blanco. No obstante, a mí siempre me gusta incluir un guión en vez de dejar el espacio libre con el fin de recordar que “falta algo”. La opción routefilter que hemos especificado le indica al núcleo que debe rechazar cualquier paquete de la interfaz indicado cuya dirección origen haya sido encaminada fuera con un interfaz distinta. En este caso, si el interfaz ppp0 recibe un paquete con una dirección original entrante que normalmente se habría dirigido fuera desde la interfaz eth0, esta sería abandonada. Esto es llamado anti-spoofing.
La segunda opción, norfc1918, indica al núcleo que no debe enrutar direcciones especificadas como “privadas” en RFC 1918. RFC 1918 lista una serie de rangos de direcciones que pueden ser usadas por cualquiera y no deben se enrutadas. Esta opción asegura que no lo serán. Los detalles respecto a RFC 1918 pueden ser encontrados en [3]. Aquí hemos tenido un problema. Queremos que nuestros otros ordenadores sean capaces de acceder a Internet, pero tienen direcciones en el rango marcado por RFC 1918. Entonces, ¿cómo pueden acceder a Internet? Bueno, eso lo veremos en breve. Podemos configurar Shorewall de forma que se comporte de determinadas maneras en base a las zonas ajustando condiciones específicas para cada zona. Los ajustes por defecto para cada zona son iguales (como nos podemos imaginar) y están en el archivo policy. Los campos en este archivo son: cliente (la zona origen), servidor (la zona destino), política (lo que se debe hacer por defecto) y nivel de registro (cuanta información debe ser almacenada). El listado 3 muestra un archivo de política de ejemplo. Observemos las últimas dos líneas. La primera indica que cualquier tráfico que haya sido comprobado y venga desde Internet simplemente debe ser abandonado (ignorado). Tenemos cuatro opciones para la política de conexión: ACCEPT (Aceptar) - Acepta la solicitud de conexión. DROP (Dejar) - Ignora la solicitud de conexión. REJECT (Rechazar) - Devuelve un error determinado al equipo solicitante. CONTINUE (Continuar) - Nos permite tener anfitriones en múltiples zonas y aplicar reglas de ambas zonas. El nivel de registro determina cuanta información se envia al registro del sistema (syslog). Debemos recordar que todo esto se realiza con los iptables que existen en el núcleo. Esto significa que toda la información es enviada por la
Listado 2: Archivo de interfaces de ejemplo 01 02 03 04
#ZONE OPTIONS BROADCAST INTERFACE net ppp0 routefilter,norfc1918 loc eth0 detect #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
www.linuxmagazine.com.es
Shorewall
utilidad de registro del núcleo. Todo lo que nosotros hacemos es especificar la prioridad de los mensajes que a registrar. Debemos repasar la página principal del syslogd para encontrar más detalles al respecto. Las dos últimas líneas de mi archivo de política tienen este aspecto: net all DROP info all all REJECT info
La primera línea indica que cualquier tráfico que no haya comprobado y provenga de Internet debe ser abandonado (ignorado). No obstante, el resto del tráfico debe ser rechazado. Esto puede parecer un poco absurdo al principio, pero tiene sentido cuando consideramos las diferencias entre abandonar y rechazar. Cuando un paquete viene de Internet con destino a una dirección específica o puerto no permitido deseamos ignorarlo. No deseamos que el remitente sepa lo ocurrido. Esto puede darle al usuario alguna pista respecto de cómo evadir la seguridad. Por otro lado, los paquetes provenientes de cualquier otro lugar (mi estación de trabajo o el equipo local) son rechazados, dando indicaciones a la aplicación cliente de lo ocurrido. Estamos configurando el comportamiento por defecto en el archivo de la zona. Esto significa que si no definimos ninguna conexión adicional éste será el comportamiento que aplicará en el archivo de política. En mi archivo de política solo tengo una entrada para la zona de red. Teóricamente, esto significa que todos los paquetes que provengan de Internet deben ser abandonados. No obstante, tengo en mi máquina un servidor Web con mucha información de referencia que deseo acceder desde el trabajo. Debido a que esta conexión es vía Internet, el archivo de reglas no me permitirá acceder a mi servidor. La respuesta a este problema es el archivo reglas. El archivo de reglas es el corazón de la configuración de Shorewall. Aquí definimos una conexión específica en términos de zonas, servicios de red (puertos), segmento de red, equipos individuales y básicamente cualquier combinación en la que podamos pensar. Cuando llegue una
solicitud saliente lo primero que hace el sistema es comprobar la solicitud con las conexiones definidas en el archivo de reglas. Si no se encuentra ninguna usa el valor por defecto del archivo de política. Las columnas del archivos de reglas son: acción a ejecutar, la fuente de la solicitud, el destino, el protocolo usado, el puerto de destino, el puerto origen y el destino original. Adicionalmente a las acciones del archivo zona, tenemos un par de acciones adicionales en el archivo de reglas. DNAT nos permite hacer traducciones de direcciones de destino de red (Destination Network Address Translation). De esta forma las solicitudes pueden ser redireccionadas a equipos distintos e incluso a distintos puertos en esos equipos. La acción REDIRECT (redireccionar) redireccionará las solicitudes a puertos específicos en el mismo equipo. Esto se utiliza normalmente para redireccionar solicitudes HTTP al proxy local (por ejemplo, squid). Para redes más pequeñas que no necesitan proporcionar acceso completo a Internet he averiguado que la acción REDIRECT es extremadamente útil (posiblemente sólo permitiendo acceso HTTP). Hay una entrada que es como sigue: REDIRECT loc 3128 tcp www -U !10.2.38.0/24
En un interfaz de comandos, esta entrada indica que todas la conexiones entrantes usando el protocolo TCP y solicitando servicios www (por ejemplo HTTP) serán redireccionados al puerto 3128. Este es el puerto en el que el servidor proxy Squid está escuchando. Mirando en el destino original especificamos una completa red tipo C usando la anotación CIDR: 10.2.38.0/ 24. Además esta entrada está precedida de una marca de exclamación. Como en otros contextos, la marca de exclamación se utiliza para negar el acceso. Por tanto el significado de la línea entera en inverso. Lo que significa que todas las solicitudes excepto aquellas destinadas a direcciones en la red 10.2.38.0 son redireccionadas a Squid. Esto tiene sentido porque 10.2.38.0 es mi red local y cualquier servidor Web en la red local puede o debe ser accesi-
PORTADA
ble sin necesidad de tener que pasar a través de un proxy. La acción LOG (registro) primero registrará el paquete y luego continuará con la siguiente regla de aplicación. La acción QUEUE (cola) se utiliza para dirigir paquetes a aplicaciones de espacio de usuario, las cuales se manipulan y se devuelven a la pila IP. Una norma a seguir cuando configuremos el archivo rules es poner apagar todo (off>) en principio y luego ir encendiendo cosas según las necesitemos. Muchas personas lo hacen al revés empezando con una red abierta y luego van apagando servicios innecesarios. En el primer caso, si olvidamos algo lo único que ocurre es que no tendremos acceso según esperamos (lo que es un simple inconveniente), pero si esto ocurre en el segundo caso, olvidar apagar algo puede significar estar abierto a un ataque.
Cavando más profundo El archivo /etc/shorewall/hosts nos permite definir anfitriones específicos. Habitualmente no hay razones para añadir nada en el archivo hosts para redes pequeñas. Cuanto más pequeña es la red es más posible que todas la máquinas en una zona están configuradas de la misma forma (o dicho de una forma más correcta, que todas las máquinas de un interfaz concreto tienen la misma configuración). Este puede que no sea el caso y puede que necesitemos diferentes reglas de acceso para distintas máquinas de la misma red. Hace un par de meses mi hijo comenzó a jugar a un juego de rol en Internet. Esto implica que él necesita algo más de un simple acceso HTTP a Internet, por lo que no pude continuar simplemente usando la redirección al proxy Squid como describimos antes. Para proporcionar este acceso he definido un grupo específico de ordenadores como una zona nueva. Primero he creado una nueva entrada en mi archivo de zonas para esta nueva zona, la cual he llamado “juego” (game). Luego he creado una entrada en el archivo hosts que solo contiene el equipo de mi hijo: game eth0:10.2.38.13.
Pero esto no es todo. Recordemos que mi red local es 10.2.38.0/24. Éste es una de
www.linuxmagazine.com.es
Número 03
25
PORTADA
Shorewall
Listado 3: Archivo policy de ejmplo 01 02 03 04 05 06 07 08
#SOURCE DEST POLICY fw net ACCEPT fw loc ACCEPT loc net REJECT loc fw ACCEPT net all DROP all all REJECT # LAST LINE -- ADD YOUR
LOG info info info info
info info ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
las redes “privadas” listadas en RFC 1918. Incluso si yo quisiese dirigirla a través de mi tarjeta DSL, podríamos apostar a que mi ISP no va ha aceptarla. Entonces, ¿qué podemos hacer? La solución es algo llamado “enmascarar IP” (IP masquerading). Como su nombre implica, una dirección IP es “enmascarada” por las otras. En mi caso, la dirección IP en la tarjeta DSL (la cual tiene una dirección de Internet válida) es enmascarada por la dirección IP en la red local. Por tanto necesito creer una entrada en el archivo /etc/shorewall/masq como la siguiente: ppp0 10.2.38.0/24
Esta entrada hace que todo el tráfico saliente de la interfaz ppp0 desde la red clase C 10.2.38.0 debe ser enmascarada. En este punto ya hemos acabado la configuración básica del enmascarador. No obstante, lo siguiente es la parte más complicada. No fue muy sencillo encontrar información acerca de cómo ejecutar este juego a través de cortafuegos. De hecho encontré determinada información al respecto que sugerían deshabilitar el cortafuegos si se desea jugar. Bien, pues al final conseguí que funcionara. Para hacerlo necesité ajustar el nivel de acceso en el archivo policy para depurar y vigilar en el archivo de registros todos los intentos de conexión desde el equipo de mi hijo con cualquier otra máquina para entonces comprobar el DNS para ver si fue una máquina de los desarrolladores del juego. Entonces añadí un puerto específico a mi archivo rules. Si lo hubiese deseado, también podría haber añadido reglas para el servicio WWW (puerto 80). No obstante, debido a que esto es lo único que mi hijo nece-
26
Número 03
LEVEL
sitaba al margen de acceso a la Web, aún continuo usando REDIRECT para el acceso Web.
Resolución de problemas y acceso Es posible (y probable) que tengamos problemas la primera vez que configuremos Shorewall. Por tanto, rastrear las causas de un problema nos será útil. Una técnica útil para depurar problemas es ajustar el nivel de registro en el archivo policy. Ajustarlo para depurar nos proporciona mucha más información. Entrar en mucho detalle respecto a las entradas del registro está más allá del alcance de este artículo, pero es bastante fácil entender de que van incluso sin comprender del todo la terminología. Por ejemplo, veamos estos datos: Nov 1 11:19:32 saturn kernel:U Shorewall:net2all:DROP:IN=ppp0U OUT= MAC= SRC=1.2.3.4 DST=10.2.38.11U LEN=48 TOS=0x00 PREC=0x00U TTL=116 ID=47048 DF PROTO=TCP SPT=1 292 DPT=1080U WINDOW=64240 RES=0x00 SYN URGP=0
Estos son datos estándar de /var/log/messages. Al principio tenemos la fecha, el nombre del equipo y el registro del sistema (kernel en este caso). A continuación encontramos el mensaje propiamente dicha. Fácilmente podemos ver que el paquete entraba en mi tarjeta DSL (ppp0) y que el paquete fue abandonado. También podemos observar que estaba usando la conexión net2all de Internet a todas las otras zonas. Si volvemos a repasar lo comentado respecto al archivo policy veremos que teníamos una entrada que indicaba que el comportamiento por defecto debía ser el abandono de todos los paquetes
www.linuxmagazine.com.es
que vengan de Internet hacia el resto de las interfaces. Había un paquete intentando acceder el puerto 1080 (DPT). No hay nada ejecutándose en ese puerto y desde luego no me he comunicado con nadie que deba usar ese puerto. Puesto que no hay ningún servicio “estándar” asociado a este puerto no hay razón para que nadie intente acceder a el desde Internet, por lo que parece bastante obvio que alguien intentaba aprovecharse de un error de Windows. Si el equipo remoto (o incluso otro equipo en la misma red) continua intentando acceder a distintos puertos de mi equipo puede que desee añadirlo a la “lista negra”. Esto se hace añadiendo la dirección del anfitrión o de red en formato CIDR al archivo /etc/shorewall/blacklist. Eso implica que, al margen de que cualquier otra entrada les permita el acceso, estos equipos tienen el acceso específicamente prohibido. Por defecto, Shorewall usa un sistema de acceso que normalmente envía un mensaje a /var/log/messages. Incluso cuando configuré syslogd para enviar mensajes a otro archivo encontré molesto hacer que el registro de mi cortafuegos no se confundiera con otros mensajes del kernel. Para resolverlo podemos usar el soporte ULOG del kernel. Este debe estar disponible para nuestro kernel, siendo habitual en la mayoría de las distribuciones. No obstante, el paquete ulogd no está siempre disponible, por lo que es posible que lo tengamos que descargar desde [4]. Una vez ulogd esta configurado en nuestro sistema no usaremos más los niveles de acceso del syslogd. En su lugar ■ usaremos el ULOG.
INFO [1] Netfilter Website: http://www.netfilter. org [2] Shorewall Website: http://www. shorewall.net [3] Asignación de Direcciones Privadas de Internet RFC 1918: http://rfc.net/rfc1918. html [4] Ulog: http://www.ulog.ch/english/index. html [5] Squid Proxy: http://www.squid-cache.org/
SDL
DESARROLLO
Diseño de juegos bajo Linux
Todo bajo Control Este mes todo está bajo control. Y Steven Goodwin controla un montón. Veremos cómo el jugador controla el juego y cómo el juego controla los personajes. POR STEVEN GOODWIN
E
l mes pasado vimos cómo SDL proporciona toda la entrada a nuestro juego a través de un bucle de eventos con SDL_PollEvent. Esta función cumplimenta nuestra variable SDL_Event con información útil sobre el evento siguiente. Ahora necesitamos interpretar estos datos.
Mensaje en una botella Lo primero que hay que advertir es que SDL_Event no está implementado como estructura, sino como una unión, porque cada elemento es mutuamente exclusivo, no tiene sentido obtener información sobre el puntero del ratón para un evento que reporta la pulsación de una tecla. Por consiguiente, la lectura de parte de una estructura que no corresponda con el tipo de evento producirá invariablemente datos inutilizables y no el contenido del ultimo mensaje del ratón, por ejemplo. Solamente necesitamos manejar los eventos en los que tenemos interés; todo lo demás será ignorado, SDL no intentará ni supondrá qué hacer con el evento. En nuestro juego la pantalla siempre se actualiza 60 veces por segundo, así que no necesitamos manejar el mensaje de SDL_VIDEOEXPOSE, por ejemplo. Cada estructura del evento contiene una miríada de información que pertenece al evento. Por ejemplo, SDL_MouseButtonEvent indica qué botón de ratón fue pulsado, la posición x e y del puntero del ratón y qué dispositivo del ratón era (para sistemas con dos, o más, ratones). Los nombres asociados a las variables dentro de cada estructura se pueden encontrar en las páginas de
manual, o en SDL_events.h, que generalmente habita en /usr/local/include/SDL. Desde aquí podemos crear manejadores de evento para cada mensaje en el que estemos interesados. Esto se hace creando funciones separadas que manejen una clase particular de evento (como la entrada).
Whisky en la Jarra El control es probablemente la parte más importante de un juego de ordenador. Es la interfaz entre el jugador y el juego. Todos los diseñadores de juegos saben esto y pasarán muchas semanas (incluso meses) retocando el sistema de control hasta que esté “perfecto”. SDL no hace este proceso más fácil, sino que proporciona la suficiente
información sobre el controlador, sea del ratón, el teclado o una palanca de juegos, para permitirnos la suficiente flexibilidad para crear un buen sistema de control. La entrada del teclado es la forma de entrada más empleada en este juego, ¡ya que la mayoría de los PCs tiene tendencia a tenerlo! Pero como cada pulsación del teclado tiene 2 partes, un evento de tecla pulsada y un evento de tecla liberada, es necesario escuchar ambos. Manejar múltiples teclas es muy fácil y la velocidad de auto repetición del teclado no causa problemas adicionales, ya que solo importa si la tecla ha sido pulsada o no. Si aparece auto repetición, una característica importante es que se puede almacenar siempre el tiempo en el
www.linuxmagazine.com.es
Número 03
27
SDL
DESARROLLO
cual la tecla fue presionada utilizando la función SDL_GetTicks. Con la asignación de un puntero SDL_Event (pEevnt), se encuentra la tecla correcta con la linea: SDLKey key = pEvent->keyU .keysym.sym;
Esto puede parecer un poco agotador para una simple pulsación de tecla, pero los otros miembros de estas estructuras también son redundantes (Por ejemplo pEvent ->key.state incluye la misma información como tipo de evento; pulsado o soltado) o intrascendente (el código de exploración específico del teclado). Prefiero pensar que esto es minucioso y no prolijo. El valor sym equivale a una de las muchas definiciones que indican una tecla específica: Por ejemplo SDLK_LEFT para el cursor izquierdo y SDLK_RIGHT para el cursor derecho. Las teclas alfanuméricas mapean muy bien el ASCII, así que comprobar la tecla ‘0’ es tan simple como debe ser: if (key == '0') /* ...se podiaU haber usado SDLK_0 aquí... */
No obstante, recomiendo usar las definiciones de SDL_keysyms.h ya que las letras activan siempre eventos con sus homólogas minúsculas del ASCII (el valor de tecla sería igual a ‘a’ no ‘A’) sin tener en cuenta el bloqueo de mayúsculas o la tecla ‘mayúsculas. if (key == SDLK_a) /* ...Vaya!U Efectivamente son minúsculas... */
Usaremos este conocimiento recién encontrado para almacenar pulsaciones de tecla de una manera parecida a los juegos, mediante la creación de una matriz especial para indicar que teclas
están controlando el personaje. Esto es diferente de que tecla ha sido pulsada porque, cuando dos teclas son pulsadas, queremos la pulsada más recientemente para controlar la dirección. Nuestro código será algo así Figura 1: Nuestro juego hasta ahora. como el Listado 1. Escribir el sistema de control de esta manera hace que sea más fácil cambiar Cuadro 1: Di ‘Patata’ la asignación de teclas o añadir un control de palanca de juegos. Adviértase, sin SDL ha hecho que capturar la pantalla sea un embargo, que el mensaje de ‘tecla liberaasunto muy simple que apenas requiere una da’ se perderá si cambia del juego al función, SDL_SaveBMP. Esta es el espejo exacto de la función SDL_LoadBMP que depurador. SDL no funciona y no está hemos usado en la primera parte y toma el habilitado para escuchar mensajes de puntero de la superficie (que en nuestro tecla liberada (los cuales, ahora van al caso es la superficie de pantalla) y un nomdepurador). Por tanto cuando retorne al bre de fichero. juego tomará un evento adicional de 01 if (ev.type == SDL_KEYDOWN && tecla pulsada y tecla soltada para 02 ev.key.keysym.sym==SDLK_F12) restablecer el sistema ¡Esto es más noto03 { rio si el personaje continúa moviéndose 04 static int curr_grab = 0; a pesar de que no se pulsan teclas! 05 char GrabName[32]; Sin embargo, comprobar todas las 06 sprintf(GrabName, teclas de este modo, puede ser leve07 "DugPic%d.bmp", curr_grab); mente incomodo. La abstracción de las 08 ++curr_grab; teclas de control del juego es una ‘buena 09 SDL_SaveBMP(TheGame.pScreen, cosa’, pero tener que escribir el código 10 GrabName); para aceptar el nombre de los jugadores 11 } para la tabla de puntuaciones máximas cuando el cursor izquierdo ha sido remapeado, digamos, a ‘Z’. en este caso, Cuadro 2: Acerca del solamente queremos preguntarle a SDL tiempo que tecla concreta se ha pulsado. Podemos hacer esto con la función Uint8 *keystate = SDL_U GetKeyState(NULL);
El puntero devuelto es una matriz (que no está permitido modificar) que representa cada tecla en el sistema y está referenciado con las macros SDLK_* que
Tabla 1: Retrollamadas Función
Notas
Start game
Llamada una vez al comienzo del nivel
Reset game
Llamado siempre que el nivel consiga reiniciarse, después de que el jugador muera por ejemplo
Update
Mover o animar al objeto
Draw
Dibujar este objeto en la pantalla
Destroy
Liberar cualquier memoria ocupada al inicio del juego
28
Número 03
www.linuxmagazine.com.es
Este mes hemos hecho una adición a la función de actualización. Es un parámetro para controlar el tiempo. Generalmente, cada llamada a los comportamientos que la función de Update() realizaría un cuadro valido de la actividad. Sin embargo, en casos extremos, el juego podría haber tomado dos cuadros para procesar la ultima imagen. Esto requeriría que la función de Update() se llamara dos veces dentro de un solo cuadro para compensar. Sin embargo, llamar dos veces a Update() no permite que el comportamiento se optimice con eficacia. Así que en vez de eso lo llamamos una vez y le pedimos que actualice N cuadros. Los juegos con una granularidad más fina pasarían un número de coma flotante (indicando los segundos transcurridos) a sus funciones de la actualización.
SDL
veremos más tarde. Cualquier valor distinto de cero en esta matriz significa que la tecla está actualmente pulsada. if ( keystate[SDLK_F12] ) U printf("The F12 key is down.");
Cualquier tecla que se ha mantenido pulsada durante dos cuadros consecutivos será considerada ‘VERDADERO’ para ambos cuadros, porque esta función informa del estado de la tecla y no eventos. Normalmente esto no es un problema, pero si se está usando esta característica para realizar una captura de pantalla, obtendrá una imagen por cada cuadro mientras la tecla este pulsada. Véase el Cuadro 1 “Di ‘Patata’”, para más detalles sobre como realizar una captura de pantalla. También se puede determinar que modificador de teclas están pulsados (como ‘mayúsculas’ o ‘alt’); pero para esto necesita una función diferente. Véase el Listado 2.
Mi Chica Piruleta La entrada de la palanca de juegos es muy fácil de programar bajo SDL, que incluso permite múltiples palancas de juego sin ningún esfuerzo extra. En nuestro ejemplo, se supondrá que hay una palanca de juegos, pero en un juego más completo es deseable dejar al jugador que seleccione que palanca de juegos utilizará y que personaje controlará.
Listado 1: Pulsaciones de teclas 01 void exUpdateInterface(const SDL_Event *pEvent) 02 { 03 if (pEvent->type == SDL_KEYDOWN) 04 { 05 SDLKey key = pEvent>key.keysym.sym; 06 if (key == SDLK_LEFT) 07 { 08 iMovement[EXI_MOVE_LEFT] = TRUE; 09 iMovement[EXI_MOVE_RIGHT] = FALSE; 10 } 11 /* ... etcétera ... */
DESARROLLO
Listado 2: Modificadores de teclas 01 if (SDL_GetModState() & KMOD_SHIFT) printf("Una de las teclas de mayúsculas se ha presionado."); 02 if (SDL_GetModState() & KMOD_LSHIFT) printf("Se ha presionado la tecla de mayúsculas izquierda.");
Al contrario que el control de teclado, SDL no inicializa la palanca de juegos automáticamente cuando se llama a SDL_Init. Hay tres pasos adicionales: Inicializar el subsistema de la palanca de juegos (que no es distinto del subsistema de vídeo o el temporizador), poner en marcha los eventos de la palanca de juegos (si no el bucle de eventos no informará sobre los eventos de la palanca de juegos) y abrir un puerto de palanca de juegos para la lectura. Véase el Listado 3. Si se tienen que manejar varias palancas de juegos, entonces la función SDL_NumJoysticks informará del número de palancas de juegos conectadas al sistema. El parámetro para la función SDL_JoystickOpen, como se puede esperar, indica cual de las palancas de juegos hay que abrir. Una vez que se tiene un puntero SDL_Joystick se pueden consultar las capacidades y los parámetros de la palanca. Esto es importante porque cada palanca de juegos es distinta: Algunos tienen controles tipo HAT (conmutador digital de 8 vías, otros tienen ‘track balls’ y otros tienen más botones de lo que se pueda imaginar. Las palancas de juegos para simulación aérea suelen incluir todos los anteriores. Determinar las capacidades de la palanca de juegos le permitirá saber, por ejemplo, si el jugador tendrá que reasignar los botones de la palanca de juegos al teclado. Nosotros solo necesitamos control a izquierda, derecha y botón de salto, así que cualquier palanca de juegos disponible debe ser
suficientemente buena para Explorer Dug. Refiriendonos de nuevo a la tabla comentada anteriormente hay tres eventos principales en los que estamos interesados: SDL_JOYAXISMOTION, SDL_JOYBUTTONDOWN y SDL_JOYBUTTONUP. Puesto que solamente hay una palanca de mando en nuestro juego, podemos ignorar cualquier elemento de la estructura del evento y suponer que cualquier evento de la palanca de juego debe haber venido de la palanca cero (porque es la única que hemos abierto). Entonces podemos usar pEvent->jaxis.value (que oscila entre -32768 y 32767, indicado totalmente a la izquierda, totalmente a la derecha) para controlar el juego. Véase el Listado 4. La banda muerta es un tema interesante. Todas las palancas de juego se mueven, que yo sepa. Pero las palancas de juego también se mueven cuando nadie las está tocando. Tiemblan ligeramente y por tanto generan eventos de palanca de juegos espúreos en cada cuadro. Puesto que esto es una característica del hardware no podemos evitar que suceda, pero podemos limitar los efecto que esto tiene en nuestro juego. Para hacerlo, crearemos una banda muerta alrededor de la parte central de la palanca. Cualquier movimiento que ocurra en esta área será ignorado y tratado como si la palanca de juegos enviara 0,0. Fuera de la banda muerta, se tratará a la palanca normalmente. Aquí he usado una banda muerta de 8000, que es un número razonable para este tipo de juegos, aunque en un juego
Listado 3: Inicialización de la palanca de juegos 01 02 03 04
SDL_Joystick *pJoyStick; SDL_InitSubSystem(SDL_INIT_JOYSTICK); SDL_JoystickEventState(SDL_ENABLE); pJoyStick = SDL_JoystickOpen(0);
www.linuxmagazine.com.es
Número 03
29
DESARROLLO
SDL
profesional, este valor debe ser configurable.
Jumpin’ Jack Flash Como los dispositivos del teclado y el ratón, las palancas de juegos también se pueden leer sin el bucle de eventos. Para hacerlo hace falta llamar a la función SDL_JoystickUpdate que lee el hardware, antes de usar una de las funciones del listado 5 para consultar los datos. Ahora hemos recuperado la entrada, deseamos controlar algo en el juego y por eso, necesitamos algún objeto del juego …
Gente corriente cada objeto del juego, ya sea el jugador, un enemigo, o una puerta de salida, tiene un número de elementos comunes. Todos tienen una posición de comienzo, todos tienen gráficos y todos “hacen cosas”. Sin embargo, cada objeto en el juego tendrá una posición de comienzo distinta, gráficos distintos, y todos hacen “cosas” distintas. Para implementar un buen armazón debemos poder identi-
Listado 4: Movimiento de la palanca de juegos 01 if (pEvent->type == SDL_JOYAXISMOTION) 02 { 03 if (pEvent->jaxis.axis == 0) /* X-axis; assume 04 stick 0 */ 05 { 06 int DeadBand = 8000; 07 TheGame.iface.iMove[EXI_MOVE_L EFT] = FALSE; 08 TheGame.iface.iMove[EXI_MOVE_R IGHT] = FALSE; 09 if (pEvent->jaxis.value < -DeadBand) 10 TheGame.iface.iMove[EXI_MOVE_L EFT] = TRUE; 11 else if (pEvent->jaxis.value > DeadBand) 12 TheGame.iface.iMove[EXI_MOVE_R IGHT] = TRUE; 13 } 14 }
30
Número 03
Listado 5: Consultado la palanca de juegos 01 02 03 04 05 06
SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis); SDL_JoystickGetHat(SDL_Joystick *joystick, int hat); SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy); SDL_JoystickGetButton(SDL_Joystick *joystick, int button);
ficar esos elementos y aislarlos con eficacia del motor común del juego. Datos comunes para todos los objetos: • Posición de comienzo • Una superficie conteniendo gráficos Código único para cada tipo de objeto: • Como inicializar el objeto • Como actualizarlo, p. e. dirección y velocidad de la trayectoria. • Como dibujar el objeto • Como destruir el objeto Necesitamos estas distinciones porque, por ejemplo, aunque podemos describir cada objeto en términos de una superficie, cada objeto en el juego no utilizará esta superficie de la misma manera. Algunos objetos consistirán en un ladrillo (los enemigos), algunos usarán varios (la puerta de salida) y otros se desvanecerán en algún momento (el jugador). Realmente esta lista no está completa y no dudaremos en introducir nuevas características durante el desarrollo del juego, pero es un buen punto de partida. El método que he elegido para implementar estas características utiliza retro-llamadas (callback) individuales a las funciones, donde cada una tiene un propósito específico. Sin embargo, la implementación exacta de cómo trabaja esa función se controla por el código que es específico para cada tipo de objeto. Cada uno de esos tipos se denomina comportamiento. Y cada función de retro-llamada manejará como se comporta ese objeto en una situación en particular. Nuestro juego inicial de retro-llamadas se muestran en la Tabla 1. Esta lista imita nuestro bucle de juego general realmente bien: Comenzamos el juego, procesamos un bucle de actualización del dibujo y entonces salimos. No tenemos ninguna distinción entre el nivel y el juego, puesto que cada nivel es un mini-juego en sí mismo. La
www.linuxmagazine.com.es
lista también demuestra que tenemos una jerarquía de dos niveles de datos: configuración y estado. Los datos de la configuración se crean en el comienzo del juego e incluyen cosas como la superficie SDL o su posición de comienzo. Por el contrario, los datos del estado incluyen las cosas que cambian durante el juego, como la posición o la dirección actual. Esto perfila la información que necesitamos para nuestra estructura EX_OBJECT. Cada objeto del juego utilizará esta estructura genérica, almacenada como parte de una lista enlazada, con las funciones de retro-llamada púdicamente ocultas dentro de otra estructura (EX_OBJ_VTABLE), como se ve en el Listado 6. Aquí hemos creado la configuración más usada y las variables de estado dentro de la estructura EX_OBJECT y marcado las otras con punteros nulos. Será responsabilidad de cada comportamiento asignar la memoria para estos
Listado 6: EX_OBJECT 01 typedef struct sOBJECT { 02 /* Setup - los datos no cambian */ 03 int init_x, init_y; /* Posición de inicio */ 04 SDL_Surface *pGfx; /* apunta a una superficie existente */ 05 void *pBhvSetupData; 06 /* Estado - consigue el reinicio */ 07 int x, y; /* Posición actual */ 08 void *pBhvStateData; 09 /* Admin */ 10 EX_OBJ_VTABLE VTable; 11 /* Lista de componentes enlazados */ 12 struct sOBJECT *pNext; 13 } EX_OBJECT;
SDL
Listado 7: Enemigo caminando 01 typedef struct sDHE_STATE { 02 int iDirection; /* La dirección en que camina, -1 para izquierda, +1 para derecha */ 03 int iAnimFrame; /* Marco actual de la animación, mapeado directamente a una región */ 04 int iAnimDir; /* La animación ping-pong entre cuadros 0->1->2->3->2->1->0. será -1 or +1, dependiendo de la dirección */ 05 } EX_DHE_STATE;
punteros y crear estructuras que el propio comportamiento pueda comprender. Tomando el ejemplo de un enemigo que camina a ciegas de izquierda a derecha (véase el listado 7). Este estúpido enemigo horizontal (EEH) inicializará su estado en cada reset de los datos de configuración que hemos definido como tal como se ve en el listado 8. Como lenguaje, C no facilita ningún mecanismo para parar su cambio de información de configuración durante el ciclo de actualización (donde solamente debería ser cambiado el estado), ni le previene de datos del estado que cambian durante el ciclo de la creación
Listado 8: Enemigo horizontal mudo 01 typedef struct sDHE_SETUP { 02 int x1,y1,x2,y2; /* grados para el enemigo */ 03 int iInitialDir; /* -1 para izquierda, +1 para derecha */ 04 int iSpeed; 05 } EX_DHE_SETUP;
(donde no debería cambia nada). Por lo tanto tenemos que confiar en el sentido común y en los programadores competentes. Pero hay una característica del lenguaje que podemos utilizar para centrar el desarrollo. La Tabla La palabra VTable es la abreviatura de ‘virtual table’ y se ha cogido prestado de C++. Es una manera de llamar a funciones específicas en objetos específicos, sin tener que especificarlos en tiempo de compilación. Esto permite un cierto nivel de abstracción. Cada objeto hace esto estableciendo los punteros a las funciones privadas como en el listado 9. Declaramos cada una de las funciones (dheStart, dheUpdate y dheDraw) como estáticas para hacer sus nombres invisibles a cualquiera fuera del fichero actual. Esto asegurara que solo podemos llamar a estas funciones referenciando a VTable, de este modo: pObject->VTable.Start(pObject);
Para prevenir referencias a NULL o a otros punteros de función inválidos, prepararemos un conjunto de retro-lla-
Listado 9: Ajustando punteros 01 02 03 04 05 06 07 08 09 10 11
BOOL Bhv_CreateDumbHorizontal(EX_OBJECT *pObj) { /* ... otras initializaciones de cosas ... */ pObject->VTable.Start = dheStart; pObject->VTable.Update = dheUpdate; pObject->VTable.Draw = dheDraw; /* ... */ } static void dheStart(EX_OBJECT *pObj) { /* ... hace cosas ... */ } static void dheUpdate(EX_OBJECT *pObj) { /* ... hace cosas ... */ } static void dheDraw(EX_OBJECT *pObj) { /* ... hace cosas ... */ }
DESARROLLO
madas predeterminadas bajo demanda. Cada objeto podrá entonces reemplazar (o sobrecargar) esos punteros de funciones con los suyos propios. Este método puede parecer redundante, ya que requiere 2 instancias de pObject, pero normalmente es más eficiente que añadir conmutadores de estado en torno a cada llamada a Start, Update o Draw. Esto también escala bien si añadimos nuevas funcionalidades a los objetos a través de su VTable. Siempre podremos usar una pequeña función de envoltorio para prevenir el error casual cuando una VTable de un objeto se esta usando, pero se pasa el puntero de otra. void exDrawObject(EX_OBJECT U *pObj) { pObj->VTable.U Draw(pObj); }
Tu me llevas ¡Pero porque cada EEH utiliza el mismo código, no significa que utiliza los mismos datos! Tenemos ya una estructura para la información de la configuración, así que si tenemos una manera de cambiar estos datos iniciales entonces podemos introducir mucha variedad en nuestro juego, basándolo en los datos. Bien, eso se hace antes los que se dice, ya que podemos ampliar nuestra susodicha función Bhv_CreateDumbHorizontal para incluir un juego de parámetros, tales como velocidad y dirección. A fin de hacer estos parámetro generales para todos los comportamientos, los crearemos como cadenas de caracteres y dejaremos que el comportamiento los analice en busca de algo significativo. De esta manera podríamos también leerlos directamente de un archivo de texto para hacer los niveles de juego personalizables de una forma muy simple. Todas los objetos basados en comportamiento trabajan usando exactamente los mismos métodos; aunque algunos requerirán más código que otros. El jugador, por ejemplo, requerirá manejar colisiones con el mundo, manejar las recolecciones y el contacto con los enemigos. Programaremos un manejador el ■ próximo mes.
www.linuxmagazine.com.es
Número 03
31
DESARROLLO
Ruby
Aplicaciones Web con Ruby y Rails
Bien Encaminados.
La mayoría de las bibliotecas web hacen que el 90 por ciento del trabajo sea fácil y el resto imposible. Rails, un infraestructura de código abierto programado en Ruby, es lo bastante flexible como para tener éxito con ese 10 por ciento restante. POR ARMIN RÖHRL Y STEFAN SCHMIEDL
E
l desarrollo web a menudo está caracterizado por los hackeos rápidos y sucios con una pintoresca mezcla de código y HTML. Sin embargo, hay en camino un esfuerzo para llevar una estructura más formal a la programación web. Por ejemplo, Rails [1] usa Ruby para implementar una clásica infraestructura Model View Controller
32
Número 03
(MVC), algo que en el mundo de smalltalk se ha usado algunas veces. La infraestructura MVC abstrae el procesamiento de datos del modelo de manejo de código (controlador) basada en GUI y de la representación del código (la vista), véase la Figura 1. Esta técnica de abstraer los datos de los métodos del procesamiento de datos
www.linuxmagazine.com.es
puede aplicarse a cualquier cosa, desde una tabla de una base de datos a un modelo de flujo de trabajo para una empresa de gran tamaño. El modelo es parcial o completamente visualizado en la vista. Los controladores reaccionan a la entrada del usuario (entre otras cosas) para comenzar los cambios de estado dentro del modelo.
Ruby
Esta estructura hace a la lógica de la aplicación independiente de la representación externa y de la interfaz del usuario. Algunos productos de desarrollo afirman ofrecer MVC, aunque esta afirmación resulta ser un poco pretenciosa cuando se analiza de cerca.
Software en Aplicaciones Prácticas Para mantener el modelo, Rails incluye el Registro Activo (Active Record) que proporciona el mapeado relacional del objeto. El modelo Paquete de Acción (Action Pack) subdivide la petición web en controladores y componentes específicos de la vista. Este diseño hace que
Rails sea realmente útil para el desarrollo de aplicaciones de bases de datos basadas en web, como el software de gestión de proyectos Basecamp [2], que ha sido programado usando Rails (véase el cuadro “entrevista con el desarrollador de Rails”). Cuando se trabaja con Rails, se nota que el diseño del sistema viene de un entorno práctico. Rails evita muchos de los fallos presentes en la mayoría de las estructuras teóricas de trabajo. Rails está basado en el concepto DRY (Dont Repeat Yourself: No se repita; en otras palabras, “una vez y solamente una vez.”) Repetir código dentro de un programa suena a programa mal dise-
Tabla 1: Java y Ruby Aplicación
Java
Ruby
GUI Aplicación
Swing
TK,QT,Fox
GUI Web
JSP,XSLT,XMLC…
Iowa,Rails
Domino de objetos permanentes y gestión de transacciones mente Kansas
Entity EJBs,JDO,generados manual-
Mecanismo RPC (Llamadas a Procedimientos remotos) Para la comunicación entre front-end y back-end & Session EJBs,Servlets Drb Infraestructura para comunicación asíncrona
DAOs
DESARROLLO
ñado. Rails tiende a utilizar la reflexión y módulos en tiempo de ejecución para sustituir los ficheros de configuración; esto elimina la necesidad del típico maratón de configuración al estilo XML. También tiene el efecto de aplicar los cambios inmediatamente sin tener que pasar por un proceso de generación que consuma mucho tiempo. Rails también ha integrado la funcionalidad de comprobación general y unitarias. RubyDoc proporciona la documentación. El gran avance es que los tres componentes de la estructuras de trabajo MVC fueron escritas en Ruby. Si los desarrolladores se adhieren a las convenciones de Rails (mapeado entre base de datos y estructura de objetos), la estructura ayudará a lanzar un proyecto rápidamente. Las funciones para añadir, modificar y borrar objetos están disponibles con unas pocas pulsaciones de teclado.
Popularización de la Base de Datos de Objetos Nuestro ejemplo de aplicación está basada en el tutorial de la página web de Ruby. Crearemos una simple aplicación
EJBs manejado por mensaje DRb/Rinda/Tupleserver
Cuadro 1: Instalación Para los usuarios de Mac OS X (versión 10.3 o posterior), dos vídeos [5] muestran el proceso de instalación. Desde luego que también hay cosas interesantes para los usuarios de Linux. Rubygems [6] (versión 0.7 o posterior) una herramienta de gestión de paquetes para Ruby, facilita una aproximación sencilla a la instalación: gem install rails Cada vez que una nueva versión de Action Pack o Active Record se publica, puede actualizarse simplemente tecleando gem update. Asegúrese de que la conexión de la base de datos al back-end está disponible; puede usar tanto MySQL como PostgreSQL. Los usuarios de Debian necesitaran cumplir algunos requisitos para la instalación, ya que los componentes necesarios están dispersos a lo largo de un gran número de paquetes (véase también [7]): irb1.8,libbigdecimal-ruby1.8, libdbm-ruby1.8, libdl-ruby1.8, libdrbruby1.8, liberb-ruby1.8, libgdbm-ruby1.8, libiconv-ruby1.8, libopensslruby1.8, libpty-ruby1.8, libracc-runtime-ruby1.8, libreadlineruby1.8, librexml-ruby1.8, libruby1.8,libruby1.8-dbg, libsdbm-ruby1.8, libsoap-ruby1.8, libstrscanruby1.8, libsyslog-ruby1.8, libtest-unitruby1.8, libwebrick-ruby1.8, libxmlrpc-ruby1.8, libyaml-ruby1.8, libzlibruby1.8, rdoc1.,ri1.8 ruby1.8,ruby1.8-dev, ruby1.8-elisp, y por ultimo, ruby1.8-examples. Configuración de Apache Si aun no lo ha hecho, necesitará habilitar el modulo rewrite de Apache:
# a2enmod Which module would you like to enable? Your choices are: ... rewrite ... Module name? rewrite Module rewrite installed; run /etc/init.d/apache2 force-reload to enable. Para ejecutar aplicaciones en /var/www/myapp necesitará añadir una entrada al host virtual en su fichero de configuración de Apache. La entrada puede ser algo como esto: 01 01 <VirtualHost *:80> 02 ServerName rails 03 DocumentRoot /var/www/railsdemo/public 04 ErrorLog /var/www/railsdemo/log/apache.log 05 <Directory/var/www/railsdemo/public/> 06 Options ExecCGI FollowSymLinks 07 AllowOverride all 08 Order allow,deny 09 Allow from all 10 </Directory> 11 </VirtualHost> Compruebe el archivo htaccess para la aplicación web para más ajustes; en nuestro ejemplo, éste está en /var/www/railsdemo/public/.htaccess. Ahora trabajando como root, recargue su configuración de Apache como sigue, para aplicar los cambios: /etc/init.d/apache2 force-reload
www.linuxmagazine.com.es
Número 03
33
DESARROLLO
Ruby
web en la carpeta /var/www/railsdemo. Rails comenzará por crear una estructura conteniendo los archivos necesarios: rails /var/www/railsdemo
Esta orden sobreescribirá la aplicación Rails que exista en el directorio especificado, así que procedamos con cuidado. Necesitamos una base de datos MySQL para la tabla de ejemplo; véase el listado 1. El archivo Yaml config/database.yml define el acceso a la base de datos; el archivo serializa los datos en un lenguaje independiente del formato: production: adapter: mysql database: rails_production host: localhost username: root password:
El acceso a la base de datos de prueba será parecida a ésta. En la vida real, no
Listado 1: SQL para Person 01 CREATE DATABASE rails_production; 02 USE rails_production; 03 04 CREATE TABLE people ( 05 id int(10) unsigned NOT NULL auto_increment, 06 name varchar(50) NOT NULL default '', 07 street1 varchar(70) NOT NULL default '', 08 street2 varchar(70) NOT NULL default '', 09 city varchar(70) NOT NULL default '', 10 state char(2) NOT NULL default '', 11 zip varchar(10) NOT NULL default '', 12 PRIMARY KEY (id), 13 KEY name (name) 14 ) TYPE=MyISAM AUTO_INCREMENT=2; 15 16 INSERT INTO people VALUES (1, 'Superman', 17 '123 Somewhere', '', 'Smallville', 'KS', '123456')
34
Número 03
Figura 2: El portal de planificación para empresas Basecamp (http://www.basecamphq.com) utiliza Ruby Rails como aplicación web de fondo.
querrá ejecutar esto con privilegios de root que están sin contraseña. El guión new_controller crea un nuevo controlador; su nombre debe aparecer con letras mayúsculas. La vista sigue el nombre del controlador: ./script/new_controller ßß Friends list display new edit Evite usar process como nombre de vista, ya que Rails usa este nombre internamente. El proceso para crear un nuevo modelo es similar: ./script/new_model U Person
Normalmente Rails descubre automáticamente la tabla subyacente de la base de datos. Si fuera necesario el guión aceptara un nombre de tabla, después del nombre de modelo: @LI./script/new_model ßß Person people Para comprobar la configuración de una aplicación Rails, los desarrolladores pueden ejecutar rake (el make de Ruby) en el directorio de la aplicación. Podrán ocurrir toda una serie de cuestiones en función de la configuración de su sistema: • Si mysql.sock no está en la ubicación habitual, podrá editar cualquier mysql.rb (en un directorio tal como usr/lib/ruby/gems/1.8/gems/act
www.linuxmagazine.com.es
ive-record-0.9.5/lib/active_recor d/vendor ) o configurar la variable de entorno MYSQL_UNIX_PORT. • Los permisos para la base de datos no están bien configurados. • El guión espera que /usr/local/bin/ruby sea la ruta a Ruby. Si Ruby está ubicado en otro sitio, puede crear un enlace simbólico o cambiar el nombre de ruta en el archivo del guión. Para completar la aplicación web, ahora necesitaremos proporcionar algo de contenido para app/views/friends/display.rhtml: 01 <html> 02 <body> 03 <h1>Amigos</h1> 04 <p>Muestra un entrada de alguien</p> 05 <p> 06 <%= @person.name %><br /> 07 <%= @person.street1 %><br /> 08 <%= @person.street2 %><br /> 09 <%= @person.city %><br /> 10 <%= @person.state %><br /> 11 <%= @person.zip %><br /> 12 </p> 13 </body> 14 </html>
Ruby
Listado 2: SQL para Números de teléfonos 01 01 USE rails_production; 02 CREATE TABLE phones ( 03 id int(10) unsigned NOT NULL auto_increment, 04 person_id int(10) unsigned NOT NULL default '0', 05 phone varchar(15) NOT NULL default '', 06 PRIMARY KEY (id),
Esto es parecido a Erb, la variante de HTML incrustado de Ruby. La página HTML muestra los datos que el modelo proporciona. El control tiene que definir y crear el objeto referenciado @person aquí. Esto o c u r r e e n el archivo app/controllers/friends_controller.rb, que
07 KEY people_id (person_id), 08 KEY phone (phone) 09 ) TYPE=MyISAM AUTO_INCREMENT=3; 10 11 INSERT INTO phones VALUES (1, 1, '1234567890'); 12 INSERT INTO phones VALUES (2, 1, '1122334455');
contiene los métodos de acceso. La orden require añade el modelo. require 'person'
Ahora la aplicación web puede usar la clase Active Record para acceder a la base de datos. Si ahora insertamos el
DESARROLLO
siguiente código para el método display, cogerá la primera entrada de la tabla y lo escribirá en la variable de la instancia @person para la vista de clase. def display @person = Person.find(1) end
La definición del modelo de clase en app/models/person.rb también es digno de examinar. require 'active_record' class Person < U ActiveRecord::Base end
La clase de base ActiveRecord::Base hace la mayoría del trabajo, ya que define métodos simples de acceso a la base de
Cuadro 2: Una entrevista con el desarrollador de Rails, David Heinemeier Hansson <LM>:¿Por qué desarrolló Rails? <DH>:Yo había estado programando en PHP durante unos años mientras vigilaba de cerca todos los proyectos de desarrollo web basados en Java. Yo amaba PHP por su inmediatez y estaba muy inspirado por los infraestructura en Java. Así que no quería rendirme rápidamente y y abandonar PHP, pero ni uno ni otro eran lo que yo buscaba para lidiar con las dificultades de grandes sistemas orientados a objeto. En el momento álgido de mi enojo con PHP y no mucho después de mi desilusionante encuentro con Java (trabajé en con J2EE durante 6 ó 7 meses), leí sobre como Martin Fowler y los Programadores Pragmáticos trabajando sobre un lenguaje que encajaba a la perfección con mis exigencias. Por supuesto que ese lenguaje era Ruby, y una vez que supere los primeros escollos, fue amor a primera vista. Poner todas mis inspiraciones de Java en una infraestructura impulsada por Ruby resultó ser un camino muy natural para mi. Tenía que hacerlo de todos modos, con el propósito de construir Basecamp tan rápido como lo hice (en dos meses). <LM>:¿Cuál es la mayor fortaleza de Rails? <DH>:Sobre todo la inmediatez. Puedes crear aplicaciones increíblemente rápido sin que por ello acabes con código enmarañado. Se construye una aplicación rápidam, pero te sirve para toda la vida. Totalmente enfocado a patrones probados,
tales como pruebas y desarrollo dirigidos a dominios, junto con una división MVC que de verdad ayuda en este caso.
hay un plan gratuito por el tiempo de duración de un solo proyecto.
<LM>:¿Cuál es la mayor debilidad de Rails?
<DH>:Estamos mejorando la aplicación constantemente. Justamente la semana pasada lanzamos un montón de nuevas características para gestionar mejor las responsabilidades de un proyecto. Además, pienso que acabamos de hacernos con un porcentaje minúsculo de un mercado enorme. La gestión de proyecto está por todas partes. Además de las obvias aplicaciones en los negocios, estamos viendo que la gente usa Basecamp para planificar cualquier cosa, desde bricolaje casero hasta bodas. Basecamp se ajusta muy bien a un amplio rango de proyectos debido a su sencillez. Gestionar un proyecto no es un proyecto en sí mismo.
<DH>:Puede ser difícil de convencer a los potenciales clientes (o sus gerentes) que ellos podrían ser productivos en un lenguaje relativamente desconocido cuando todos ellos han leído sobre Java y C#. <LM>:¿Cuál es el futuro de Rails? <DH>:Espero publicar la versión 1.0 en el año 2004. Pienso que el 2005 será El Año de Ruby y espero que la publicación de Rails ayude a conseguirlo. Pero por otra parte, tengo unas metas bastante humildes para el ulterior desarrollo de la infraestructura. Rails tiene en este momento alrededor de 2.500 líneas de código. Me gustaría que no creciera mucho más allá de eso. <LM>: Por favor díganos 2 párrafos sobre Basecamp. Quizá debería mencionar también el modelo de negocio. <DH>:Basecamp es una aplicación de gestión de proyectos basado en web, construida en torno a weblogs, hitos y listas de quehaceres (TODO en inglés). Es una aplicación engañosamente sencilla que ha tenido un impacto enorme en todas las personas que gestionan proyectos. Es una aplicación alojada en un servidor externo y las empresas pagan entre 19 y 59 dolares al mes por usarla. Para el que sólo desea probarla, incluso
<LM>:¿Cuál es el futuro de Basecamp?
<LM>:¿Hacia donde piensa que va la programación basada en web? <DM>:Espero que no hacia la intensa complejidad que J2EE, .NET y otros entornos torpes que de alguna manera han convencido a la gente que los necesitan. Los lenguajes dinámicos como Ruby y las estructuras de trabajo construidas con él, como Rails, los van a barrer de la escena en los próximos años. Clientes y desarrolladores comenzarán a darse cuenta de que la mayoría de los aplicaciones web no necesitan la potencia de fuego de un destructor Imperial, sino más bien la flexibilidad de un Caza rebelde (Sííí, acabo de ver Star Wars en DVD).
www.linuxmagazine.com.es
Número 03
35
Ruby
La llamada has_many :phones especifica un vinculo 1:n. En otras palabras, una persona puede tener más de un número de teléfono. Necesitaremos añadir las siguientes líneas a display.html para cambiar el formato de visualización.
Figura 1: Esquema Model View Controller (MVC). El flujo de datos no es
<% for phone in U @person.phones %> <%= phone.phone %><br/> <% end %>
idéntico para todas las aplicaciones y podría diferir del flujo de datos mostrado aquí.
datos. El nombre de la tabla es el plural del nombre de la clase. Curiosamente, la forma plural es gramaticalmente correcta para los nombres irregulares, por ejemplo, men para man o people para person. Véase la documentación de la clase para más detalles sobre las reglas sobre los nombres y las convenciones [8]. El resultado de este trabajo ahora es visible bajo http://localhost/rails/friends/ display. Esta URL apunta al controlador (friends) y a la acción (display).
Tablas Asociadas Rails también tiene una solución para la asociación de tablas. Usaremos dos tablas con números de teléfono (véase el listado 2). Rails utiliza un sufijo (_id) para identificar claves externas, por ejemplo person_id. Como se menciono anteriormente el nombre de la tabla es la forma plural del nombre del modelo: ./script/new_model Phone
El archivo generado anteriormente, person.rb necesita dos modificaciones: require 'active_record' require 'phone' class Person < U ActiveRecord::Base has_many :phones end
36
Número 03
Si un modelo ya existe, en Rails es bastante fácil usar técnicas de estructuración para definir visualizaciones y métodos de manipulación para los datos. Los desarrolladores Web pueden ajustar los métodos básicos tanto como lo necesiten.
scaffold :phone, :suffixU => true
Esto nos da las siguientes URLs: http://rails/friends/list_person http:// rails/friends/list_phone Como puede ver, hemos creado una estructura para una aplicación Web con un esfuerzo mínimo. La aplicación almacenará y manipulará objetos en una base de datos relacional. Ruby implementa el modelo MVC elegantemente e incluso genera el código básico asociado con la estructura de MVC.
Logout Rails facilita el desarrollo de aplicaciones básicas si se siguen las reglas. El sistema proporciona una introducción sumamente útil a la programación de aplicaciones web. Si necesita más ayuda para empezar con Ruby, revise el Manual ■ de Ruby.
RECURSOS [1] Ruby on Rails: http://www.rubyonrails.org [2] Basecamp: http://www.basecamphq.com
Estructuración Automática
[3] Apache Struts: http://struts.apache.org
El siguiente ejemplo supone un directorio de aplicación Rails vacío. Primero crearemos un controlador y un modelo (./script/new _controller Friend y ./script_new _model Person, véase más arriba). Nos aseguraremos de que no tenemos una acción llamada list. Rails utilizará la base de datos existente. Simplemente necesitamos modificar el controlador friends:
[4] Struts Action Invocation Framework (SAIF):http://struts.sourceforge.net/saif/
scaffold :person
Este añadido crea nuevos métodos con la conducta predefinida, como se especifica en la documentación en [9]: list, show, destroy, new, create, edit y update. Esto facilita la estructuración con Person, pero aún necesitamos los números de teléfono. Si se establecen los indicadores correctos, Rails añade una referencia a la acción al nombre del modelo para evitar colisiones de nombres con las acciones de nombres definidas: scaffold :person, :suffixU => true
www.linuxmagazine.com.es
[5] Videos del tutorial: http://www. rubyonrails.org/show/HomePage [6] Rubygems:http://rubygems.rubyforge. org/wiki/wiki.pl [7] Rails para Debian: http://www. rubyonrails.org/show/RailsOnDebian [8] Rules para nombres plurales: http://api. rubyonrails.org/classes/ActiveRecord/Base. html [9] Metodos de estructuración: http://api. rubyonrails.org/classes/ActionController/ Scaffolding/ ClassMethods.html [10]El weblog del autor de Rails: http:// loudthinking.com
LOS AUTORES
DESARROLLO
Armin Röhrl y Stefan Schmiedl dirigen una compañía llamada Agile Softwareschmiede Approximity GmbH. Usan Ruby desde hace cinco años y todavía se divierten trabajando con Ruby y otras soluciones de desarrollo y administración de proyectos hiperproductivos. Para los autores es más importante la productividad que estar a la última.
Curses
DESARROLLO
Menús con Curses
Menú del Día El tema de los menús con curses es complejo. La información que se puede consultar por ahí, es contradictoria. Una función puede aparecer como menu_post(), display_menu() o, incluso, menu_display() en según que versión del manual mires, cuando en realidad se llama post_menu(). Los ejemplos que se encuentran por Internet no están documentados y muchos de ellos no compilan. POR PAUL C. BROWN
¿
Qué hacer? Acudir a la sección de interfaces del tío Paul, por supuesto. De hecho, para empezar a comprender como funcionan los menús, ni siquiera vamos a verlos con una envoltura C++, sino que vamos a estudiar unos sencillos programas en C pelado y mondado para evitar líos y confusiones. Con tal motivo presento la prueba A: el listado 1, que contiene un programa, y sin que sirva de precedente, completo, compilable (se puede utilizar g++ o gcc, monta tanto, tanto monta) y ejecutable que presentará en pantalla nuestro primer menú (ver Figura 1)… Sí, ya sé que no es muy
impresionante, pero paciencia. Analicemos lo que hace el código y podremos mejorarlo.
Primer menú Lo primero es declarar una matriz de cadenas (options) que contiene las opciones que vamos a mostrar en nuestro menú. Atención, que si bien se mostrarán cuatro elementos en el menú, hay que definir 5 porque curses exige que el menú termine en una cadena nula, que es exactamente lo que es el elemento (char*) NULL al final de la matriz. A continuación, nos metemos directamente en la función main del programa y inicializamos la ventana estándar de
curses (esto a estas alturas no debería entrañar ningún misterio). De la línea 18 a la 21, declaramos variables que nos servirán en la creación del menú. Tenemos, por un lado, un puntero a una variable MENU, que es la que apunta al menú propiamente dicho. A continuación tenemos un puntero a las cadenas options, un entero i que servirá de iterador en un bucle y, finalmente, una matriz de punteros ITEM (barra) cada elemento del cual contendrá las opciones disponibles en el menú. El siguiente paso consiste en asignar espacio de memoria a barra. Esto lo hacemos con la función C calloc() y le asignamos tanto espacio como elemen-
www.linuxmagazine.com.es
Número 03
37
DESARROLLO
Curses
Listado 1: menu.c - nuestro primer menú 01 02 03 04 05 06
#include <stdlib.h> #include <menu.h>
26
char* opciones[5] = { "Fichero", "Editar", "Ventana", "Ayuda",(char*) NULL 07 }; 08 09 int main(int argc, char *argv[]) 10 { 11 (void) initscr(); 12 keypad(stdscr, TRUE); 13 (void) nonl(); 14 (void) cbreak(); 15 (void) noecho(); 16 wclear(stdscr); 17 18 MENU * menu_principal; 19 char ** o=opciones; 20 int i; 21 ITEM ** barra; 22 23 barra=(ITEM**)calloc(5,sizeof( ITEM*)); 24 25 for(i=0;i<5;i++)
tos del menú disponemos (en este caso, 5). A continuación, en la línea 26, tenemos un bucle que asigna los elementos del menú a barra y, después, creamos el menú propiamente dicho pasando barra como parámetro a la función new_menu() de curses. Y, por fin, podremos ver nuestro menú. Lo mandamos a la ventana con post_menu(). Como no se especifica ninguna otra ventana, el menú aparecerá en la ventana estándar por defecto, stdscr. Para que se pueda visualizar el menú, habremos de refrescar la pantalla, cosa que hacemos con refresh(). El resto del listado debería ser obvio: se espera un entrada del teclado, si el usuario pulsa la tecla [Inicio], el bucle termina, se retira el menú, se liberan los elementos, se cierra curses y se acaba el programa. ¿Alguien está viendo maneras de envolver todas estas feas tareas domésticas en una hermética clase C++? Por que yo sí.
38
Número 03
barra[i]=new_item(opciones[i], ""); 27 28 menu_principal=new_menu((ITEM* *)barra); 29 post_menu(menu_principal); 30 refresh(); 31 32 int ch; 33 34 while ((ch=getch())!=KEY_HOME) 35 { 36 /* procesar entrada del teclado */ 37 } 38 39 unpost_menu(menu_principal); 40 refresh(); 41 free_menu(menu_principal); 42 43 while(*barra) 44 free_item(*barra++); 45 46 endwin(); 47 exit(0); 48 }
El ejemplo anterior es un poco aburridillo ¿verdad? Pero si de verdad queréis probarlo, para compilar el listado 1, bastará con ejecutar… gcc -o menu menu.c -lcursesU -lmenu
… en el directorio donde tengamos el código fuente. O, si preferís… g++ -o menu menu.c -lcursesU -lmenu
… que lo compilará igual. El aspecto de nuestro menú no es exactamente como lo queremos. Esto es porque no hemos definido la geometría del menú y la librería menu aplica la geometría por defecto, que, según la documentación, consiste en un menú de una columna y dieciséis filas. Además, no podemos desplazarnos por las opciones, lo cual hace que nuestro menú sea incluso menos interesante.
www.linuxmagazine.com.es
Listado 2: Menú mejorado. 01 . 02 . 03 . 04 menu_principal=new_menu((ITEM* *)barra); 05 set_menu_format(menu_principal ,1,5); 06 post_menu(menu_principal); 07 refresh(); 08 09 int ch; 10 11 while ((ch=getch())!=KEY_HOME) 12 { 13 switch(ch) 14 { 15 case KEY_RIGHT: 16 menu_driver(menu_principal, REQ_RIGHT_ITEM); 17 break; 18 case KEY_LEFT: 19 menu_driver(menu_principal, REQ_LEFT_ITEM); 20 break; 21 default: 22 menu_driver(menu_principal, ch); 23 break; 24 } 25 } 26 . 27 . 28 .
Vamos a ver como se solucionan los dos problemas anteriores y después pasaremos a abstraer el código a una clase.
Un poco de Movimiento En el listado 2 podemos ver una versión mejorada del programa, o al menos la parte que nos atañe. Observemos, por ejemplo, que hemos insertado una nueva función, set_menu_format(), a la cual, pasándole el puntero del menú el cual queremos modificar y las filas y las columnas, modifica el formato por defecto. Como nosotros queremos tener una barra de menús, utilizamos una sola fila y varias columnas, tantas
Curses
DESARROLLO
Listado 3: application.cpp (fragmento) 01 02 03 04 05 06
. . . void application::mainMenu() { window main_Menu(COLS-2,3,1,1,TRUE,"" ); 07 vector<string> mitems; 08 09 mitems.push_back("Fichero"); 10 mitems.push_back("Editar"); 11 mitems.push_back("Ventanas"); 12 mitems.push_back("Ayuda"); 13 14 menuClass main_App_Menu(mitems,main_Menu .getWHandle(),1,10); 15 app_Window.wWrite(2,10,main_Ap p_Menu.hideMenu()); 16 17 main_Menu.closeWindow(); 18 } 19 . 20 . 21 .
Figura 2: Eso está mejor: una barra de menús, y además…
Figura 3: ¡Podemos desplazarnos por ella!
como elementos del menú, para el formato. Lo siguiente es conseguir mover el enfoque de elemento a elemento. Esto lo conseguimos dentro del bucle principal, consultando a la variable ch. Si ch contiene el seudo-carácter KEY_RIGHT (correspondiente a la tecla de flecha de cursor derecha), llamaremos a la función menu_driver() de la librería menu. La función menu_driver() es el motor tras la interacción del usuario con el menú una vez creado este. Acepta como entrada el puntero al menú al cual afectarán los
cambios y un carácter o seudo-carácter que dicta el comportamiento del enfoque del menú. En el ejemplo que nos ocupa, al pulsar el usuario en las flechas izquierda y derecha, el enfoque se desplaza hacia el elemento de la izquierda o derecha, respectivamente. La tercera opción, permite que menu_driver() busque una coincidencia en la lista de opciones en el caso de que ch sea un carácter imprimible. Por ejemplo, si tenemos el enfoque en el primer elemento del menú (“Fichero”
- ver figura 2) y pulsamos la letra “v”, menu_driver() desplazará el enfoque a la opción “Ventana” (ver figura 3) y empezará a examinar la segunda letra de todas las opciones que empiecen por “v” a la espera de otro carácter imprimible que le puede permitir depurar la selección. Aquí, en este caso, es una funcionalidad un poco tonta, pero podéis imaginar su utilidad si tenemos una larga lista de nombres sacada, por ejemplo, de una base de datos y podemos ir tecleando las letras del apellido buscado y menu_driver() nos iría acercando al registro buscado. Ha llegado el momento de crear la clase menú.
Un Menú con Clase Ahora es cuando empieza lo interesante y quitamos de en medio todos esas feas funciones. El listado 3 muestra un fragmento de la implementación de la clase application (ver los dos capítulos anteriores de esta serie, aparecidas en Linux Magazine 1 y Linux Magazine 2 - el
www.linuxmagazine.com.es
Número 03
39
DESARROLLO
Curses
Listado 4: Implementación de la clase menuClass 01 #include <menuclass.h>
set_menu_sub(menu_Thing,derwin (menu_Window,1,COLS-4,1,2)); 12 showMenu(); 13 moveFocus(); 14 } 15 16 menuClass::~menuClass() 17 { 18 } 19 20 string menuClass::hideMenu() 21 { 22 string option=getSelectedItem(); 23 24 unpost_menu(menu_Thing); 25 refresh(); 26 free_menu(menu_Thing); 27 while (*menu_Items)
28 free_item(*menu_Items++); 29 return option; 30 } 31 32 void menuClass::createItemList() 33 { 34 unsigned int i; 35 menu_Items=(ITEM**)calloc(item _List.size(),sizeof(ITEM*)); 36 37 for (i=0;i<item_List.size();i++) 38 menu_Items[i]=new_item(item_Li st.at(i).c_str(),""); 39 menu_Items[i]=new_item(NULL,"" ); 40 } 41 42 void menuClass::setMenuWindow(WINDO W* window=stdscr) 43 { 44 menu_Window=window; 45 setMenuWindow(menu_Window); 46 } 47 48 void menuClass::showMenu() 49 { 50 post_menu(menu_Thing); 51 wrefresh(menu_Window); 52 } 53 54 void menuClass::moveFocus() 55 { 56 int ch; 57 while((ch=getch())!=13)
código completo se puede descargar de [1]) que muestra el método que activa el menú principal de la aplicación. No requiere mucha explicación. Creamos una ventana donde alojar el menú (esto es práctica habitual en curses) y a continuación utilizamos un vector de cadenas para almacenar las etiquetas de cada opción. Después creamos un objeto menuClass al cual pasamos el vector, el handle de la ventana y la posición del menú dentro de esa ventana. He optado por la fila 1 y columna 10 para no “pisar” el borde del cual he dotado la ventana
con el fin de que quede el área del menú claramente delimitado (ver figura 4). La inicialización de la clase implica la creación y visualización del menú, a la vez que se traslada el enfoque a él. El enfoque permanece con el objeto hasta que el usuario pulsa [Enter] habiendo realizado su selección (todo esto lo vemos un poco más abajo). Una vez que el menú libera el enfoque, recogemos la salida del método hideMenu(), que es la opción escogida cuando el usuario pulsó [Enter] y lo imprimimos en pantalla para demostrar
02 03
04 05 06 07 08
menuClass::menuClass(vector<st ring> items, WINDOW* window=stdscr,int rows=16, int columns=1) { item_List=items; createItemList(); menu_Window=window; menu_Thing=new_menu((ITEM**)me nu_Items);
09 set_menu_format(menu_Thing,row s,columns); 10 set_menu_win(menu_Thing,menu_W indow); 11
40
Número 03
www.linuxmagazine.com.es
58 59 60 61 62
{ switch (ch) { case KEY_RIGHT:
menu_driver(menu_Thing,REQ_RIG HT_ITEM); 63 break; 64 case KEY_LEFT: 65 menu_driver(menu_Thing,REQ_LEF T_ITEM); 66 break; 67 case KEY_UP: 68 menu_driver(menu_Thing,REQ_UP_ ITEM); 69 break; 70 case KEY_DOWN: 71 menu_driver(menu_Thing,REQ_DOW N_ITEM); 72 break; 73 default: 74 menu_driver(menu_Thing,ch); 75 break; 76 } 77 wrefresh(menu_Window); 78 } 79 } 80 81 string menuClass::getSelectedItem() 82 { 83 selected_Item=item_name(curren t_item(menu_Thing)); 84 return(selected_Item); 85 }
que es correcto. Obviamente, en un caso real, la clase application tendría que hacer algo más productivo con esta salida, como guardar el fichero en edición, abrir una ventana de ayuda, etc. Por fin, cerramos la ventana del menú para que desaparezca del entorno. Cómo habréis imaginado, la clase menuClass es el meollo de la cuestión. El listado 4 muestra su implementación. Esta clase es virtualmente hermética, es decir casi ninguno de sus métodos ni ninguno de sus atributos son accesibles desde fuera de la clase. Ella se la guisa y
Curses
DESARROLLO
Listado 5: El fichero principal.cpp 01 #include "application.h" 02 03 int main() 04 { 05 int ch, cDialogos=1; 06 application my_App(TRUE,"Mi Aplicación número %i",1); 07 08 while((ch=my_App.wGetch())!=KE Y_HOME) 09 10 11 12 13 Figura 4: Un menú delimitado en nuestra aplicación.
ella se la come. La excepción son el constructor (a partir de la cual se llaman todos los otros métodos), el destructor (que está vacío), el método hideMenu() (que se llama para cerrar el menú y recoger el valor seleccionado) y getSelectedItem(), que devuelve la etiqueta de la opción actual escogida (ya que es útil poder acceder a esta información en cualquier momento). El constructor menuClass() (de la línea 3 a la 14) es la encargada de llamar a todos los otros métodos (a excepción de hideMenu()) en su debido orden. Primero inicializa un vector string llamado item_List que, como su nombre indica, contendrá la lista de elementos que mostrará el menú. Seguidamente, llamamos al método createItemList() que hace exactamente eso: crear la lista de elementos en un formato que podrá insertarse en el menú. Si se ha seguido este artículo hasta el momento, el método createItemList() (de la línea 34 a la 42) no entrañará ningún misterio: Primero reservamos memoria para la lista (línea 37) y a continuación volcamos las etiquetas en el espacio reservado (líneas 39 y 40), para, finalmente, marcar el final de la lista con un elemento nulo. De vuelta al constructor, el siguiente paso consiste en inicializar el menú propiamente dicho (línea 8), establecer su formato, la ventana y la subventana donde se va a mostrar y exhibirlo. El encargado de esto último es el método
showMenu() (ver de la línea 51 a la 55) que simplemente utiliza la función post_menu() de la librería menu y refresca la ventana con wrefresh(). El constructor, por último, llama al método moveFocus() que se puede ver en el listado de la línea 57 a la 82. Este método se limita a escuchar las entradas del teclado y mueve el enfoque de un elemento a otro según convenga. Para que se puedan apreciar los cambios, después de que el enfoque haya cambiado, hay que refrescar la ventana (ver línea 80). Si el usuario pulsa [Enter] (clave ASCII 13), el bucle termina. Por último, hideMenu() recoge la última opción escogida y lo coloca en la variable de cadena option, esconde el menú y libera el espacio reservado por la lista de elementos. La variable option se devuelve a la función que llamó al método para ser procesada. Todos Juntos En el listado 5 podemos ver una función main que hace uso de la clase explicada a través de la clase application. Como se puede comprobar, no es nada complejo explotar esta clase. Para mostrar el menú, pulsaremos en F2 y para mostrar una ventana de diálogo como el que vimos el mes pasado, pulsamos en F1.
Conclusión En este artículo no hemos hecho más que rayar la superficie de las funcionali-
{ switch (ch) { case KEY_F(1): my_App.dialWin(50,10,"Esto se supone un Diálogo.","Diálogo %i",cDialogos++); break; case KEY_F(2): my_App.mainMenu(); break; }
14 15 16 17 18 19 20 21 22 23 }
} my_App.~application(); exit(0);
dades de la librería menu de curses. Existen muchas otras cosas que se pueden hacer. Entre ellas, la posibilidad de asociar una función con cada elemento de menú que se ejecute cuando se selecciona una opción. En todo caso, si tanto escribir te da pereza, existe por ahí toda una serie de clases (como, por ejemplo, las que se suelen instalar en /usr/share/doc/libncurses5-devel-5.3/c++/ con el paquete estándar de curses) con sus ejemplos que implementan más funcionalidades, tanto de menús, como formularios y otros aspectos de curses. Pero, estate advertido, están mal documentadas y son bastante más complejas que los mías. ■
RECURSOS [1] Listados completos en formato tar.gz con Makefile para facilitar la compilación http://www.linuxmagazine.com.es/ Magazine/Downloads/03
www.linuxmagazine.com.es
Número 03
41
DESARROLLO
Perl
Control remoto con un bot Jabber
Contacto Interior Para acceder a una LAN traspasando un cortafuegos, se necesita una puerta trasera secreta o un agente colaborador dentro. Un cliente Jabber dentro de la LAN conecta con un servidor Jabber público y esperará que aparezcan instrucciones en forma de mensajes instantáneos enviados por su conocido de Internet. POR MICHAEL SCHILLI
P
or supuesto, que una manera de realizar tareas, desde Internet, en una red local es abrir un agujero a través del cortafuegos y conectar con un servidor web local. Servicios como http://www.dyn-dns.org/ (entre otros) permiten un acceso casi estático a través de la dirección IP dinámica que asigna el proveedor de Internet. Un agente o “bot” (palabra derivada de “robot”) hace la vida más fácil: Un cliente de mensajería detrás del cortafuegos puede conectar con una red pública de mensajería Jabber y aceptar ordenes en formato de mensajes de texto. El cliente descrito en este artículo solo aceptará ordenes desde clientes de su lista de conocidos y solo permitirá cuatro acciones: cargar la comprobación para el ordenador bot, consultar la dirección pública del enrutador (orden: ip) y encender y apagar las luces de mi apartamento en San Francisco (lamp on|lamp off). El guión agent.pl (Véase el Listado 1)necesita Log::Log4perl y transacciones de “log” en un archivo llamado
42
Número 03
/tmp/agent.log. La línea 33 de este guión crea un nuevo objeto Net::Jabber::Client que implementa el cliente de mensajería instantánea que actuará como agente. Antes agent.pl entra en el bucle principal de eventos en la línea 83, se necesita definir unas cuantas retro-llamadas para varios eventos en la línea 35ff. El manejador onauth en la línea 68 se llamará después de que el cliente haya ingresado en el servidor usando las credenciales especificadas en la línea 23. El manejador entonces llamará a RosterGet() para que vaya a buscar la lista de conocidos y la almacene en una variable global %ROSTER. El método siguiente, Presence(),envía un mensaje presence a todos los clientes en la lista para decirles que agent.pl está en línea. A partir de este punto, un cliente gaim que haya ingresado como el usuario mikes-agent-sender mostrará a mikes-agent-receiver como cliente activo en su propia lista de conocidos (Véase la Figura 2). La retro-llamada message en la línea 37 se invocará cuando alguien envíe un mensaje a agents.pl. Cualquier cliente en la red Jabber puede hacer esto y es por eso que la línea 45 comprueba si el emisor es un amigo. En este caso mikes-agent-sender es el único al que se le permite enviar un mensaje, ya que es la única entrada en la lista de conocidos del cliente (Véase la sección “Instalación”). La función simplemente descarta todas las demás peticiones, almacena un mensaje de información en archivo de “log” y vuelve al bucle principal en la línea 50. El método getBody() en la línea 57 del guión extrae la orden de control enviada
www.linuxmagazine.com.es
con el mensaje de texto y la pasa a la función run_cmd definida en la la línea 93. En la línea 83, Execute() conecta con el servidor de Jabber en jabber.org e ingresa como mikes-agent-receiver. Si se pierde temporalmente la conexión el bucle principal, que se ejecuta indefinidamente, la rescatará. Si también se detiene porque se han producido muchos errores, la línea 90 los eliminará y parará el programa. Para estar seguro de que el agente empiece a funcionar cuando se inicialice el sistema, se añade lo siguiente:
Figura 1: El “bot” detrás del cortafuegos, ejecuta las ordenes que se le envían mediante un cliente Jabber basado en Internet. Figura 2: El “bot” aparece ahora en la lista de conocidos del emisor.
Perl
Para hacer esto agent.pl usa LWP::Simple; si el mensaje de texto que el cliente Jabber recibe es IP, la función get de la línea 99 toma el contenido de la página web. Determinar la carga actual del sistema sigue un patrón similar: La línea 17 llama a uptimes y el resultado pasa de vuelta a la línea 55. La siguiente llamada a chomp Figura 3: Visión general del interruptor de luz controlado por elimina el contenido sobrante y un “bot”. la línea 62 amontona el resultado en el cuerpo del mensaje; x:3:respawn:su U el método send envía este resultado username -cU hacia el compañero solicitante. /usr/bin/agent ¿Pero como hace un agente que está funcionando en un ordenador Linux, a /etc/inittab. Este código también se para encender la luz del dormitorio? cerciora de que el agente consiga reiniLa Figura 3 muestra la configuración. ciarse inmediatamente si deja de En EE.UU. se utiliza mucho una tecfuncionar por cualquier razón. nología conocida como X10 para transmitir señales a través del cableado Arriba y Abajo de la instalación eléctrica de los hogares (por supuesto que los equipos El agente descubre la dirección americanos solo funcionan con el externa del enrutador enviando una voltaje de ese país, aunque en Europa solicitud web a la URL pública http:// también se venden productos que utiperlmeister.com/cgi/whatsmyip. El lizan esta tecnología adaptados a los objetivo es un simple guión que valores europeos [5]). Estos equipos se devuelve la dirección del cliente comunican con el ordenador a través solicitante: de interfaces serie o USB. Hay disponible una amplia gama de disposiprint U tivos X10 para diversas tareas de "Content-Type: text/html\n\n"; automatización domestica. Además de print $ENV{REMOTE_ADDR}, "\n";
DESARROLLO
simples interruptores, se pueden encontrar sistemas con capacidades X10 en cámaras de vigilancia, sensores de movimiento, sistemas de alarma, reproductores mp3, televisiones y detectores de metales. Cada unidad de control X10 (Figura 4) tiene un código de casa (A-P) y un código de unidad (1-16) que la unidad de control (por ejemplo la de la Figura 5) ha de seleccionar para encender la lampara correcta (en vez de la del vecino). X10 no es caro (en EE.UU.): Un kit básico con cuatro componentes con toda clase de extras y un control remoto cuesta en algunos sitios entre 50$ y 100$ en [3]. El listado lamp.pl muestra un guión corto que envía los códigos a través del puerto serie al controlador de la lampara. El guión solo usa Device::ParallelPort y ControlX10::CM11 de CPAN, para direccionar la unidad usando el código de casa/unidad en la línea 38. El subsiguiente send() con el código y una “J” (para encender) o una “K” (para apagar) activa el dispositivo indicado. El puerto serie usado en este ejemplo en la línea 34 es /dev/ttyS0, donde la pequeña caja blanca que se ve en la Figura 6 está conectada al primer puerto serie del ordenador. Evidentemente, este equipo no está a la ultima, pero eso es solo para demostrar que Linux es poco exigente con los recursos. La línea 35 configura el baudrate a 4800
Figura 5: La unidad de control X10 con un conector Figura 4: La dispositivo X10 espera a la señal y
serie puede enviar señales desde el ordenador a los
Figura 6: Encendiendo la lampara del dormitorio
conecta y desconecta la lampara.
dispositivos X10 a través de la instalación eléctrica.
vía Internet.
www.linuxmagazine.com.es
Número 03
43
DESARROLLO
Perl
para asegurar que el dispositivo X10 conectado al puerto serie reciba el mensaje correctamente.
Potencia de root restringida lamp.pl accede al puerto serie del ordenador y necesita ejecutarse como root para hacer esto. La línea 29 comprueba que el user ID sea el correcto y detendrá la ejecución si no es 0 (root). Como el cliente Jabber se ejecuta con un user ID sin privilegios, el listado lamp.c define
un envoltorio C, que se puede compilar así de fácil:
Oct 2 08:48 lamp -rwxr-xr-x 1 root root 742 U Oct 2 08:45 lamp.pl
gcc -o lamp lamp.c
Ajustando el bit de setuid vía chmod 4755 lamp de manera que un usuario ‘normal’ pueda ejecutar el binario compilado lamp y por tanto el guión Perl /usr/bin/lamp.pl como root:
En esta configuración, solamente root puede modificar el guión lamp.pl, pero un usuario normal puede ejecutar lamp.pl con el ID efectivo de root.
Guardian Bot Y ahora volvamos al bot: Para evitar que cualquier cliente antiguo de Jabber envíe ordenes,
$ ls -l /usr/bin/lamp* -rwsr-xr-x 1 root root 11548U
Listado 1: agent.pl 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041
44
#!/usr/bin/perl ############################# # agent -- Jabber bot # Operando tras un cortafuegos # Mike Schilli, 2004 # (m@perlmeister.com) ############################# use warnings; use strict; use Net::Jabber qw(Client); use Log::Log4perl qw(:easy); use LWP::Simple; Log::Log4perl->easy_init( { level => $DEBUG, file => '>>/tmp/agent.log' } ); my $JABBER_USER = 'mikes-agent-receiver'; my $JABBER_PASSWD = "*****"; my $JABBER_SERVER = "jabber.org"; my $JABBER_PORT = 5222; our %ROSTER; my $c = Net::Jabber::Client->new(); $c->SetCallBacks( message => sub { my $msg = $_[1]; DEBUG "Mensaje '", $msg->GetBody(),
Número 03
042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083
www.linuxmagazine.com.es
"' from ", $msg->GetFrom(); if ( !exists $ROSTER{ $msg->GetFrom() } ) { INFO "Denegado (no está en . "la lista)"; return; }
"
DEBUG "Ejecutando ", $msg->GetBody(); my $rep = run_cmd( $msg->GetBody() ); chomp $rep; DEBUG "Resultado: ", $rep; $c->Send( $msg->Reply( body => $rep ) ); }, onauth => sub { DEBUG "Auth"; %ROSTER = $c->RosterGet(); $c->PresenceSend(); }, presence => sub { # Ignorar todas las # peticiones de subscripción }, ); DEBUG "Conectando ...";
084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
$c->Execute( hostname => $JABBER_SERVER, username => $JABBER_USER, password => $JABBER_PASSWD, resource => 'Script', ); $c->Disconnect(); ############################# sub run_cmd { ############################# my ($cmd) = @_; # Encontrar IP Externo if ( $cmd eq "ip" ) { return LWP::Simple::get( "http://perlmeister" . ".com/cgi/whatsmyip" ); } # Imprimir Carga if ( $cmd eq "load" ) { return `/usr/bin/uptime`; } # Encender/Apagar luz if ( $cmd =~ /^lamp\s+(on|off)$/ ) { my $rc = system( "/usr/bin/lamp $1"); return $rc == 0 ? "ok" : "not ok ($rc)"; } return "Orden desconocida"; }
Perl
acepta mensajes presence desde cualquier cliente de la red. Esto no sería tan malo, pero sin más dificultades, pondrá a estos clientes en su lista de conocidos. Un manejador de presence vacío evitará que ocurra esto. Figura 7: Usando el cliente gaim para añadir el agente de ordenes a la lista de emisores aceptados.
Figura 8: Añadiendo el emisor a la lista de conocidos del “bot”. Figura 9: Añadiendo el “bot” a la lista de conocidos del emisor.
agent.pl solo acepta mensajes de las personas de su lista de nombres. Cuando llega un mensaje, la línea 45 comprueba que el emisor está en la lista y lo rechazará si no es así. El manejador de petición de presencia definido en la línea 75 está vacío e ignora cualquier petición desde clientes que quieran añadir al agente en su propia lista de conocidos. Net::Jabber::Client trae un manejador predeterminado que
use warnings; use strict; use Device::SerialPort; use ControlX10::CM11; my $UNIT_CODE = "F"; my $HOUSE_CODE = "1"; my %cmds = ( "on" => "J", "off" => "K", ); die "utilización: $0 [on|off]" if @ARGV != 1
01 02 03 04
Cuando se instale el bot, se debe configurar su lista de conocidos. La mejor manera de hacerlo es usando un cliente gaim [4], creando 2 nuevas cuentas en Jabber, mikes-agent-receiver y mikes-agent-sender y hacer que mikes-agent-receiver tenga a mikes-agent-sender en su lista de conocidos (Véase la Figura 7). Si ambas cuentas están en línea, en mikes-agent-sender emergerá el cuadro de dialogo mostrado en la Figura 8 y será necesario pulsar en Authorize para indicar al servidor que permita que se realice la acción. Entonces se preguntara a mikes-agent-sender si quiere poner a mikes-agent-receiver en su lista de conocidos (Figura 9); por supuesto que sí, hacer esto tiene sentido para permitir al remitente seleccionar el nombre en la lista de conocidos para enviar una orden al bot.
main(int argc, char **argv) { execv("/usr/bin/lamp.pl", argv); }
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
or $ARGV[0] !~ /^(on|off)$/;
RECURSOS [1] Listados de este artículo: http://www. linuxmagazine.com.es/Magazine/ Downloads/03
my $onoff = $1; die "Debe ser root" if $> != 0;
[2] “Jabber Developer’s Handbook”de Dana Moore y William Wright, Colección Developer’s Library, de la editorial Sam’s Publishing, 2004.
my $serial = Device::SerialPort->new( '/dev/ttyS0', undef ); $serial->baudrate(4800);
[3] Dispositivos X10 de: http://x10.com
# Unidad de Dirección ControlX10::CM11::send( $serial, $UNIT_CODE . $HOUSE_CODE ); # Enviar Instrucción ControlX10::CM11::send( $serial, $UNIT_CODE . $cmds{$onoff} );
Después de salir de la sesión, hay que asegurarse de que la cuenta mikes-agent-receiver solo se utilice por agent.pl y no por otros clientes, para evitar que enreden en la lista de conocidos, que proporciona el mecanismo de la autorización. Cuando se lance agent.pl, mikes-agent-receiver debe aparecer en la lista de conocidos de mikes-agent-sender (Véase la Figura 2). El archivo de bitácora /tmp/agent.log, anotará lo sucedido en el caso de que sea necesario depurar la configuración. Hay que ser cuidadoso cuando se aplican modificaciones, un pequeño error en la implementación puede abrir un agujero en el cortafuegos ¡Hay que vigilarlo! Desde luego que si se vive en una zona donde la infraestructura eléctrica no da soporte a X10, se necesitará encontrar otra manera de comunicar con el interruptor de la lampara. Pero, aparte de este proyecto, estas técnicas ayudarán a comenzar con la construcción de un ■ agente de mensajería instantánea.
[4] Gaim, el cliente de mensajería instantánea universal: http://gaim.sourceforge. net [5] Dispositivos Domóticos: http://www. domotica.net/
EL AUTOR
#!/usr/bin/perl ############################# # lamp -- x10 light switch # Mike Schilli, 2004 # (m@perlmeister.com) #############################
Listado 3: lamp.c
Instalación
Listado 2: lamp.pl 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
DESARROLLO
Michael Schilli trabaja como desarrollador de software en Yahoo!, Sunnyvale, California. Es el autor de “Perl Power” de la editorial Addison-Wesley y se le puede contactar en mschilli@perlmeister.com. Su página está en http://perlmeister. com.
www.linuxmagazine.com.es
Número 03
45
ADMINISTRACIÓN
PHP
Uso de PHP en scripts de administración
Operación Comando La mayoría de los administradores suelen usar la shell, Perl o Python si necesitan programar un script de administración. Pero para los programadores de la web no es necesario aprender otros lenguajes para escribir una tarea de rutina. PHP proporciona a los administradores la potencia para programar herramientas de línea de comandos e incluso interfaces web completos. POR CARSEN MÖHRKE
L
os scripts escritos en PHP para la consola tienen básicamente la misma forma que scripts escritos para la web: los programadores pueden usar todo el rango de características de PHP. Para permitir de forma sencilla, que los programas se ejecuten en la línea de comandos, se necesita especificar el intérprete de PHP en la primera línea del fichero de scripts de la siguiente forma #!. Si no se conoce el path al intérprete, tecleando which php se averiguará. También, los ficheros de scripts necesitan tener activado el permiso de ejecución. Echémosle un vistazo al típico ejemplo “Hello, World” en PHP: #!/usr/bin/php -q <?php echo "Hello, World\n"; ?>
Las herramientas de PHP es lo que se necesita para cualquier clase de manipulación de texto, como modificación de ficheros de
configuración, ficheros de registro, entradas de gestión de usuarios y cosas así. Si se necesita acceder a las funciones de sistema operativo, para tareas como administración de procesos, se necesitará añadir algunos comandos Linux.
Línea de Comandos PHP tiene cuatro funciones diseñadas para la ejecución de comandos del sistema: exec(), system(), passthru() y shell_exec(): *exec() ejecuta el comando que se le pasa como primer argumento y elimina cualquier salida del comando. La última línea del comando se devuelve como resultado. Si el segundo parámetro es el nombre de un array, exec() rellena el array línea a línea con la salida que debería aparecer en la pantalla. Si se necesita procesar el código de salida del comando exec() se puede usar un tercer parámetro. *system() no suprime la salida al contrario que exec(). Tiene un segundo parámetro opcional para el código de salida.
Interfaces para la Shell Antiguos y Modernos Las versiones de PHP 4.3.0 o posteriores tienen un nuevo interfaz para la shell para programar herramientas desde la línea de comandos: el CLI(Command Line Interface). Las versiones previas de PHP (incluso algunas nuevas) tienen un interfaz de programación llamado Server Application Programmers Interface (SAPI), pero SAPI fue diseñado para usarse en servidores web (CGI-SAPI) y añade una cabecera HTTP a la salida. (Se puede suprimir la cabecera colocando la opción -q cuando se lanza el intérprete de PHP, pero esto no eliminará las etiquetas HTML de los mensajes de error). Se puede comprobar si se tiene la versión CGI, que no tiene el mismo alcance de características que tiene la interfaz de línea de comandos, tecleando php -v. El ejemplo de este artículo funcionará con cualquier versión.
46
Número 03
www.linuxmagazine.com.es
*passthru() funciona como system(), pero en modo binario compatible. Esto permite al comando pasar imágenes generadas como salida convertidas para un navegador web. *shell_exec() funciona como una versión simple de parámetros de exec(), pero en vez de extraer la última línea, devuelve una cadena con la salida completa del comando. La cadena contiene caracteres de nueva línea en contraposición a las entradas que devolvía el comando exec() en el array de valores. Tanto exec() como shell_exec() son útiles en casos donde se necesite manipular el texto de salida de un comando externo. Los ejemplos que vienen a continuación hacen uso de la función exec(), que es mucho más flexible que las otras funciones. Nos encontramos con un pequeño fallo técnico relacionado con esto en la actualidad: PHP no siempre devuelve el código de salida correcto del comando externo (por ejemplo cuando concatenamos comandos).
Control de Procesos El siguiente script PHP usa exec() para mostrar el número de procesos que se ejecutan en el sistema: unset ($out); $cmd="ps axu | wc -l"; $erg=exec($cmd,$out); $erg-=1; //minus 1 line header echo "Number of active U processes is $erg\n";
PHP
El fichero primero elimina el contenido de la variable $out, que representa el array donde se almacenará la salida del comando. exec() no sobrescribiría el array sino que simplemente le añadiría al final la nueva salida. El ejemplo impide que se mezclen los resultados de múltiples scripts vaciando primero el array. El comando detecta el número de líneas en la lista de procesos y resta una línea de las cabeceras de columna. shell_exec() y exec() tan sólo pueden manejar datos de stdout. Para capturar la salida de error estándar desde stderr, se necesita redireccionar la salida de error a stdout: 2 >&1. Los programadores a menudo necesitan pasar argumentos de la línea de comandos al script. Para permitir que esto pueda hacerse, PHP introduce los argumentos que siguen al nombre del fichero en la línea de comandos dentro de un array llamado $argv, conservando el orden original. Además, el número de argumentos se almacena en la variable $argc.
Buenos Argumentos PHP no soporta comandos que lean datos directamente desde el teclado. Para proporcionar soporte a las entradas de teclado, los programadores pueden abrir el flujo stdin como un fichero y leer desde él. Esto permite el uso de los flujos stdout y stderr relacionados: $in=fopen("php://stdin","r"); $err=fopen("php://stdin","w"); $input=trim(fgets($fp, 100)); while (""==$input) { fputs($err,"Please input a U value\n"); }
Si se usa stdin para leer las entradas de teclado de esta forma, el script debería usar la función trim() para eliminar los espacios en blanco al final de la cadena. No hay necesidad de usar stdout para la salida de datos, ya que PHP cuenta con las funciones echo y print para realizar estas tareas. La salida de ambos comandos pueden ser redireccionadas.
Coloreado Para diseñar aplicaciones más cómodas, los programadores necesitan funciones que borren la pantalla, que controlen el
Tabla 1: Secuencias de Escape importantes Significado
Secuencia
Borrar Pantalla
\033[2J
Posicionar el cursor en x,y \033[x;yH Coloca el cursor n posiciones a la izquierda \033[nC Coloca el cursor n posiciones arriba \033[nA Color de Fuente rojo
\033[0;31m
Color de Fuente negro
\033[0;30m
Color de Fuente verde
\033[0;32m
Color de Fuente gris
\033[0;37m
cursor y que añadan color a la salida. Las secuencias ANSI [1] proporcionan una solución útil, ya que la shell es capaz de interpretarlas. Estas secuencias empiezan con el carácter Escape y son conocidas como secuencias de Escape. Por ejemplo, la secuencia echo "\033[2J" limpia la pantalla. La Tabla 1 lista unas cuantas de las secuencias más importantes. El color seleccionado permanece válido hasta que se selecciona un color diferente. Las funciones de PHP ncurses proporcionan mayor portabilidad y un rango mucho más amplio de características. Véase los ejemplos de las páginas web de PHP o Zend en [2], [3] para más detalle.
Gestión de Usuarios El siguiente ejemplo muestra las funciones referidas a aquellas en el contexto de un script para la gestión de usuarios de un servidor con el fin de que se vean ejemplos prácticos. El Listado 1 es una muestra y el script completo está disponible para descargarse desde [4]. Nótese que el script abre la entrada estándar con fopen() pero no hace uso de fclose() para cerrarla. Ya que PHP automáticamente cierra todos los flujos abiertos cuando finaliza el programa, el script evita cerrar el flujo por razones de legibilidad. El tiempo de ejecución para los programas de la línea de comandos no está restringido. PHP es ideal para crear interfaces web. Esta atractiva opción tiene algunas pegas ocultas. Cuando se diseña una aplicación se necesita considerar los riesgos potenciales de seguridad. El más pequeño de los agujeros de seguridad podría tener consecuencias fatales. Un ejemplo:
ADMINISTRACIÓN
01 <form method="POST"> 02 Command: <input name= "cmd" /><br /> 03 <input type= "submit" value= "Execute" /> 04 </form> 05 <?php 06 if (isset ($_POST['cmd'])) 07 { 08 $outp=shell_exec 09 ($_POST[cmd]); 10 echo "<pre>$outp</pre>"; 11 } 12 ?>
Las soluciones que ejecutan comandos arbitrarios (como esta) están fuera de lugar. Los scripts de administración tan sólo deberían ser ejecutables dentro de un entorno seguro y no deberían permitir ninguna posibilidad de que sean manipulados.
Privilegios Especiales Los scripts a menudo necesitan privilegios de root. Un script PHP basado en web normalmente se ejecuta con los privilegios del identificador de usuario del servidor web. Podría parecer obvio darle a este usuario (típicamente www, wwwrun o nobody) muchos más privilegios, pero esto es extremadamente peligroso. Comandos como sudo o su proporcionan una alternativa. Sin embargo, su requiere la práctica insegura de añadir la clave de root como texto en claro dentro del script. La herramienta sudo también puede asignar privilegios de root para acciones específicas a un usuario sin la necesidad de que este usuario conozca la clave de root. En vez de ello, los usuarios se autentican con su propia clave y se les asignan los privilegios específicos por el root en el fichero /etc/sudoers. Si un administrador necesita asignar al usuario webadmin el derecho de terminar procesos con el comando kill, él o ella podría añadir la siguiente línea a /etc/sudoers: webadmin ALL = /bin/kill, U /usr/bin/killall
Es una buena idea usar el editor visudo para esto. El editor se asegura de que sólo un usuario puede editar el fichero
www.linuxmagazine.com.es
Número 03
47
PHP
de configuración al mismo tiempo. Además se asegura de que las entradas concuerden con las reglas y no entren en conflicto. La sintaxis genérica para asignar privilegios con sudo es: QUIEN DONDE = QUE. QUIEN puede ser un nombre de usuario, como en nuestro ejemplo, o un grupo de usuarios que deben ser definidos usando un User_Alias. DONDE significa el host donde el usuario tendrá estos privilegios.
Cambio de Identidad Gracias a las entradas en el fichero de configuración de sudo, el usuario webadmin puede ahora “matar” procesos de forma arbitraria después de introducir su clave para la cuenta de usuario. Un script automatizado podría pararse y preguntar por la clave antes de continuar. Suele colocarse el parámetro -S para indicarle a sudo que lea la contraseña desde la entrada estándar. La línea de comandos sería como sigue: echo clave | sudo -S kill 13221
Si el usuario webadmin no es el usuario root del servidor web desde el punto de vista de los procesos de Unix (esto implicaría la herencia de los privilegios del usuario que probablemente no sería deseada en la mayoría de los casos), con toda seguridad se necesitará una combinación de su y sudo. El usuario del servidor web primero asumirá la identidad de webadmin temporalmente ejecutando su y entonces es cuando se le asignan los privilegios de root específicos por medio de sudo. Un script que usa esta solución puede parecerse a este: $user="webadmin"; //sudoer $pwd="clave"; U // Webadmin password $befehl="kill -9U ".escapeshellarg($_GET ["pid"]); $cmd_line="echo $pwd | U su -l $user -c \"echo $pwd | sudo -S U $command 2>&1\"";
$ret=shell_exec($cmd_line);
El script primero usa escape-shellargs() para manipular el pid, que lo procesa desde un formulario. Esto elimina los ataques potenciales a la shell, que por otro lado se podrían insertar en el código ■ de forma maliciosa.
RECURSOS [1] Códigos ANSI:http://en.wikipedia.org/ wiki/ANSI_escape_code [2] Manual de Funciones Ncurses: http:// www.php.net/ncurses [3] Tutorial Ncurses: http://www.zend.com/ zend/tut/tut-degan.php [4] Listado: http://www.linuxmagazine.com. es/Magazine/Downloads/03
EL AUTOR
ADMINISTRACIÓN
Carsten Möhrke es un consultor freelance y profesor, es el autor de “Better PHP Programming” y el CEO de Netviser. Puede ponerse en contacto con Carsten en cmoehrke@netviser.de.
Listado 1: Menú PHP 01 02 03 04 05
#!/usr/bin/php -q <?php function cls() { echo "\033[2J"; // Borrar Pantalla 06 echo "\033[0;0H"; // Cursor 07 to 0,0 08 } 09 10 function text_red() 11 { 12 echo "\033[0;31m"; 13 } 14 15 function text_black() 16 { 17 echo "\033[0;30m"; 18 } 19 20 // Funciones adicionales 21 // ¿Se ha insertado nombre de usuario? 22 $in=fopen("php://stdin","r"); 23 $err=fopen("php://stderr","w") ; 24 if (3==$argc &&
48
Número 03
25 26 27 28 29 30 31 32 33
34 35 36 37 38 39 40 41 42 43 44 45 46 47
"-u"==$argv[1] && isset($argv[2])) { $user=$argv[2]; // leer username } else { // no hay nombre de usuario fputs($err,"Por favor utilice -u para insertar un nombre de usuario\n"); exit(1); } // Comprobar existencia usuario // con etc/passwd if (false ===user_exists($user)) { fputs($err,"Nombre de usuario no existe\n"); exit(2); } while (1) //Procesado infinito loops { cls();
www.linuxmagazine.com.es
48 text_red(); 49 echo "Administración para usuario $user\n"; 50 text_black(); 51 echo "1) Comprobar consistencia\n"; 52 echo "2) Crear usuario MySQL DB\n"; 53 // Más elementos del menú 54 echo "q) Salir Programa\n\n"; 55 echo "Escoja una opción: "; 56 // Eliminar blancos e entrada 57 58 $input=trim(fgets($in,255)); 59 60 switch ($input) 61 { 62 case "1": 63 consistency_check($in); 64 break; 65 // Más casos 66 case "q": exit(0); 67 // beep en caso de entrada incorrecta 68 default: echo chr(7); 69 } 70 } 71 ?>
Python
DESARROLLO
¿Problemas de ortografía? La R.A.E. y Python raudas al rescate.
Python y Palabra Empiezan por “P”
Desde que llegó Internet todos escribimos más. Se supone que con los ordenadores y sus fabulosos correctores ortográficos y gramaticales no volveríamos a cometer errores garrafales al hescrivir. La realidad es que, a pesar de estas ayudas, cuando escribimos a través de los sistemas de mensajería o en los correos solemos usar argot, lo que nos obliga a desactivar los correctores. Es entonces, después de escribir mil veces ´k´ en lugar de ´que´, al enfrentarnos a escribir algo normal comienzan a asaltarnos dudas ¿esto era con ´b´ o con ´v´? ¿Existe esta palabra?. POR JOSÉ MARÍA RUÍZ Y JOSÉ PEDRO ORANTES
T
anto GNOME como KDE disponen de sendas aplicaciones para consultar diccionarios. A nosotros nos resultan muy útiles cuando, por ejemplo, aparece en alguna página o documento una palabra de argot o difícil en inglés. Entonces recurrimos a ellas, realizan consultas en prestigiosos diccionarios
como el Webster o en el famosísimo (a la par que desternillante) Jargon file. Pero no todo el mundo está dispuesto a usar GNOME o KDE (al menos uno de nosotros no lo hace), así que parece un poco desmedido instalar todo un escritorio gráfico solamente para tener acceso a un programa que podemos realizar sin
demasiada dificultad usando nuestro querido Python y el maravilloso Tkinter.
Hablando con el servidor de la R.A.E. La R.A.E. (Real Academia de la lengua Española) tiene una página web (http:// www.rae.es) donde podemos consultar el
www.linuxmagazine.com.es
Número 03
49
DESARROLLO
Python
parámetros seleccionemos nosotros, lo que nos permitirá hablar con el servidor directamente sin necesidad de usar un navegador. De esta manera podemos crear programas que salten el paso del navegador y accedan directamente al servidor HTTP. Ese es nuestro objetivo. Figura 1: Nuestra utilidad busca-palabras en marcha. Tenemos que localizar esos parámetros en el servidor HTTP de la R.A.E. en la página diccionario o realizar preguntas sobre de búsqueda de palabras. dudas lingüísticas. Tener que acceder a esa página es un poco engorroso si lo vas Localizando los Parámetros a hacer más de una vez. Ahora comienza nuestra labor de detecA pesar de todas esas buzzwords (que tives. Primero accedemos a la página de si PHP, que si J2EE, que si .NET) al final la R.A.E y pinchamos en Diccionario de todo acceso a un servidor web se realiza la lengua española, lo primero que nos a través del protocolo HTTP. Este protodebería extrañar es que la URL no ha colo no posee estados y, básicamente, cambiado, sigue siendo http://www.rae. sirve para pedir ficheros. En teoría es. Eso significa que nuestro browser implementa varios tipos de mensajes, de está volviendo a pedir el mismo objeto al los cuales solo el GET y el POST se utiservidor HTTP, pero lo que vemos es una lizan (existe otros más, como PUT que página distinta. Esto puede significar nos permitiría depositar archivos, pero varias cosas, pero una inspección del casi nadie lo usa). GET sirve para pedir código HTML de la página nos dice que un fichero a través de una URL y POST se están usando FRAMES. para enviar información al servidor El W3C [1], entidad que gestiona HTTP. Desde este punto de vista, un servidor HTTP solo ve dos cosas: archivos Listado 1: Programa que le pedimos y datos que le damos. buscador.py Tanto GET como POST se pueden utilizar para pasar información al servidor. 01 #!/usr/local/bin/python Ambos tienen ventajas e inconve02 nientes. Generalmente se usa GET, 03 from popen2 import popen2 porque los parámetros que pasamos al 04 from sys import argv servidor van incluidos en la URL. De 05 esta manera podemos pasarle una URL 06 def busca_palabra(palabra): a alguien o ponerla en nuestra página y 07 salida, entrada = cualquiera podrá ver la página con los popen2('lynx -dump --nolist parámetros que nosotros selec"http://buscon.rae.es/draeI/Sr cionamos. Con POST esto no es posible, vltGUIBusUsual?TIPO_HTML=2&LEM ya que los parámetros no están preA=' + palabra + '"') sentes en la URL. Los estándares dicen 08 entrada.close() que GET debe usarse para pasar 09 cadena = salida.read() parámetros (opciones por ejemplo) 10 print(cadena) mientras que POST debe ser usado para 11 mandar información al servidor que 12 if __name__ == "__main__": posteriormente sea almacenada. 13 if ( len(argv) == 1 ): Si entramos en una página web y 14 print("ERROR: hace prestamos atención a las URLs que se falta un argumento") van generando podemos encontrar las 15 else: opciones que acepta esa página. Si las 16 busca_palabra(argv[1]) localizamos podemos crear URLs cuyos
50
Número 03
www.linuxmagazine.com.es
muchos de los estándares de la web, desaconseja el uso de FRAMESET, la razón es que engañan a las URLs y al usuario. Por ejemplo, estoy diciendo que estamos en la página de búsqueda del diccionario de la R.A.E., pero la URL sigue siendo la de la página principal de la R.A.E. (http://www.rae.es), así que no podemos deciros que vayáis a esa URL porque no se corresponde con la de búsqueda en el diccionario. Por ello los FRAMES destruyen la idea de que una URL, una dirección, corresponde a un solo objeto en la red. La página de búsqueda la componen 2 FRAMES ( o subpáginas): cabecera y portada. La cabecera no nos interesa. La portada a su vez la componen los FRAMES: elección y presentación. Este último es el que presenta los resultados de la búsqueda… ¿pero como sabe a qué palabra nos estamos refiriendo? Cada FRAME contiene varias páginas, y los FRAMES se diseñaron para mostrar varias páginas la vez. A nosotros solo nos importa una página: http://buscon. rae.es/draeI/SrvltGUIBusUsual. Esta página es la que acepta un parámetro, LEMA, y devuelve una web con la definición (o un aviso de fallo) de LEMA. El método usado es POST, lo sabemos porque si vemos la información de la página, los parámetros pasados son LEMA de tipo POST. Pero muchas aplicaciones web, en particular la que usar Servlets de Java, suelen buscar los parámetros tanto en POST como en GET. Y éste es nuestro caso. ¿Cómo se pasan parámetros? Pues muy sencillo, vamos a usar GET. Se pone la URL y se le añade ?<PARAMETRO1>=<VALOR1>&<PARAMETRO2>=<VALOR2>. Por ejemplo: http://buscon.rae.es/draeI/ SrvltGUIBusUsual?LEMA=hola. Ahora tenemos que ver como es posible obtener el contenido de esa URL.
Lynx al Rescate Podríamos haber diseñado algún complejísimo sistema, para traer la página HTML, eliminarle las etiquetas, formatearla y demás; pero la vagancia, aliada poderosa del buen programador, nos hace buscar una manera más simple de hacer esto. La manera más simple, consistiría en seguir el ejemplo de xdrae [2]. Esta apli-
Python
cación, realizada en Tcl/Tk, descansa en otro programa, lynx, para obtener el resultado de las búsquedas parseado y en formato texto. Esto nos enseña un lección muy importante de la manera en que UNIX entiende la reutilización de código. La manera propuesta por UNIX es la creación de utilidades compactas y pequeñas que puedan ser conectadas mediantes tuberías (por ejemplo ls -l | wc -l). Para que esto sea posible, las salidas deben ser en formato texto. lynx acepta multitud de parámetros pero posee uno, -dump, que hace que vuelque en la salida estándar la página, pero ya formateada de manera que es ASCII sin etiquetas HTML. Si lo hacemos así, lynx nos volcará la página formateada más una lista de todos las URLs de los hipervínculos de la misma. Para que no lo haga añadimos --nolist. Nos quedaría al final algo así: lynx -dump --nolist URL.
18
popen2
19
Para poder recoger lo que lynx genera tenemos que crear una tubería entre él y nosotros. Para ello existe la función popen2 de la librería del mismo nombre. Esta función ejecuta un programa y crea dos descriptores de fichero, uno para mandarle texto al programa y otro para recibirlo. Se corresponden con la entrada y la salida estándar del programa que se ejecuta. La idea es ejecutar lynx... con popen2. Su entrada estándar no nos interesa, así que la cerramos, pero la salida estándar es lo que buscábamos. Una vez ejecutado popen2, el volcado de lynx... puede ser leído como si leyésemos un fichero. >>> salida, entrada = popen2U ("wc -w") >>> entrada.write("En un lugarU de la mancha de cuyo nombre noU quiero acordarme") >>> entrada.close() >>> print salida.read() 12 >>>
wc -w devuelve el número de palabra que son leídas de su entrada estándar hasta el fin de fichero (por eso tenemos que hacer un entrada.close()).
DESARROLLO
Listado 2: Programa buscador2.py 01 02 03 04 05 06 07 08 09 10
#!/usr/local/bin/python
self.scrollbar.pack(side=RIGHT ,fill=Y)
from popen2 import popen2 from Tkinter import * from Tkconstants import *
35 36
class GUI: def __init__(self): self.root = Tk() self.crea_panel_busca()
11 self.crea_panel_muestra() 12 13 14 15 16 17
20 21 22
def arranca(self): mainloop() def busca_palabra(self): self.label_estado.config(text= "Estado: buscando palabra...") palabra = self.entry_palabra.get(); salida, entrada = popen2('lynx -dump --nolist "http://buscon.rae.es/draeI/Sr vltGUIBusUsual?LEMA=' + palabra + '"') entrada.close() texto = salida.read() # Borramos el texto que hubiese antes
23 self.label_estado.config(text= "Estado: mostrando texto") 24 self.text_muestra.delete(1.0,E ND) 25 self.text_muestra.insert(1.0,t exto) 26 salida.close() 27 28 def crea_panel_muestra(self): 29 self.panel_muestra = Frame(self.root) 30 self.panel_muestra.pack() 31 32 # Vinculamos una barra de desplazamiento 33 self.scrollbar= Scrollbar(self.panel_muestra) 34
# Caja de texto para mostrar la definición de la 37 # palabra 38 self.text_muestra = Text(self.panel_muestra, yscrollcommand = self.scrollbar.set) 39 self.text_muestra.pack() 40 41 def crea_panel_busca(self): 42 self.panel_busca = Frame(self.root) 43 self.panel_busca.pack() 44 45 self.label_estado = Label(self.panel_busca, text="Estado: parado") 46 self.label_estado.pack(side=LE FT) 47 48 self.entry_palabra = Entry(self.panel_busca) 49 self.entry_palabra.pack(side=L EFT) 50 51 # Botón de salida 52 self.btn_salir = Button(self.panel_busca,text=" Salir", command= self.root.destroy) 53 self.btn_salir.pack(side=RIGHT ) 54 55 self.btn_busca = Button(self.panel_busca, text='Buscar', command=self.busca_palabra) 56 self.btn_busca.pack(side=RIGHT ) 57 58 if __name__ == "__main__": 59 60 app = GUI() 61 app.arranca()
www.linuxmagazine.com.es
Número 03
51
DESARROLLO
Python
a campo_texto y a boton1 dentro de panel. Veamoslo en práctica con un hola mundo.
Figura 2: Página del diccionario de la RAE.
Ahora solo tenemos que ejecutar nuestro comando lynx... y leer su salida, almacenando el valor en una variable.
Script de Consulta Sencillo xdrae hace uso de esta metodología de trabajo, invocando a lynx, que realiza la mayor parte del trabajo pesado, dejándole a xdrae la gestión del GUI. Un script sencillo para que consigamos el mismo resultado sería el del Listado 1. Cuando Python comenzó a tener expansión se hizo evidente la necesidad de un sistema para la creación de interfaces gráficos. Pudieron hacer lo mismo que en Java y crear su propio sistema (AWT y Swing), pero en lugar de eso reutilizaron uno ya existente: Tcl/Tk.
Tcl/Tk Tcl/Tk son unas siglas extrañas, pueden recordarnos a TCP/IP y la verdad es que algo comparten con ellas. Tanto Tcl/Tk como TCP/IP hacen referencia a 2 tecnologías que trabajan juntas. En el caso de Tcl/Tk estas tecnologías son el lenguaje script Tcl y el sistema de interfaz gráfico de usuario Tk. Tk fue creado después que Tcl, y está realizado como una extensión de Tcl. Tcl fue creado por el profesor John K. Ousterhout con el objetivo de disponer de un lenguaje script que fuese sencillo
52
Número 03
de empotrar en aplicaciones realizadas en C. La idea era que el usuario pudiese extender la funcionalidad de la aplicación sin tener que ponerse a programar en C, sino creando scripts que la aplicación ejecutaría. Al poco tiempo comenzó a trabajar en Tk, una extensión de Tcl que permitiría la creación de interfaces gráficos de manera rápida y simple gracias a Tcl. Aunque no hayamos escuchado hablar mucho de Tcl/Tk, su importancia en el software es muy grande, muchos lenguajes usan Tk como librerías gráficas. Tcl/ Tk se ha usado mucho en el prototipado de aplicaciones.
El hola mundo Gráfico Después de esta pequeña lección de historia, pongámonos manos a la obra. Lo primero que necesitamos saber es como estructura Tk los widgets (usaremos esta palabra a partir de ahora, viene a significar elementos gráficos). Tk usa un árbol, como el árbol de directorios, pero en lugar de usar el símbolo / y usa el punto, .. La aplicación se crea desde la raíz, . hacia adelante. Los widgets pueden contener otros widgets, o sea, los widgets pueden ser directorios de otros widgets. Así podemos tener un widget .panel que tenga dos hijos .panel.campo_texto y .panel.boton1. Visualmente veríamos
www.linuxmagazine.com.es
01 >>> import Tkinter 02 >>> from Tkconstants import * 03 >>> tk = Tkinter.Tk() 04 >>> 05 >>> panel = Tkinter.Frame(tk, relief=RIDGE, borderwidth=2) 06 >>> panel.pack(fill=BOTH, expand=1) 07 >>> 08 >>> etiqueta = Tkinter.Label (panel, text="Hola Linux Magazine") 09 >>> etiqueta.pack(fill=X, expand=1) 10 >>> 11 >>> boton = Tkinter.Button (panel,text="Salir", command=tk.destroy) 12 >>> boton.pack(side=BOTTOM) 13 >>> 14 >>> tk.mainloop()
El método pack posiciona los widgets dentro de su widget padre, si le especificamos side=BOTTOM los irá posicionando uno encima de otro; fill=X sirve para que el widget ocupe todo el espacio horizontal (con fill=Y ocuparía el vertical y con fill=XY todo el espacio disponible); expand=1 hace que el widget crezca si su padre crece, en caso contrario no modificará sus dimensiones. Tk funciona de la siguiente manera. Primero se construye el interfaz gráfico. Cada elemento del interfaz responde a una serie de eventos (ser pulsado, que el ratón pase por encima…) y cada uno de estos eventos puede estar vinculado con un procedimiento que se dispara al ocurrir el evento. Así que asignamos procedimientos a los eventos de los widgets. Por último entramos en el bucle principal (main loop). Todas las invocaciones a las funciones de creación de widgets tienen un primer argumento, en él se especifica de quien cuelga (o dentro de quien está) nuestro widget. Aquí el widget tk representa la ventana, dentro de la cual hay un panel y dentro del cual hay dos widgets, una etiqueta y un botón. El botón tiene vinculado un comando, en este caso tk.destroy, pero podría
Python
DESARROLLO
Figura 4: “Hola Mundo” de Tcl/Tk.
Ensamblaje Final
haber sido otro. Podríamos haber incorporado otro botón antes de ejecutar el tk.mainloop(): >>> def escribe(): ... print "Hola mundo" ... >>> >>> boton2 = Tkinter.ButtonU (panel, text="Escribe",U command= escribe ) >>> boton2.pack(side=BOTTOM)
Habría otro botón, debajo de el botón Salir, que al pulsarlo escribiría por la salida estándar (normalmente la consola) el texto Hola mundo.
Diseño de la aplicación Tk tiene todos los widgets que existen en el resto de GUIs. Tenemos etiquetas, botones, paneles, imágenes, combos y demás. Nosotros lo que necesitamos es: • Un panel • Una etiqueta Estado, un campo de entrada de texto, un botón Buscar y otro Salir. • Un widget de texto con múltiples líneas para la respuesta, con una barra de desplazamiento asociada. • Deberíamos también darle un título a la ventana.
Barras de desplazamiento + Campos de texto = algo muy útil Un widget de texto es un widget que nos permite mostrar una gran cantidad de texto. Posee infinidad de opciones, sien-
do posible implementar con ellas hasta un intérprete de HTML o crear texto enriquecido. Vamos a usar un widget de texto para contener la respuesta del servidor de la R.A.E.. Tenemos que solucionar el problema de que la respuesta de la R.A.E. sea mayor que el contenido de nuestro campo. Nuestro widget de texto no va ser redimensionable y puede que haya más texto del que quepa en el área que vemos del widget de texto. Para solucionar este problema, se inventaron las barras de desplazamiento, que damos por sentadas, pero que fueron toda una innovación en su día. La idea es crear una barra de desplazamiento y vincular su movimiento y tamaño al texto mostrado en el widget de texto que tendrá asociada. En Tk el tamaño no es posible vincularlo, pero podemos vincular el movimiento. Algunos widgets, aquellos propensos a usar una barra de desplazamiento, poseen un evento llamado yscrollcommand, que toma un valor de una función y lo usa para posicionar el texto dentro del widget. El widget tiene un elemento llamado viewport, que es la ventana dentro de todo lo que tiene el widget que puede ver el usuario. El widget puede tener, aprovechando la coyuntura, “El Quijote” pero en el viewport solo se ven unos cuantos párrafos de la obra de Cervantes. Cuando vinculamos una barra de desplazamiento con un widget de texto en realidad lo que hacemos es que vinculamos el valor de inicio del viewport con el de la barra de desplazamiento.
RECURSOS [1] W3C http://www.w3c.org [2] Página de xdrae http://xinfo.sourceforge. net/xdrae.html
José María Ruiz actualmente está realizando el Proyecto Fin de Carrera
LOS AUTORES
Figura 3: Buscador desde la línea de comandos.
Y ahora llega el momento que estábamos esperando, cuando todas estas técnicas e ideas se ponen juntas y aparece algo útil. Básicamente lo que hace nuestra aplicación es crear un objeto GUI. Éste se encarga de crear y vincular la acciones que los widget requieren. Una vez creadas, es necesario invocar el método arranca() que ejecuta el bucle principal de Tk. Este bucle se dedica a repintar la ventana y gestionar los eventos. El encargado de buscar en la R.A.E. una palabra a través del botón “Buscar” es el método busca_palabra, ejecuta lynx… con las opciones necesarias y con el contenido del campo de entrada. Lo hace a traés de popen2. Cuando está listo el texto, borra el contenido del widget de texto e inserta en él el texto devuelto por el servidor HTTP de la R.A.E.. Cada vez que se hace esto, la aplicación queda bloqueada como resultado de la invocación a popen2, que bloquea a nuestra aplicación hasta que termine de ejecutarse lynx…. Para evitar este problema se deben emplear hebras, pero eso está fuera del alcance de éste artículo. Cuando se pulsa el botón “Salir” la ■ aplicación acaba.
de Ingeniería Técnica en Informática de Sistemas. Lleva 7 años usando y desarrollando software libre y, desde hace dos, se está especializando en FreeBSD. Pedro Orantes está cursando 3º de Ingeniería Técnica en Informática de Sistemas.
www.linuxmagazine.com.es
Número 03
53
ADMINISTRACIÓN
Charly
Vigilancia con movimiento
Gente Pez Los sistemas comerciales del vigilancia son caros y normalmente involucran acuerdos de mantenimiento. Yo creo que debe haber una alternativa de bajo coste. POR CHARLY KÜHNAST
SYSADMIN Autopsy............................................55 En esta segunda parte dedicada a las auditorías de seguridad, vemos como diseccionar un equipo cuya seguridad ha sido comprometida con el paquete Autopsy.
Suspend ..........................................59 Vemos como poner un equipo en modo hibernación, volcando el contenido de la memoria al swap con el paquete Software Suspend.
54
Número 03
ésta difiere de la anterior con un número de pixeles configurable. El siguiente comando es el único que necesité usar para utilizar esta función: motion -t /home/charly/motion El parámetro -t indica a Motion donde debe almacenar las imágenes. Ahora, cuando paso delante de la cámara Web, los altavoces del PC emiten un sonido de alerta. Motion ha detectado el cambio en la imagen. Si preferimos omitir el sonido de alerta debemos añadir -Q al comando. Si queremos que Motion se ejecute en modo demonio añadiendo el parámetro -D, el sonido esta deshabilitado por defecto.
Cuando las Películas Aprenden a Contar Si necesitamos ajustar a medida Motion debemos tocar el archivo opcional de configuración. El archivo puede residir bajo /usr/local/etc/ o en nuestro directorio raíz. El archivo de configuración nos permite ajustar la sensibilidad de la función de detección de la imagen. La entrada threshold 1500
Estipula que al menos 1500 pixeles deben cambiar de una imagen a otra antes de que Motion detecte el cambio. Mis peces de pelea Siameses son muy valientes pero muy pequeños, por lo que dejé el valor en la mitad. Esperando y contemplando, Motion reacciona cada vez que un pequeño pez de 3 centímetros o más nada delante de la cámara Web. Si nuestra distribución Linux dispone de codificador MPEG podemos incluso hacer que Motion nos genere una película a partir de una serie de imágenes fijas (por ejemplo, ffmpeg proporciona soporte directo para esta aplicación). Motion.cgi [2] hace que el uso de Motion
www.linuxmagazine.com.es
Figura 1: una pez de pelea Siamés [3] nadando felizmente en la imagen de la cámara Web de Charly. Recogido por Motion.cgi.
sea incluso más sencillo. El paquete opcional incluye un interfaz para comenzar, detener y grabar con Motion. Incluso nos permite picotear en el flujo de datos en cualquier momento para ver una imagen real en vivo como la que aparece en la figura 1, que muestra los habitantes de mi pecera. Debemos saber que la cámara que usemos puede ser determinante en los resultados que Motion nos dé. Mi vieja cámara Web fue útil mientras la habitación tuvo luz suficiente, pero inútil en la oscuridad. Como no creo que los ladrones entren en la tienda de Olli y Melanie para encender la luz y sonreír a la cámara, parece lógico que mis amigas inviertan en una nueva cámara Web. ■
INFO [1] Motion:http: //www.lavrsen.dk/twiki/ bin/view/Motion/WebHome [2] Motion.cgi: http://www.lavrsen.dk/twiki/ bin/view/Motion/MotionCGI [3] A fish: http://www.fishbase.org/Country/ CountrySpeciesSummary. cfm?Country=Malaysia&Genus=Betta&S pecies=splendens
EL AUTOR
O
lli y Melanie, que son dos buenas amigas mías, tienen tres tiendas. Una de las tiendas ha sido robada muchas veces. Por supuesto que hay seguros para cubrir los robos. sin embargo ellos estaban preocupados porque nadie había sido capaz de detener a los culpables. Se preguntaban si un sistema de vigilancia podía ayudar. Por supuesto que los sistemas de vigilancia llave en mano son caros, por lo que me han preguntado si un viejo PC y una cámara Web pueden ser una alternativa. Actualmente yo tengo una cámara Web, pero sólo la he usado para grabar el acuario que tengo en mi salón. No tengo ninguna experiencia con aplicaciones de vigilancia. Pero menos mal que existen los motores de búsqueda, ¿verdad? Tras una breve investigación encontré rápidamente una aplicación muy útil llamada Motion [1]. Motion es fácil de instalar. En mi máquina de ensayos Debian, elegida simplemente porque tenía una cámara Web instalada, solo fue necesario escribir apt-get install motion Los usuarios con otras distribuciones pueden usar RPM o archivos tar. Motion accede a dispositivos V4l o V4L2, en este caso mi cámara Web, comparando la imagen actual con la imagen previa. El programa almacena la imagen actual si
Charly Kühnast es un gestor de sistemas Unix en el centro de datos Moers cerca del Rhin, el famoso río alemán. Sus tareas incluyen la seguridad y disponibilidad del cortafuegos y ocuparse del DMZ (zona desmilitarizada).
Autopsy / Sleuthkit
ADMINISTRACIÓN
Autopsy y Sleuthkit, Kit de Herramientas para el Forense Digital
Tras la Pista del Zorro S
leuthkit busca en los sistemas de ficheros de Microsoft y Unix ficheros borrados y reconstruye los hechos para localizar una intrusión. Autopsy Forensic Browser [1] no es sólo fácil de usar, sino que también proporciona funciones avanzadas: este interfaz basado en web de Sleuthkit facilita y documenta el proceso de análisis forense.
Nuevos Casos Basaremos nuestros ejemplos en el sistema de ficheros Forensic Challenge [3]. El tarball contiene la partición individual como aparece descrita en la Tabla 1. Antes de empezar la investigación con Autopsy y Sleuthkit, los investigadores forenses tienen que abrir un nuevo caso. Para hacerlo, simplemente hay que hacer clic en el botón New Case al pie de la página de bienveni-
Para determinar si un sistema está expuesto, el administrador tiene que buscar señales reveladoras y pruebas seguras, el administrador se convierte en un científico forense. Sleuthkit y Autopsy pueden ayudar con esta complicada tarea haciendo uso de una práctica interfaz Web para buscar archivos borrados y descubrir la pista de los intrusos. POR RALF SPENNEBERG da de Autopsy. Haciéndolo, se abre la página de entrada para el nuevo caso (véase la Figura 2). Una vez que se hayan rellenado todos los campos y pulsado New Case, Autopsy creará el directorio del caso (/var/morgue/forensic_challenge/) y el fichero de configuración (/var/morgue/forensic_challenge/case.au t), además de añadir al investigador. La herramienta muestra los resultados en otra página Web y le pide que lo confirme pulsando OK. En la siguiente ventana (Case Gallery, Figura 3), Autopsy presenta una lista de casos seleccionables; incluso se puede acceder a esta página desde la página de bienvenida pulsando el enlace Open Case. El caso forensic_challenge está seleccionado por defecto; después de hacer clic en OK para confirmar la selección, es el momento de añadir las máquinas que se desean investigar en este caso.
Bajo la lupa Para añadir un nuevo host hay que especificar el nombre de la máquina y opcionalmente se puede añadir una descripción, adicionalmente se puede indicar el huso horario y la desviación del reloj del ordenador con respecto al tiempo real, si fuera necesario. También se puede especificar, si se tiene, una base de datos hash de ficheros benignos o malignos. A continuación hay que pulsar Add Host y Autopsy mostrará de nuevo una página de confirmación. Púlsese OK para aceptar.
A continuación se muestra la Host Gallery, permitiendo seleccionar los hosts que van a ser procesados; otra vez hacemos click en OK para confirmar antes de continuar añadiendo las imágenes de disco. Para ello, hay que seleccionar Add Image y teclear el nombre del fichero (véase la Figura 4). Este formulario se utiliza también para especificar si Autopsy debe añadir un enlace simbólico para el fichero original en el directorio morgue o si la imagen debe ser copiada o movida. También hay que especificar el punto de montaje original, el tipo de sistema de ficheros y las opciones MD5. Autopsy calcula la suma de verificación MD5 en cada caso; si ya conoce cual debería ser dicho valor, se puede introducir aquí, para que Autopsy lo verifique con el valor de real.
Registro del 7 de Noviembre de 2000 Ahora se puede continuar con la investigación de la escala temporal de las modificaciones del sistema de ficheros seleccionando el elemento del menú File Activity Time Lines. Haciéndolo se cambia la apariencia de la aplicación Web, dividiendo la ventana en dos marcos. El marco
Tabla 1: Particiones de Challenge Partition
Filesystem
/dev/hda8
/
/dev/hda1
/boot
/dev/hda6
/home
/dev/hda5
/usr
/dev/hda7
/var
/dev/hda9
swap
www.linuxmagazine.com.es
Número 03
55
ADMINISTRACIÓN
Autopsy / Sleuthkit
Figura 3: Autopsy organiza las investigaciones forenses en casos. Esto permite cambiar de caso sin tener que reiniciar la GUI.
A continuación Autopsy crea la Figura 2: Hay que especificar el nombre del nuevo caso (forensic_challenge en línea temporal nuestro ejemplo) y añadirle un login para el investigador responsable para basada en el este caso (ralf). fichero “body”. El elemento del superior muestra los pasos típicos como menú Create Timeline indica con prulos elementos del menú y el marco inferior dencia que se restrinja la ventana de se usa para las entradas y las salidas. tiempo que se va a investigar. La Figura 5 muestra como crear el llaLa descripción de Forensic Challenges mado fichero de “body” usando el eleindica que el 7 de Noviembre del 2000 es la mento del menú Create Data File. Este fecha más probable de la intrusión. Para proceso puede tardar un poco, ya que este ejemplo, el investigador querrá Autopsy tiene que invocar los comanrestringir la ventana del tiempo para detados fls e ils de Sleuthkit. Después de llar de forma más precisa las investigacompletarse estos pasos, Autopsy ciones en el período entre el 7 y el 9 de automáticamente calcula las sumas de Noviembre de 2000. Para permitir a comprobación MD5 que se utilizan Autopsy reemplazar el UID y el GID con los para comprobar la integridad de los nombres correspondientes cuando se cree ficheros. la línea temporal, hay que establecer la
imagen del sistema de ficheros que contenga los ficheros /etc/passwd y /etc/group. La línea temporal muestra que el fichero /etc/hosts.deny ha sido modificado, reduciendo su tamaño a 0 bytes. Unos pocos minutos después, un fichero tarball fue instalado en el directorio /usr/man/.Ci/ (véase la Figura 6). Este es el directorio en el que el investigador forense querrá concentrarse después. Unos pocos segundos antes de que esta instalación tuviera lugar, el inodo 8 133 en hda8 fue borrado. El tamaño del fichero era de 2.129.920 bytes, y pertenecía a un usuario llamado drosen. Un fichero en el rootkit fue borrado después, el fichero en el inodo 109.801 con un tamaño de 1.153 bytes. La línea temporal también muestra los accesos de lectura a las bibliotecas de
Instalación y ejecución de Autopsy Autopsy no sólo realiza análisis, sino que también ayuda al investigador a realizar las tareas de papeleo que el análisis forense conlleva, organizando las tareas en casos y asignándole un directorio a cada uno. Es una buena idea crear un directorio padre para los directorios de los casos antes de empezar con el proceso de instalación: /var/morgue es un buen nombre para el almacén de pruebas. La instalación de Autopsy es algo extraña. Después de ejecutar make, hay que contestar una o dos preguntas. El script de instalación comprueba si una versión de Sleuthkit está instalada antes de crear los ficheros de instalación. Cuando se lanza la herramienta, tecleando ./autopsy en el directorio
56
Número 03
fuente, el Autopsy Forensic Browser se activa mostrando su número de versión, una URL y
un mensaje indicando que se debe dejar este proceso ejecutándose durante la fase de análisis y que hay que pararlo cuando termine dicha fase pulsando [Crtl]+[C].
Figura 1: Tecleando make se compila e instala Autopsy, pero hay que estar preparado para contestar algunas preguntas. Tiene sentido crear el directorio morgue antes de empezar la instalación.
www.linuxmagazine.com.es
A continuación, con cualquier navegador Web, se puede acceder a Autopsy. Tan sólo hay que introducir la URL mostrada anteriormente en el cuadro de texto de la barra de direcciones del navegador Web. También se pueden usar opciones de la línea de comandos para indicarle a Autopsy que se ejecute en otro puerto y dirección IP: ./autopsy <número de puerto> <dirección IP>. Si se prefiere usar los paquetes RPM del autor [2] para instalar Autopsy, en vez de usar los fuentes, se dará cuenta que autopsy se incluye en el path por defecto. Este paquete usa /var/morgue como almacén de pruebas.
Autopsy / Sleuthkit
ADMINISTRACIÓN
Figura 5: Autopsy crea un fichero “body” para almacenar la línea temporal para las operaciones sobre el sistema de ficheros de la imagen. El “body” se puede aplicar tanto a los ficheros borrados como a los existentes.
poral. A lo largo derecha Close) y seleccionar la partición del curso del /usr. Tras confirmar pulsando OK se gador ha de añadir la imagen al caso, especificando la suma de control MD5 ataque, parece muestra una nueva vista, donde hay que para asegurarse que la imagen no esté dañada. que el intruso seleccionar File Analysis. Este es el sitio dejó una copia donde se pueden mostrar los ficheros funciones. Este hecho indica que el del cliente “Bitch X IRC” y “eggdrop” en individuales, como el llamado intruso compiló una o varias aplicael disco. /usr/man/.Ci/install (véase la Figura 7). ciones. Ahora la tarea del administradorProcesos Ocultos detective consiste en descubrir la natuNingún Punto para Encubrir raleza y el propósito de los ficheros Afortunadamente, Autopsy también Pistas instalados. Los scripts de instalación son permite el visionado de otros tipos Después de completar la instalación el siempre un buen punto de partida. El de ficheros. Por ejemplo, intruso borró una enorme cantidad de intruso los ha borrado, pero Autopsy no /usr/man/.Ci/addps contiene un script ficheros. Parece que estos ficheros tiene ningún problema en recuperarlos. que obviamente ha sido usado para oculfueron creados como parte del proceso Para recuperarlos, primero hay que tar procesos que normalmente se muesde compilación. Tras borrar los ficheros cerrar la línea temporal (arriba a la tran con los comandos ps o top para de superfluos, el intruso parece que instaló una Listado 1: Instalación de SSH distribución SSH (véase el Listado 1). 01 537 m.c -/-rw------- root root 26570 /etc/ssh_host_key La línea temporal tam02 880 .a. -/-rw-r--r-- root root 26579 /etc/ssh_config bién indica que el intruso 03 512 m.c -/-rw------- root root 2048 /root/.ssh/random_seed usó scripts de instalación 04 341 mac -/-rw-r--r-- root root 26578 /etc/ssh_host_key.pub para tomar el control e 05 ... instalar software. Dicha 06 604938 mac -/-rws--x--x root root 109999 /usr/local/bin/ssh1 línea contiene un número de entradas que indican el borrado de ficheros Listado 2: Scripts de Instalación que nos hace mant e n e r esta hipótesis: 01 1153 ..c -/-rwxr-xr-x 1010 users 109801 /usr/man/.Ci/install-sshd1 (deleted) install-sshd1 y parecidos 02 1076 ..c -/-rwxr-xr-x 1010 users 109802 /usr/man/.Ci/install-sshd (deleted) (véase el Listado 2). 03 80 .a. -/-rwxr-xr-x 1010 users 109803 /usr/man/.Ci/install-named (deleted) Los ficheros mostra04 71 ..c -/-rwxr-xr-x 1010 users 109867 /usr/man/.Ci/install-wu (deleted) dos aquí no son las úni05 106 ..c -/-rwxr-xr-x 1010 users 109864 /usr/man/.Ci/install-statd (deleted) cas entradas sospe06 ... chosas de la línea temFigura 4: Antes de investigar una imagen del sistema de ficheros, el investi-
www.linuxmagazine.com.es
Número 03
57
Autopsy / Sleuthkit
ADMINISTRACIÓN
este modo evitar ser detectados. El atacante parece que ha reemplazado los comandos estándar del rootkit por variantes. El contenido del fichero es el siguiente: #!/bin/sh HIDE=$1 echo "hiding $HIDE from ps/top" /bin/echo "2 $HIDE" >>/dev/ptyp
Los comandos ps y top modificados leen /dev/ptyp con el objetivo de ocultar estos procesos. El fichero contiene las siguientes entradas: 2 slice2 2 snif 2 pscan 2 imp 3 qd ...
Figura 6: Reconstrucción de Autopsy de un rootkit. Las columnas contienen las fechas y horas, tamaños, acciones (a para access, m para modify), privilegios, UID, GID, número de inodos y nombres de los ficheros en cuestión.
El análisis del comando ps con strings o con la interfaz Autopsy, muestra que este comando contiene la cadena /dev/ptyp. Esto demuestra nuestra hipótesis previa, ya que la versión original del comando ps no lee este archivo.
Troyanos El servidor SSH instalado por el atacante es otro fichero interesante. /usr/local/sbin/sshd contiene una referencia a /usr/tmp/nap. La referencia es fácil de localizar. Tan sólo hay que mirar al carácter separador /. /usr/tmp es un enlace simbólico a /var/tmp. El fichero /var/tmp/nap contiene la siguiente información: username: root password: U tw1Lightz0ne hostname: U c871553-b.jffsn1.mo.home.com
En otras palabras, el servidor SSH instalado por el intruso almacena cualquier contraseña que recibe en formato texto.
Funciones Avanzadas Autopsy proporciona un número adicional de funciones, tales como búsquedas de palabras claves, clasificación de ficheros por tipo y acceso directo al contenido de los ficheros. Una de las mayores ventajas de usar Autopsy es la posibilidad de calcular las sumas de control MD5 al vuelo y de añadir comen-
58
Número 03
Figura 7: El módulo de análisis de ficheros de Autopsy permite mostrar cualquier fichero del sistema de ficheros, incluso los borrados (resaltados en rojo). El panel inferior de la derecha muestra el contenido del fichero borrado install-named
tarios. Un investigador tiene que ser extremadamente disciplinado para conseguir esta funcionalidad solamente haciendo uso de la línea de comandos. Los desarrolladores de Autopsy están actualmente trabajando en rutinas de búsqueda indexadas para la característica de búsqueda de palabras claves. Tan sólo hay que crear una vez un archivo índice, para acelerar cualquier búsqueda. Una búsqueda que tarda 168 segundos actualmente, tardaría tan sólo 2 segundos con el uso de la nueva técnica.
Conclusión La combinación de Sleuthkit con Autopsy Forensic Browser proporciona
www.linuxmagazine.com.es
un conjunto de herramientas bastante potentes para la realización de análisis forenses. Sus características y servicios son comparables con las herramientas comerciales. El hecho de que sea de código abierto permite a los investigadores seguir el rastro de los progresos ■ de la herramienta en detalle.
RECURSOS [1] Autopsy Forensic Browser: http://autopsy. sf.net [2] Paquetes RPM Autopsy y Sleuthkit: http:// www.spenneberg.org/Forensics/ [3] Ficheros del Desafío Forense: http:// project.honeynet.org/challenge/images. html
Software Suspend
ADMINISTRACIÓN
Trabajando con Software Suspend
Sueño Profundo Casi todas las placas bases tienen la característica de control de energía, diseñada para apagar el ordenador y ponerlo en modo suspendido. En la vida real, esta característica no siempre funciona. Linux tiene varias alternativas para tratar de solucionar el problema. POR SIMON RUTISHAUSER
L
a teoría sobre Software Suspend es sencilla: Linux escribe el contenido de la memoria y otros buffers, como la memoria gráfica, a la partición de swap y luego apaga la máquina. La próxima vez que se encienda el ordenador, Linux comprueba la partición de swap, detecta que el sistema operativo fue apagado, pero de forma diferente a como se apaga normalmente, que se detuvo por Software Suspend y restaura la memoria desde los archivos existentes. Esta forma de actuar ignora la BIOS y su sistema de control de energía, así que no hay por qué preocuparse por los errores de la BIOS. Esto es una buena noticia para los usuarios cuyos ordenadores no soportan la suspensión interna APM o ACPI. En un mundo perfecto, Software Suspend funcionaría perfectamente ¿no sería maravilloso que la vida fuera así de simple? El gran obstáculo para el sistema operativo es la captura de los datos de la memoria. Para hacerlo, Linux tiene que lanzar un nuevo proceso que cambia el contenido actual de la memoria. En otras palabras, el sistema tiene que estar en un estado tan estable como sea posible antes de ponerlo a dormir. Y hay algunos drivers que se niegan a cooperar (por ejemplo, los adaptadores gráficos de NVidia y ATI).
Tres sistemas diferentes En el momento de escribir este artículo, hay disponible tres soluciones diferentes de Software Suspend. Todas ellas originadas por el mismo proyecto y basadas las tres en el mismo principio. Software Suspend (Swsusp), la original, está implementada en el kernel 2.6,
que elimina la necesidad de instalarlo. Como inconveniente, necesita de una BIOS ACPI compatible. El proyecto PMDisk fue una de las ramas en las que se dividió swsusp para añadirle unas pocas mejoras. PMDisk está también en el kernel 2.6. La ventaja que PMDisk ofrece es que no necesita ACPI. El equipo del kernel mezcló los avances realizados por los dos proyectos bajo el nombre original Swsusp [1]. Software Suspend 2 (Swsusp2) [2] es otra mejora a la versión Swsusp. Como PMDisk, no necesita una BIOS con el sistema de control de energía y tiene algunas características extra. Por ejemplo, ahorra espacio comprimiendo el archivo de memoria. En vez de usar la partición de swap, puede usar un archivo de swap en la partición de datos. Además, Swsusp2 funciona con sistemas multiprocesadores. El reverso de la moneda es que Swsusp2 no está incluido en el kernel y por lo tanto hay que parchearlo y recompilarlo manualmente. La pregunta es: ¿Cuál de estos tres sistemas de Software Suspend es la elección correcta para usted? Las integradas en el kernel son sin duda las opciones más sencillas, ya que eliminan las tareas de parchear y recompilar. Sin embargo, como ninguno de los tres sistemas está realmente maduro, podría darse el caso que el que más le guste de los tres no soporte su hardware; así que el proceso entero implica seguir el proceso de la prueba y error. Los tres sistemas de Software Suspend suponen que su partición de swap es lo bastante grande. Dos veces la cantidad de memoria RAM proporcionará un margen suficiente de seguridad.
Afortunadamente, el ordenador no se colgará si se queda sin espacio, sino que simplemente debería salir del proceso de suspensión.
Sofware Suspend, el original El kernel 2.6 incluye swsusp por defecto, pero no todas las distribuciones tienen habilitada la opción en el kernel que suministran. Suse y Mandrake habilitan swsusp, mientras que los usuarios de Debian y Fedora tendrán que empezar a preparar sus compiladores. Hay que habilitar la opción CONFIG_SOFTWARE_SUSPEND bajo Power management options (ACPI, APM) y recompilar el kernel. Nótese que swsusp necesita ACPI. También es necesario añadir un parámetro al cargador del sistema. Suponiendo que se tenga instalado grub, que es el cargador estándar actual para Suse y la mayoría de las distribuciones, se necesita editar el archivo /boot/grub/menu.lst. Localizar la línea del kernel que esté utilizando y añadir resume=/dev/hdaX sustituyendo /dev/hdaX por la partición de swap, por ejemplo /dev/hda6. Puede teclear fdisk -l /dev/hda | grep swap para identificar la partición swap de su sistema. Para no cometer errores y curarse en salud, copie la entrada completa y cree una entrada nueva en la lista del menú de arranque. Asígnele un nombre diferente a esta entrada, por ejemplo, poniéndole noresume en la línea título. Ahora borre el parámetro resume en la línea kernel de la nueva entrada y añada pmdisk=off noresume noresume2. Esta entrada le permitirá reiniciar la máquina si falla el arranque tras haber entrado en
www.linuxmagazine.com.es
Número 03
59
ADMINISTRACIÓN
Software Suspend
modo suspendido. Después de completar los cambios, el contenido de /boot/grub/menú.lst debe ser como el mostrado en el Listado 1. La primera entrada es la que necesitamos cuando rearrancamos (esta es la entrada del Linux SuSE de nuestro laboratorio). La entrada arranca el ordenador de forma normal y lo reanuda después de haber sido suspendido. La segunda entrada, SuSE Linux noresume, es nuestro salvavidas en caso de que algo vaya mal. Swsusp no necesita en realidad las opciones pmdisk=off y noresume2; hacen lo mismo que noresume para los otros dos sistemas de Software Suspend. En Suse, el programa powersave manejará el ahorro de energía por defecto, y no swsusp. Para cambiarlo, hay que localizar el archivo /etc/powersave.conf y cambiar la entrada POWERSAVED_DISABLE_USER_SUSPEND de yes a no. Sólo en el caso de que las cosas vayan mal, tiene sentido entrar en el modo monousuario; así que habrá que introducir init 1. Ahora tan sólo hay que teclear la clave del root para poner la máquina en modo suspendido. En Suse hay que teclear /etc/init.d/powersaved start para lanzar el servicio powersave y luego escribir powersave --suspend. En otras distribuciones sólo con teclear el comando: sync && echo 4 > /proc/acpi/sleep es suficiente. Si esta prueba funciona, habrá que probar los runlevels, empezando con el modo multiusuario sin GUI (init 3). Los
Listado 1: Grub Menu List 01 title SuSE Linux 02 kernel (hd0,1)/boot/ 03 vmlinuz root=/dev/hda2 vga=791 04 resume=/dev/hda6 05 initrd 06 (hd0,1)/boot/initrd 07 08 title SuSE Linux 09 noresume 10 kernel 11 (hd0,1)/boot/vmlinuz 12 root=/dev/hda2 vga=791 13 pmdisk=off noresume noresume2 14 initrd 15 (hd0,1)/boot/initrd
60
Número 03
usuarios de Debian tendrán que usar init 2; hay que parar manualmente el servicio de login gráfico tecleando /etc/init.d/kdm stop, suponiendo que se esté usando KDM. Si este test también funciona, teclee init 5 y repita el proceso con el GUI; los usuarios de Debian pueden lanzar el servicio de login tecleando /etc/init.d/kdm start. Si está usando el GUI sin aplicaciones que consuman mucha memoria, el ordenador debería tardar entre 10 o 20 segundos en suspenderse y entre 30 y 40 segundos en volver a activarse. Estos tiempos pueden variar dependiendo de la velocidad del ordenador y de cuanta memoria esté usando en el momento de entrar en el modo de suspensión.
PMDisk Como swsusp, PMDisk fue presentado en la versión 2.6 del kernel. La diferencia más importante entre el proyecto PMDisk y swsusp es que PMDisk no necesita ACPI, lo que es una buena noticia para los ordenadores que usen APM. PMDisk tabién funciona a veces en máquinas que tienen ACPI pero no entran en modo de suspensión usando swsusp. Como PMDisk es un pariente cercano de swsusp, apenas hay diferencias en la forma de usar los programas. La mayoría de las distribuciones del kernel tienen la opción requerida activada por defecto. En Debian, hay que habilitar CONFIG_PM_DISK y recompilar el kernel. Luego, hay que editar el archivo del gestor de arranque, /boot/grub/menu.lst, igual que se hizo para swsusp, pero usando pmdisk=/dev/hdaX en vez de la opción resume: title kernel
initrd
SuSE Linux (hd0,1)/boot/U vmlinuz root=U /dev/hda2 vga=U 791 pmdisk=U /dev/hda6 (hd0,1) U /boot/initrd
Añadésele por seguridad pmdisk=off tal y como se describió en la sección de swsusp. Ahora se puede teclear sync && echo -n "disk2 > /sys/power/state para habili-
www.linuxmagazine.com.es
tar PMDisk. El comando sync se incluye por razones de seguridad; almacena los datos en un archivo temporal del sistema, por si el ordenador se cuelga cuando se habilite PMDisk.
Software Suspend 2 Software Suspend 2 [2] está también basado en el Software Suspend original, aunque tiene nuevas características. En vez de escribir en la partición de la swap, Software Suspend 2 puede almacenar los datos de memoria en el sistema de ficheros; comprime los datos antes de almacenarlos y soporta sistemas con múltiples CPU y con más de 1 Gigabyte de RAM. Swsusp2 puede manejar incluso particiones swap encriptadas. Software Suspend 2 incluye algunas características avanzadas bajo el ala. Por ejemplo, swsusp2 usa los llamados “freezers”, que soportan una ejecución mejorada del proceso de hibernación. Además, el programa elimina los datos superfluos de la memoria caché para ahorrar espacio en la partición swap. Desafortunadamente, Software Suspend 2 no ha sido incluido en el kernel oficial 2.6. Para usar swsusp2, se necesita aplicar un parche al código fuente del kernel y recompilarlo.
Parcheando el kernel Los parches del kernel para Software Suspend 2 están disponibles en el sitio web [2]. Allí se encontrarán las últimas versiones, además de las antiguas. Las distribuciones que usan kernels modificados pueden presentar algunos problemas, ya que las distribuciones específicas a menudo entran en conflicto con el parche swsusp2, así que será mejor que se pruebe en un kernel sin alterar. La siguiente descripción se basa en la versión 2.6.8.1 del kernel. Conectados como root, hay que entrar en el directorio /usr/src y descomprimir el kernel tecleando tar xjf linux-2.6.8.1.tar.bz2. Luego hay que introducir tar xjf sotware-suspend-2.0.0.105.tar.bz2 para descomprimir el parche swsusp2. Ahora es el momento de aplicarle el parche al kernel. Para ello, hay que entrar en el directorio /usr/src/linux-2.6.8.1/ y teclear ../software-suspend-2.0.0.105-for-2.6.8.1/apply . El script da la opción de añadir algunos
Software Suspend
Figura 2: Configuración del kernel para Software Suspend 2.
extras. La mayoría de estos extras son innecesarios, por lo que típicamente se acepta la configuración por defecto presionando [Enter]. Si todo ha ido bien la salida mostrada debería ser similar a la que aparece en el listado 2. El siguiente paso es configurar el nuevo kernel. Para usar las opciones actuales, hay que copiar el fichero de configuración del kernel actual al directorio del nuevo kernel escribiendo cp /boot/config-X /usr/src/linux-2.6.8.1/.config. Hay que asegurarse de reemplazar la X por el nombre de la versión actual del kernel. Después hay que continuar modificando la configuración de manera que se ajuste a sus necesidades. Si se tienen instalados los paquetes ncurses-devel o ncurses-dev, tecleando make menuconfig se mostrará un sistema de configuración basados en menú en modo texto. Hay que usar las flechas del teclado y la tecla [Enter] para navegar por los elementos. Se selecciona la entrada de menú Power management options (ACPI, APM) y se desabilita Software Suspend (EXPERIMENTAL) y las entradas Suspend-toDisk Support presionando la tecla [n]; estas entradas son para el otro sistema de suspensión software. Bajo estas entradas, debería verse el menú Software Suspend 2. Hay que presionar [y] en las entradas Software Suspend 2, Swap Writer, LZF image compresion, Text mode console support y Compile in debugging output para habilitarlas. La última de estas opciones proporciona mensajes de depuración más detallados (Cuadro 1) y puede ser útil en situaciones en las que se presenten problemas. Suponiendo que no se desee modificar nada más, hay que presionar tres veces [Alt+e] para salir del configurador del kernel.
Para recompilar el kernel recién configurado hay que introducir make bzImage && make modules modules _install. Dependiendo de la velocidad del microprocesador y la configuración, esto puede tardar unas cuantas horas. Cuando haya concluido, hay que copiar el nuevo kernel al directorio de arranque /boot/: cp arch/i386/boot/bzImage /boot/vmlinuz-suspend2. A continuación teclee mkinitrd para crear un disco ram inicial para el nuevo kernel; es decir, a menos que haya recompilado todos los drivers que se necesitan para leer el sistema de ficheros raíz en el nuevo kernel. Se necesita introducir una nueva entrada en el gestor de arranque para que arranque el nuevo kernel; si se está usando grub, añádase las siguientes líneas a /boot/grub/menu.lst, asegurándose que se modifica la partición de modo que refleje la configuración de su sistema: title
SuSE Linux - U SoftwareSuspendU 2.0.0.105
Listado 2: Salida del script Software Suspend 2 01 /usr/src/linux-2.6.8.1 # ../software-suspend-2.0.0.105for-2.6.8.1/apply 02 Apply KDB patches (for serious debugging capabilities) [yN]? 03 Apply Bootsplash patches (includes bootsplash.org patch) [yN]? 04 Apply Win4Lin support patches [yN]? 05 Applying 20-software-suspend-linux-2.6. 8.1-rev1-whole ... 06 Applying 21-software-suspend-linux-2.6. 8.1-rev2-incremental ... 07 Applying 21-software-suspend-linux-2.6. 8.1-rev3-incremental ... 08 Applying 30-software-suspend-core-2.0.0 .104-whole ... 09 Applying 31-software-suspend-core-2.0.0 .105-incremental ... 10 All happy!
ADMINISTRACIÓN
kernel
(hd0,1)/boot/ U vmlinuz- U suspend2 root= U /dev/hda2 vga=791 U resume2=swap: U /dev/hda6 initrd (hd0,1)/boot/ U initrd-suspend2
Nuestro ejemplo usa la partición /dev/hda2 como el sistema de ficheros raíz. En la jerga de grub, está partición se referencia como hd0,1, donde hd0 es el primer disco duro, es decir, hda, y el 1 que le sigue a la coma se refiere a la segunda partición, es decir, hda2. La partición swap está ubicada en /dev/hda6. Se está usando la convención de Suse para los nombres de las entradas del menú, aunque se puede escribir lo que se quiera en la línea del título (title). Si se sigue el ejemplo, se debería tener una entrada denominada Suse Linux Software Suspend 2.0.0.105 en el menú de arranque cuando se inicie el nuevo kernel.
Configuración del Script Hibernate El sitio web de Software Suspend [2] también proporciona el paquete Hibernate. Hibernate contiene los ficheros de configuración y el script hibernate, que inicia el modo de suspensión. Entrando como root, tecléese rpm -Uvh hibernate-0.98-1.i386.rpm para instalarlo; en Debian hay que teclear dpkg -i hibernate-0.98-1_all.deb. Se necesita echar un vistazo al script de configuración de Hibernate en /etc/hibernate/hibernate.conf para asegurarse que Software Suspend 2 funcionará tal y como se espera que funcione. En la mayoría de los casos se puede dejar la configuración por defecto. Pero podría ser necesario añadir las siguientes líneas: RestartServices hotplug StopServices alsasound StartServices aumix LeaveXBeforeSuspend yes
La línea RestartServices hotplug le dice al script que pare el servicio hotplug antes de suspenderse y que lo reinicie después de que se despierte; esto asegura que los
www.linuxmagazine.com.es
Número 03
61
ADMINISTRACIÓN
Software Suspend
dispositivos tales como ratones USB y teclados funcionarán bien una vez despertados. Las siguientes dos líneas detienen el sistema de sonido antes de suspenderse y restaura el nivel de volumen después de despertarse. Por último, LeaveXBeforeSuspend le indica al sistema que se pase a una consola en modo texto antes de suspenderse y que entre de nuevo en la GUI después de despertarse. Sin estas opciones, se experimentarán una serie de anomalías en el sistema de ventanas y el teclado. Una vez realizados estos pasos, es el momento de lanzar el test. Hay que teclear init 1 para entrar en el modo monousuario. Entonces introduciendo hibernate se pasa a modo suspendido. Si todo ha salido bien, el sistema volverá al mismo estado una vez que se haya despertado. Tras compro-
bar que funciona, hay que seguir los pasos indicados anteriormente para lanzar hibernate en modo multiusuario sin la GUI y finalmente con la GUI.
Habilitando Hibernate para los usuarios sin privilegios Se necesitan los privilegios de root para pasar a modo suspendido, aunque los usuarios sin estos privilegios podrían beneficiarse también de esta característica. Para permitir que los usuarios sin privilegios puedan usar las capacidades de suspensión, hay que instalar primero el paquete sudo, si lo necesita (la mayoría de las distribuciones incluyen sudo por defecto). Como root, modifíquese el fichero de configuración /etc/sudoers como sigue:
User_Alias USERS = U simon, whoever Cmnd_Alias HIBERNATE = U /usr/sbin/hibernate USERS ALL=NOPASSWD: U HIBERNATE
Este cambio permite a los usuarios simon y whoever lanzar /usr/sbin/hibernate invocando sudo /usr/sbin/hibernate sin tener que intro■ ducir la contraseña.
RECURSOS [1] El futuro de Swsusp y PMDisk: http:// kerneltrap.org/node/view/3485 [2] Software Suspend 2: http:// softwaresuspend.berlios.de
Cuadro 1:Problemas con Software Suspend Diversas razones pueden impedir que Software Suspend funcione y la mayoría de ellas no son específicas del sistema. Si el proceso suspend se sale sin terminar o la máquina se cuelga, teclee free para comprobar si se tiene espacio suficiente en la partición de swap; será necesario reiniciar para realizarlo. Si el espacio en swap no es el problema, habrá que comprobar los parámetros de arranque para ver si se entra en la partición correcta cuando se despierte. Si la máquina falla a la hora de despertarse el resultado puede ser una partición de swap incorrecta, en este caso la partición no mostrará como free. Para formatearla y activarla de nuevo hay que introducir mkswap /dev/hdaX, seguido de swapon /dev/hdaX. Otra posible fuente potencial de errores son los módulos de bajo nivel del kernel. Para comprobar si éste es el caso, tecléese init 1 para entrar en modo monousuario. Luego habrá que introducir lsmode para mostrar la lista de módulos activos y eliminar tantos como sea posible con el comando modprobe -r. Los sospechosos habituales son los módulos del sonido, USB y AGP. La salida de dmesg después de una suspensión fallida a menudo indica la causa del fallo. Si Software Suspend 2 provoca el cuelgue después de mostrar la barra de progreso en la pantalla, pulsando [Esc] normalmente cancelará el proceso y devolverá al sistema al estado actual. En caso de que dmesg no proporcionara la información necesaria para determinar la causa del fallo, habrá
62
Número 03
que habilitar la función de información de depuración integrada como sigue:
relance el modo suspendido hasta que se encuentre al culpable.
thinkpad:~# cd /proc/software_suspend thinkpad:/proc/software_suspend# echo 3 > default_console_level thinkpad:/proc/software_suspend# echo 1 > log_everything thinkpad:/proc/software_suspend# echo 7 > debug_sections thinkpad:/proc/software_suspend#e echo 1 > pause_between_steps
Desde luego, puede darse la circunstancia de que no se identifique el servicio que esté causando el fallo; en este caso, algún módulo del kernel puede ser el culpable. Con lsmode listando los módulos activos, y como root, empiece a eliminarlos uno a uno con rmmod <nombredelmódulo>.
Luego habrá que introducir el siguiente comando para lanzar el proceso de suspensión: sync && echo 1 > /proc/software_suspend/do_suspend Esto proporciona una pantalla repleta de información, donde habrá que pulsar la tecla de espacio para confirmar cada paso. Armado con estos mensajes individuales, habrá que navegar por la página web de swsusp2 [2] y comprobar el FAQ, el Wiki, la lista de correo y la documentación restante en busca de respuestas. Si Software Suspend funciona en modo monousuario, pero no en el runlevel normal, habrá que intentar averiguar qué servicio es el causante del fallo. Para localizar al culpable, habrá que parar cualquier servicio sospechoso, por ejemplo, tecleando /etc/init.d/alsa stop si se sospecha de alsa. Si este primer intento no funciona, siga parando individualmente los servicios y
www.linuxmagazine.com.es
Si algún elemento hardware, como la tarjeta de sonido o algún dispositivo USB, es el causante del fallo, se puede parar dicho elemento antes de entrar en el modo de suspensión. Como root, deténgase el servicio y elimínese el módulo correspondiente del kernel. Después de despertar al sistema habrá que lanzar el servicio y cargar el módulo usando modprobe. Si resultara imposible cargar el módulo una vez que se haya despertado el sistema, se puede probar a recompilar el módulo dentro del kernel. En el caso de Software Suspend 2, bajar a una versión anterior podría ayudar, ya que el proyecto está aún en desarrollo. La versión 2.0.0.93, en particular, presentó cambios importantes en comparación con las versiones anteriores. Algunos equipos portátiles funcionan mejor después del cambio, pero su hardware podría funcionar mejor con versiones anteriores. Si los problemas persisten a pesar de todas estas pruebas, puede ser que tenga mejor suerte con algunas de las otras implementaciones de Software Suspend: en caso contrario, pruebe a escribir en alguna de las listas de correo.
Bienvenidos a Linux User Ésta es la sección dedicada a la presentación de software interesante y útil que nos ayuda en nuestro quehacer diario con el escritorio Linux. Aquí aprenderemos a utilizar software estándar de una manera más eficiente, adquiriremos valiosos conocimientos y descubriremos apasionantes nuevas aplicaciones.
Herramientas: KHotKeys
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .64 Los gestos con el ratón y los atajos con el teclado añaden velocidad y simplicidad a las operaciones con el PC. Los gestos de ratón solían ser coto privado de los usuarios de Opera y de Mozilla, pero KHotKeys nos los ofrece ahora para Konqueror para usuarios de KDE 3.2 o superior.
Desktopia: KRecipe
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67 No es necesario hacer malabarismos con libros de cocina simplemente para hacer felices a esos amigos que hemos invitado a comer. Krecipes permite a los chefs aficionados a gestionar sus recetas e incluso crear la lista de la compra. Además nos puede ayudar con una dieta si lo necesitamos.
Aplicaciones: KDM/GDM
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .73 Tanto KDE como GNOME disponen de gestores de pantallas.Veremos las características ofrecidas por KDM y GDM y examinaremos como configurar un gestor de pantalla en nuestro sistema Linux.
Programación Básica: XUL (III)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .76 En los primeros capítulos de nuestra serie de XUL hemos estado principalmente mirando los conceptos básicos del lenguaje. A medida que nuestro viaje ha continuado hemos explorado botones, etiquetas y gestión de geometrías, comenzando el mes pasado a conectar funcionalidad a nuestro interfaz.
Educación: WIMS (III)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .81 Con este artículo cerramos la serie que hemos dedicado al servidor de recursos educativos WIMS, recapitulamos su uso en una clase y hacemos lo que creemos que es un interesante y necesario balance pedagógico de la aplicación.
Linea de Comandos: su y sudo
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 Para más seguridad, aunque tenga privilegios de root para un sistema, tiene sentido utilizarlos solo temporalmente para prevenir daños accidentales. su y sudo le permiten cambiar la identidad rápidamente desde la línea de ordenes.
Iniciación a LaTeX (III)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .87 En esta nueva entrega sobre el procesador de textos LaTeX, vemos como crear tablas y fórmulas matemáticas con LaTeX, siendo esta última funcionalidad una de las más espectaculares del compilador tipográfico y uno de los motivos por el cual es tan popular en círculos académicos.
LINUX USER
KTools
Gestos de ratón y atajos de teclado con KHotKeys
Charada Los gestos con el ratón y los atajos con el teclado añaden velocidad y simplicidad a las operaciones con el PC. Los gestos de ratón solían ser coto privado de los usuarios de Opera y de Mozilla, pero KHotKeys las ofrece ahora a Konqueror para usuarios de KDE 3.2 o superior. Incluso podemos lanzar programas no-KDE con KHotKeys. POR KALLE GERWIEN
K
DE es un sistema extremadamente flexible. Los menús contextuales que se despliegan cuando los usuarios presionan en el botón derecho del ratón son tan aplicables como el menú K o los iconos de inicio rápido. Y escondido en las profundidades del centro de control de KDE hay otro interesante programa que permite un uso más flexible de KDE: KHotKeys. Con KhotKeys, el usuario puede asignar combinaciones de teclado a aplicaciones. Incluso podemos usar gestos de ratón para controlar Konqueror (ver cuadro 1). Para lanzar KhotKeys debemos presionar [Alt-F2] e introducir khotkeys o abrir el centro de control y abrir la sección Regional & Accessibility (Regiones y Accesibilidad). Cuando lanzamos KhotKeys aparece un mensaje de advertencia informando de que los cambios realizados pueden ser peligrosos. Este artículo nos proporciona una introducción a algunos simples pero efectivos ajustes con la aplicación KhotKeys. Siempre ayuda ser precavido, pero tendremos pocos temores acerca de estos cambios incluso si somos nuevos. Una
64
Número 03
vez nos acostumbremos a Khotkeys aparecerán nuestras propias ideas de teclas rápidas y gestos que incrementarán la efectividad de nuestro escritorio.
Gestos de Ratón La ventana del programa está dividida en dos paneles. El panel izquierdo tiene unos ejemplos y un gesto de ratón de Konqueror. El panel derecho contiene los ajustes de acciones individuales que están distribuidas en una serie de pestañas. Por defecto KDE habilita los atajos de KHotKeys y Konqueror entiende los gestos del ratón. Si los gestos de ratón no funcionan con nuestra distribución, debemos comprobar la pantalla de bienvenida del centro de control de KDE para ver si realmente tenemos la versión 3.2 o superior. Luego abrimos Global shortcuts (Atajos Generales) en la parte derecha del panel de Khotkeys y quitamos la marca de la casilla Disable KHotKeys daemon (Deshabilitar el demonio KhotKeys. Ver Figura 1) si es necesario. Confirmamos pulsando Apply (Aplicar) y luego cambiamos a la pestaña Gestures Set-
www.linuxmagazine.com.es
tings. Quitamos la marca de la casilla Disable mouse gestures globally (Deshabilitar los Gestos de Ratón en General) y confirmamos pulsando Apply. Los gestos pueden ser habilitados o deshabilitados individualmente. Pulsando en el signo de suma a la izquierda de Konqueror Gestures (Gestos de Konqueror) en el panel de la izquierda revela una lista de gestos comunes que podemos habilitar o deshabilitar según deseemos. Para deshabilitar un gesto de la lista pulsamos sobre el y marcamos la casilla Disable en el panel de la derecha. El panel de la derecha contiene comentarios sobre los gestos existentes. Un comentario describe el movimiento asociado con el gesto. No obstante podemos editar el comentario si no estamos contentos con ellos. Guardamos nuestros cambios pulsando Apply y continuamos probando los gestos del ratón con Konqueror.
Creando nuestros propios gestos KHotKeys nos permite reemplazar gestos existentes o añadir nuestros propios
KTools
LINUX USER
Figura 1: KHotKeys no interpretará los gestos del ratón si el demonio Disable KhotKeys está marcado.
Figura 3: Repetiremos el gesto de ratón tres veces en esta ventana.
gestos. KHotKeys tiene tres gestos posibles para cada acción. Seleccionamos el gestos requerido en el panel Actions y pulsamos en la pestaña Gestures en el panel de la derecha. El panel nos muestra tres campos para tres posibles gestos, si bien normalmente solo el primer campo esta completo. Si pulsamos el botón Edit para los tres primeros campos, KHotKeys abre una nueva ventana. Entonces podemos insertar un nuevo gesto. Debemos asegurarnos de mantener pulsado el botón de la izquierda al arrastrar el gesto, puesto que el botón central está reservado para ejecutar los gestos. Para asegurarnos de que nuestro gesto es único tenemos que realizarlo dos veces. Si los dos gestos son muy poco similares el programa no acepta el gesto y nos solicita repetir el procedimiento. Tras insertar los tres gestos al nivel exigido por KhotKey podemos pulsar OK para almacenar los gestos. El nuevo gesto entonces aparecerá en la segunda ventana con un ID único.
Nuevas funciones Si necesitamos programar una función Konqueror pero no podemos encontrar un ejemplo en el que basarnos, seleccionamos Konqueror Gestures y luego pulsamos New Action (Nueva acción). Esto crea una nueva entrada con ese nombre. En el panel de la derecha escribimos un nombre descriptivo para la acción en Action name (Nombre de la acción). Ahora seleccionamos el tipo de
acción: en nuestro ejemplo de Gesture -> Keyboard input (simple). Esto indica a KHotKeys que debe convertir el gesto realizado en un atajo de teclado. Por ejemplo podemos especificar que nuestro gesto sea interpretado como [Ctrl]+[U] para mostrar el código fuente en un documento HTML Tiene sentido decir que aspecto tiene el gesto como parte del comentario. Ahora cambiamos a la pestaña Gestures, pulsamos Edit y dibujamos el nuevo gesto. Tras completar y este procedimiento pulsamos en la pestaña Keyboard input settings. En la caja Keyboard input especificamos las teclas que deseamos emular. Comprobaremos los atajos del teclado de Konqueror. El elemento View Document Source (ver documento fuente) está localizado en el menú View. Tenemos que escribir el atajo de teclado mostrado para este elemento en la caja Keyboard input. En este caso la entrada correcta es Ctrl+U. Acabamos la programación del nuevo gesto pulsando Apply. El gesto está ahora habilitado y puede ser usado en Konqueror. Podemos seguir el mismo procedimiento para añadir gestos de ratón para todas las funciones que nece-
sitemos. Debemos evitar gestos extremadamente extravagantes, puesto que cuanto más difícil sea el gesto de ejecutar más tiempo necesitamos para ejecutar la función.
Atajos de Teclado Como sugiere su nombre, KHotKeys no solo soporta la programación de gestos de ratón, si no que también puede usar atajos de teclado para lanzar programas o escribir líneas de texto en un editor. Tiene sentido ajustar un grupo de acciones separado para esto. Para hacer esto seleccionamos General Settings y luego pulsamos sobre New Group. Escribimos un nombre para el grupo en la pestaña General. Ahora seleccionamos el recién creado grupo y pulsamos New Action. Queremos que la nueva acción use una tecla rápida para lanzar el programa Kmail. Launch Kmail (lanzar Kmail) es un buen nombre y muy descriptivo. Si usamos un programa de correo diferente elegiremos otro nombre distinto acorde con el mismo. Como tipo de acción, seleccionaremos Keyboard shortcut -> Command/URL simple. Ahora pulsaremos en la pestaña Keyboard
Cuadro 1: Gestos de ratón Opera Software introdujo los gestos de ratón en el buscador de Internet Opera. Opera simplemente buscaba una solución que permitiera a los usuarios realizar las acciones más comunes en un buscador, como Atrás, Adelante o Actualizar sin tener que navegar a través de los menús con el ratón. El resultado fue la introducción de gestos de ratón que no habían sido introducidos por los desarrolladores de Mozilla y Konqueror. Debido a que Konqueror es también un gestor de archivos, los gestos de ratón también pueden ser utilizados para navegar por directorios locales. Los gestos de ratón son tremendamente simples y pasan a ser movimientos naturales tras un breve periodo de tiempo de aprendizaje. Presionamos el botón central del ratón, ejecutamos el gesto con el ratón y soltamos el botón del ratón. Por ejemplo, para volver atrás una página en un buscador (Browser back), gesticulamos una línea desde la derecha a la izquierda (ver figura 2). El gesto es interpretado por Konqueror y el resultado es la acción deseada.
Figura 2: Gestos de ratón comunes.
www.linuxmagazine.com.es
Número 03
65
LINUX USER
KTools
Writes "With kind regards" plus name como el comentario. Ahora cambiamos a la pestaña Keyboard shortcut y elegimos una tecla rápida, por ejemplo [Ctrl]+[Y]. Entonces nos movemos a Keyboard input settings y escribimos todas las teclas que necesitemos presionar como si Figura 4: Separamos cada pulsación del teclado con dos puntos. fuéramos a escribir la frase completa. Debeshort-cut. Deberemos ver un botón lla- mos asegurarnos de separar las pulsamado None (Ninguno). Pulsamos el ciones individuales de teclas con dos botón con nuestro ratón e introducimos puntos (:). La frase que deseamos introel atajo de teclado de nuestra elección, ducir, With kind regards, Joe Public, tenpor ejemplo [Ctrl]+[K]. Si nuestra elec- drá la siguiente apariencia en la caja de ción de tecla rápida ya está siendo datos: usada nos lo indicará KhotKeys. Si no es Shift+W:i:t:h:space:k:i:n:dU así el programa simplemente acepta y ::space:r:e:g:a:r:d:s:,:spaceU muestra la entrada en una lista. Ahora ::return:Shift+J:o:e:U nos movemos a la pestaña :space:Shift+P:u:b:l:i:c: Command/URL Settings y escribimos el programa que deseamos que se lance con KhotKeys. Para Kmail escribimos Tenemos que añadir la palabra clave kmail. Para lanzar Kmail podíamos Shift+ para las mayúsculas. La tabla 1 haber seleccionado K-Menu Entry (sim- muestra más información respecto a ple) en su lugar. Esto escribe entradas teclas de control. de acceso en el menú K.
Control de Menús
Saludos Cordiales Keyboard Shortcut -> Keyboard Input (simple) es un tipo de acción interesante. Nos permite simular pulsaciones de teclas. Usaremos la frase With kind regards, Joe Public (Saludos cordiales, Joe Public) como ejemplo. Es una despedida típica para una carta en un procesador de texto, programa de correo, lector de noticias o editor de texto. KHotKeys nos proporciona la posibilidad de introducir esta frase automáticamente independientemente de la aplicación que estemos usando. Primero creamos una nueva entrada en el grupo de atajos del teclado pulsando en New Action. Podemos llamar a la entrada wkr. Seleccionamos Keyboard Shortcut -> Keyboard Input (simple) como el tipo de acción. Escribimos
66
Número 03
En este ejemplo hemos aprendido como simular pulsaciones de teclas y como usarlas para escribir simples bloques de texto. Es igual de simple simular el acceso a menús en programas. Algunos características de programas están ocultas en submenús, lo que puede ser molesto si las necesitamos habitualmente. Por ejemplo, para acceder a View / View mode / Multicolumn view pulsaríamos [Alt+A] / [Cursor right] / [Cursor down] / [Cursor down] / [Enter]. Podemos dejar que KHotKeys simule estas teclas para acceder a la vista multicolumna con un gesto del ratón o utilizando un simple atajo de teclado. Para hacer esto primero creamos otra entrada Keyboard shortcut -> Keyboard input (simple), le asignamos un atajo de teclado y escribimos un nombre descrip-
www.linuxmagazine.com.es
tivo. Como input del teclado escribimos alt+a:right:down:down:return. Esto nos permite navegar por menús incluso si las funciones no están disponibles vía simples presiones de teclas.
Más tipos de acciones El tipo de acción General nos permite combinar gestos y atajos de teclado. Por ejemplo podemos usar un gesto de ratón
Tabla 1: Teclas de control Función
Comando
Cursor Arriba
up
Cursor Abajo
down
Cursor Izquierda
left
Cursor Derecha
right
Espacio
space
Mayúsculas
shift
Alt
Alt
Intro
return
Punto
Shift+;
para lanzar un programa o una tecla de acceso rápido para apuntar a una tecla de acceso rápido definida por nosotros mismos. Para hacerlo primero creamos una nueva entrada y pulsamos New en la pestaña Trigger para especificar el tipo de activación que deseamos: un atajo, un gesto o una ventana. Entonces especificamos que queremos que ocurra en la pestaña Actions. Podemos elegir entre Command/URL, K-Menu Entry, DCOP Call, Keyboard input y Activate Window. La pestaña Conditions nos permite especificar cuando debe ocurrir esta acción.
Restringiendo Funciones Si hemos añadido muchas funciones propias puede que notemos algunos efectos desagradables. Por ejemplo puede que otro programa use una de nuestras teclas rápidas para otro menú completamente distinto. En este caso debemos habilitar la opción Send to specific window (Enviar a una ventana específica) en la pestaña Keyboard input settings. Añadimos un comentario descriptivo y seleccionamos New | Simple Window. En el siguiente dialogo debemos especificar la ventana del programa. Típicamente esto simplemente implica añadir el nombre del programa como título de la ventana (Konqueror en ■ nuestro ejemplo).
Krecipes
LINUX USER
Gestión de recetas con Krecipes
La Cocina de Cada Día No es necesario hacer malabarismos con libros de cocina simplemente para hacer felices a esos amigos que hemos invitado a comer. Krecipes permite a los chefs aficionados a gestionar sus recetas e incluso crear la lista de la compra. Además nos puede ayudar con una dieta si lo necesitamos. POR FRAUKE OSTER
S
olo tiene un año pero dispone de un gran número de ingredientes: el programa de gestión de recetas Krecipes [1] convierte nuestro ordenador Linux en una útil herramienta para la cocina. El último paquete del programa fue pre-arrancado justo antes de la Navidades del 2003 en la versión 0.4.1. Los tres desarrolladores que trabajan en el proyecto han estado cocinando de verdad desde entonces, esperando arrancar próximamente la versión 0.5. El módulo kdenonbeta CVS, almacenado en los servidores KDE, dispone de un snapshot descragable. Krecipes es poco usual para ser un programa kdenonbeta en el sentido en que ha sido capaz de entenderse con seis idiomas desde la versión 0.4.1. Algunas de las traducciones a estos idiomas no están completas puesto que en algunos casos falta la ayuda en línea, por lo que si el lector desear contactar a los progra-
madores para ofrecer su ayuda, estos estarán encantados de contar con ella.
La Despensa Krecipes almacena las recetas en una base de datos, pudiendo elegirse actualmente entre MySQL [2] y SQLite [3]. PostgreSQL se añadirá más adelante, probablemente conjuntamente con la versión 1.0. El soporte para MySQL y SQLite es correcto, ¿pero qué base de datos es mejor? MySQL es extremadamente complejo y tiene su propio servidor de bases de datos, el cual debe estar ejecutándose para arrancar Krecipes. Si ya disponemos de un servidor de MySQL en nuestro ordenador podemos asignar el gestor de recetas a éste. Si no es así, probablemente prefiramos usar SQLite. Para usar MySQL necesitamos instalar el paquete mysql, el Qt dev(el) y
qt3-mysql de los discos de nuestra distribución. Si el paquete qt3-mysql no está disponible, nuestra única opción es compilar Qt, que creará un plug-in de MySQL para la librería (ver Cuadro 1). No seremos capaces de ejecutar Krecipes con MySQL sin completar estos pasos. Las cosas son más simples si optamos por SQLite, debido a que Krecipes implementa las funcionalidades requeridas por sí mismo. Descargamos el paquete SQLite de Internet [3]. Luego descomprimimos el paquete SQLite, cambiamos el directorio fuente y arrancamos la rutina de configuración: tar xvzf sqlite-2.8.12.tar.gz cd sqlite ./configure
Si esto funciona correctamente, podemos continuar con los pasos de
www.linuxmagazine.com.es
Número 03
67
LINUX USER
Krecipes
Figura 1: MySQL insiste en configurar un usuario de base de datos.
compilación e instalación. Podemos instalar el sistema SQLite introduciendo make install. Esto requiere privilegios de administrador:
Gestor de Recetas Tras configurar la base de datos, los usuarios menos aventureros pueden descargar el código fuente del Krecipes de la página Web del proyecto. Cualquier otra persona puede arriesgarse a acudir a la versión de desarrollo KDE a través de CVS. Sin importar la versión de Krecipes elegida, debemos asegurarnos de que el paquete dev(el) kdelibs esté instalado en nuestro sistema. Si no es así, debemos instalar el paquete apropiado (kdelibs3-devel-version.rpm o similar) de nuestro distribución. Ésta es la única forma de construir programas KDE a partir de sus fuentes. Si estamos usando las fuentes de Krecipes debemos primero descomprimir el archivo tar: tar xvjf krecipes.tar.bz2
Ahora debemos cambiar al directorio krecipes creado y arrancar la herramienta de configuración. La herramienta necesita la ruta al directorio raíz Qt:
Número 03
cd krecipes ./configure -with-qt-dir= /directory
Para instalar escribimos los comandos make y make install. Si optamos por usar MySQL, necesitaremos arrancar el servidor de bases
make su -c "make install"
68
Figura 2: Una configuración de MySQL necesita credenciales de usuario.
de datos. Deberíamos ser capaces de arrancar el servidor MySQL o de ajustar el servidor de forma que se ejecute automáticamente cuando encedamos nuestra máquina. La primera vez que ejecutemos nuestra herramienta de gestión de recetas escribiendo krecipes & en la consola o
Cuadro 1: Compilanción de Qt para Añadir Soporte MySQL Para compilar Qt necesitamos las fuentes de Qt que están disponibles bien en los discos de nuestra distribución o desde el fabricante de Qt,Trolltech [4]. Tras descomprimir el archivo debemos cambiar al directorio con el código fuente de Qt. Usaremos la opción - plugin-sql-mysql para configurar las opciones de las librerías para añadir soporte MySQL a Qt: cd qt-directory ./configure -system-zlib -qt-gif -system-libpng -system-libjpeg plugin-imgfmt-mng -thread -noexceptions -plugin-sql-mysql La opción de la configuración -system-zlib habilita el uso de la librería de compresión zlib en nuestra máquina y las librerías para los formatos de imágenes PNG y jpeg. En lugar de usar una librería para el formato de imagen GIF deberíamos usar la función de Qt -qt -gif, necesitando Qt un complemento para el formato de imagen MNG (“Multiple-Image Network Graphics”). La opción -thread habilita el hilado múltiple de ejecución en programas basados en Qt. La opción de configuración final que necesitamos habilitar por defecto es -no-exceptions, que significa que no debemos esperar control de las excepciones según están definidas por los autores del programa. Como nos muestra el ejemplo, podemos añadir más opciones cuando llamemos el comando. Tras finalizar con los pasos de la configuración debemos continuar con la construcción de la librería Qt y algunas herramientas necesarias para Qt y KDE: make sub-src sub-tools Puede que esto tarde un poco, pero no obstante no hay necesidad de instalar QT tras finalizar.
www.linuxmagazine.com.es
Krecipes
usuario tiene los privilegios requeridos para la base de datos o si hemos dispuesto un administrador de sistema para la base de datos (ver figura 1). Si no seleccionamos ninguna de estas opciones y en su lugar pulsamos Next >, el siguiente diálogo mostrará nuestro actual nombre de Figura 3: Uso de la vista “Find/Edit Recipe” (Encontrar/Editar Recetas). usuario en Linux sin la contraseña. Debemos vía el menú K, aparecerá un asistente introducir la contraseña. Si no, que nos guiará con los ajustes iniciales. Krecipes no se ejecutará por falta de Los usuarios de MySQL tienen dos pasos credenciales del usuario, incluso si adicionales respecto a los usuarios de hemos completado el resto de los pasos SQLite debido a que MySQL necesita un del asistente. El cuadro 2 nos indica usuario de base de datos. como crear un usuario para la bases de Comienzo rápido datos MySQL. En el última cuadro de diálogo, que aparece inmediatamente, Inmediatamente después de que si hemos seleccionado SQLite, el asisaparezca la pantalla de bienvenida el tente nos pregunta si queremos poner asistente nos preguntará por la base de las recetas de ejemplo en la base de datos que deseamos usar. Si optamos datos. No hay que esperar mucho, por MySQL, podremos especificar si el
LINUX USER
puesto que actualmente solo hay cuatro recetas. Debemos cerrar este diálogo para arrancar Krecipes en la típica vista "Find/Edit Recipes" (ver figura 3).
La Receta Adecuada Cada vista del programa tiene una barra de navegación a la izquierda. El resto del área de la ventana es una lista de recetas donde buscarlas. Si estamos buscando un plato específico, puede que prefiramos usar la función de búsqueda, especialmente a medida que la base de datos crezca. Para hacer esto debemos introducir el nombre de la receta en el campo Search: y presionar [Intro] para confirmar. Esto indica a Krecipes que debe mostrar la receta o una lista de todas las recetas posibles. La lista muestra la categoría, el título de la receta y el número de indexado asignado a ésta cuando se creó. Podemos pulsar en los encabezados de las columnas para ordenar la lista por cada uno de los criterios. El menú desplegable a la derecha del campo Search: nos permite restringir la búsqueda a categorías específicas. Las categorías se asignan al introducir las recetas. Un solo plato puede ser asignado a múltiples categorías. Tras encontrar y seleccionar la receta deseada en la lista podemos usar cualquiera de los dos largos botones bajo la lista para abrir o editar la receta. El botón Delete borra las recetas motivo de desengaños culinarios de la base de datos. Por supuesto que necesitamos crear unas pocas recetas antes de poder empezar a borrarlas. El botón New de la barra de herramientas se ocupa de esto. Un fallo provoca un error en la forma de mostrar la caja de diálogo si tenemos Qt 3.3 (ver figura 4). Para quitar este error debemos cambiar el tamaño de la ventana arrastrando la esquina inferior derecha de la ventana.
Nouvelle Cuisine
Figura 4: Necesitamos introducir las recetas.
Hay tres pestañas disponibles para introducir los datos de nuestras recetas. La primera pestaña, Recipe, es para el
www.linuxmagazine.com.es
Número 03
69
LINUX USER
Krecipes
Figura 5: Cambiando de vista.
título de la receta, el nombre del autor y el número de comensales indicado para la misma. El botón + cerca de los campos Authors y Categories abren una caja de diálogo donde podemos seleccionar un autor o categoría. La segunda pestaña es para introducir los ingredientes y las cantidades. Una lista de conocidos ingredientes hace las cosas más fáciles.
Si disponemos de todos los detalles necesarios para los ingredientes pulsamos Add ingredient para almacenarlo. Podemos usar las teclas de flecha para mover los ingredientes por la
lista. Esto nos permite introducir los ingredientes en el orden en el que los necesitamos para nuestra receta. Debemos pulsar el botón con la cruz para eliminar ingredientes incorrectos. La tercera pestaña tiene una larga caja de texto para las instrucciones de cocina. Podemos pulsar en el botón bajo la caja de texto para comprobar la ortografía del texto introducido. Hay numerosos botones bajo las pestañas que nos permiten salvar la receta (símbolo del disquete), cerrar el diálogo (círculo con una x), muestra la receta (lupa) o añadirla a nuestra lista de la compra (icono de carro de la compra como el la figura 4). Adicionalmente, la función Scale recipe (es el botón con la flecha azul) nos permite cambiar el número de comensales para una receta y calcula automáticamente las cantidades adicionales de ingredientes.
Cuadro 2: Configuración de un usuario de bases de datos MySQL Para asignar los privilegios de lectura y escritura requeridos al usuario de la base de datos MySQL, debemos convertirnos en el administrador de la base de datos root en la línea de comandos Linux y abrir el interfaz MySQL. Debemos prestar atención y no confundir el administrador de la base de datos root con el administrador de sistemas de Linux root. Si es la primera vez que usamos la cuenta del administrador de la base de datos root, no tendremos asignada contraseña. Esto no significa que el usuario no exista, sino que la cuenta esta desprotegida. En este caso no necesitamos introducir una contraseña para acceder a MySQL: mysql -user=root mysql Para asignar privilegios de lectura y escritura a nuestra base de datos de recetas a nuestra propia cuenta “no privilegiada” debemos escribir el siguiente comando en el cursor. Esto asigna los privilegios de selección, inserción, actualización y borrado de la base de datos: GRANT SELECT, INSERT, UPDATE, DELETE ON Krecipes.* TO 'username'@'hostname' IDENTIFIED BY 'password' ; La base de datos que Krecipes crea automáticamente se llama Krecipes. Reemplazaremos username, hostname y password (nombre de usuario, nombre de host y contraseña) con los credenciales del usuario de la base de datos, la contraseña y el nombre del host. Si estamos ejecutando el servidor MySQL en nuestra máquina local debemos usar localhost como nombre para el host. Alternativamente debemos reemplazar Hostname con el nombre del servidor remoto de bases de datos (por ejemplo un servidor dedicado en nuestra red local).
Figura 6: Creación de la lista de la compra
Ahora le podemos decir al asistente de Krecipes que tenemos los privilegios adecuados (ver figura 1). En la siguiente caja de diálogo (ver figura 2) introducimos los credenciales de usuario y contraseña que acabamos de asignar.
automáticamente.
70
Número 03
www.linuxmagazine.com.es
Krecipes
LINUX USER
Si la vista receta (ver figura 5) no es de nuestro agrado y preferimos tener los ingredientes en un lugar diferente, ¿por qué no cambiar las preferencias en Settings | Page preferences...? Podemos arrastrar los elementos individualmente, por ejemplo la lista de categorías o de ingredientes, con nuestro ratón para reordenarlas (ver figura 5). Ahora debemos pulsar Save and Close para guardar los cambios.
El Carro de la Compra Tras decidir nuestro menú, la función de Krecipes Shopping List, localizada en la barra de navegación de la izquierda de la ventana nos puede ayudar con la tortura de la compra. Figura 7: El asistente de recetas de Krecipes para comensales sanos. Como se muestra en la figucrear planes de dieta con gran detalle para el desayuno como la pizza o un ra 6, podemos seleccionar una o más (ver figura 7). filete. recetas de la lista de recetas existentes En la parte inferior derecha podemos y usar el botón con la flecha hacia la Lucha Contra los Michelines seleccionar los niveles de hidratos de derecha para añadirlas a la lista de la Antes de todo debemos especificar cuancarbono, vitaminas, proteínas o grasa. compra (Shopping list). Pulsando la to tiempo pretendemos estar a dieta, Krecipes nos ofrecerá una selección limiflecha hacia la izquierda elimina las cuantas comidas haremos al día y el tada de recetas que corresponden a recetas de la lista y pulsando Clear número de platos que compondrán cada nuestras preferencias. Cuando pulsamos eliminamos toda la lista. comida. Si hay más de un plato por Create the diet (Crear una Dieta), El botón OK muestra nuestra lista de la comida podemos usar los botones PreKrecipes no solo compila un plan de compra (ver figura 6). Podemos pulsar vious Dish (Plato Previo) y Next Dish dieta para nosotros para el periodo Print para crear una copia para nuestro (Siguiente Plato) para cambiar entre especificado, si no que también nos lo próximo viaje al supermercado. Pulsareplatos. muestra. mos OK para cerrar la ventana. Si marcamos Enable Category Filte¿Alguna vez has abierto el frigorífico y En la parte inferior izquierda de la ring (Filtro por Categoría Habilitado), no has sabido que hacer de comer con ventana de la lista de la compra hay otro Krecipes solo mostrará las recetas de los ingredientes de dentro? La opción de botón que llama a la función Diet Wizlas categorías seleccionadas. Esto, por Ingredient check (Comprobador de ingreard en la barra del navegador. Esta herraejemplo, nos permite evitar platos dientes) en la barra del navegador nos mienta realmente nos puede ayudar a
GLOSARIO CVS: El sistema de versionado concurrente proporciona un sistema de gestión de versiones para archivos. El código fuente se almacena en un servidor donde los desarrolladores pueden añadir parches o nuevas funciones. Podemos usar este sistema para descargar el código a nuestro equipo, lo que al final nos permite construir una versión ejecutable. kdenonbeta: Los programas de kdenonbeta esta normalmente en fases de desarrollo muy iniciales y no son parte oficial de la versión KDE comercial. Esto significa que no se ven afectadas por planes de arrancamiento o de paralización. Como contrapartida, los programas de esta rama no suelen estar disponibles como RPMs o paquetes Debian. El soporte también esta restringido. MySQL: Base de datos que soporta la formulación de consultas en el lenguaje de bases de datos SQL (Lenguaje de consultas estructuradas). Los datos son almacenados en tablas. Podemos usar el cliente de la línea de comandos comentado más adelante en este artículo para gestionar bases de datos MySQL. La aplicación PhpMyAdmin, escrita en el lenguaje PHP, es un cliente alternativo popular. PhpMyAdmin dispone de GUI y soporta el acceso vía Web. No obstante, para usar PhpMyAdmin necesitamos un servidor Apache funcionando, lo que implica algo de trabajo de instalación adicional. SQLite: Librería C con software de servidor de base de datos integrada. Si enlazamos Krecipes con SQLite permitimos que el programa aceda a bases de datos SQL sin necesidad de ejecutar un servidor de bases de datos adicional. La librería SQlite lee y escribe la base de datos directamente desde o hacia el disco.
www.linuxmagazine.com.es
Número 03
71
LINUX USER
Krecipes
pasos indicados más abajo para añadir nuevas conversiones. Categories gestiona las categorías de la recetas y Authors es el lugar donde añadir y editar los nombres de los proveedores de recetas.
Importar
Figura 8: Podemos acceder al elemento “Data” para añadir entradas en la base de datos.
Figura 9: El diálogo “Krecipes preferences” nos permite configurar Krecipes.
puede ayudar. Simplemente debemos seleccionar los ingredientes que tenemos en casa de la lista y pulsamos sobre el icono Find matching recipe (Buscar receta coincidente). Esperemos que encontremos una buena receta en la lista y podamos marcharnos a la cocina con una misión que cumplir.
Ingredientes Si estamos en la sección "Fighting the Flab" y nos preguntamos si realmente Krecipes realmente sabe el valor nutricional de algunas comidas poco usuales como panceta o espinacas de agua, debemos comprobar el elemento Data (Datos) en la barra de navegación para averiguarlo. Estos nos lleva a más entradas de navegación usadas para editar nuestra colección de datos. Por ejemplo, el elemento Ingredients en la figura 8 nos lleva a una lista de elemen-
72
Número 03
tos de todos los ingredientes en la base de datos. Podemos añadir elementos que falten aquí, como algo que no haya sido usado hasta ahora en una receta, por si acaso. Para añadir un ingrediente debemos pulsar el botón con el símbolo +. Para eliminar un ingrediente pulsaremos el botón con el símbolo -. Ambos botones funcionan de forma similar en otras listas. Podemos asignar la unidad apropiada y por supuesto definir la proteína, grasa u otros valores nutricionales de cada ingrediente. Cargar los datos USDA (Load USDA data) hace esto más sencillo, pero esta funcionalidad no está acabada del todo. Ahora mismo lo que hace es cargar los datos de una lista de ingredientes y sus valores nutricionales de una base de datos del departamento de agricultura de los Estados Unidos [5], pero no es capaz de añadir los datos a la base de datos de Krecipes. Los desarrolladores están trabajando duro para resolver este problema. Properties nos lleva a una muestra general de los valores nutricionales introducidos hasta ahora. Podemos introducir elementos usando los símbolos más y menos como describimos antes. Units nos muestra una lista de todas la unidades que conoce la base de datos incluyendo una tabla de conversión de julios a calorías. Podemos añadir más tablas de conversión. Seguiremos los
www.linuxmagazine.com.es
Puede que tengamos muchos datos que añadir y no deseemos reescribir todas las recetas que ya habíamos introducido en nuestro PC. ¿Verdad que sería bonito poder añadir todas esas recetas que hemos descubierto en Internet a nuestra base de datos sin tener que escribirlas? Para facilitar esto, al menos en la mayoría de los casos, Krecipes soporta Recipeml (“Lenguaje de marcas de recetas”) [6], un lenguaje basado en XML especialmente diseñado para mostrar datos de recetas. Krecipes no tiene ningún problema para abrir las recetas en este formato. Puede importar formatos de recetas desde programas como Master Cook o Meal Master a la base de datos mediante el menú File usando el comando Import. El diálogo de configuración del programa bajo Settings | Krecipes preferences (ver figura 9) es el lugar donde jugar con las facilidades de importación de las recetas. También podemos cambiar el nombre de usuario y contraseña de la base de datos MySQL. Numbers modifica el modo en que los números se muestran para las cantidades. Todas estas funciones funcionan bien al margen de que el desarrollo está en fase de desarrollo. Esto hace a Krecipes adecuado para un uso diario y le augura ■ un buen futuro.
INFO [1] Krecipes: http://krecipes.sf.net/ [2] MySQL: http://www.mysql.com/ [3] SQLite: http://www.sqlite.org/ [4] Descraga de Qt: http://www.trolltech. com/download/qt/x11.html [5] Departamento de Agricultura de los Estados Unidos: http://www.usda.gov/ [6] Más información en Recipeml: http:// www.formatdata.com/recipeml/
KDM / GDM
LINUX USER
Configurando KDM y GDM
La primera pantalla Tanto KDE como GNOME disponen de gestores de pantallas. Veremos las características ofrecidas por KDM y GDM y examinaremos como configurar un gestor de pantalla en nuestro sistema Linux. POR HAGEN HÖPFNER
E
n muchos sistemas, el gestor de ventanas o de acceso es el primer programa del GUI que ve el usuario. La mayoría de las más importantes distribuciones arrancan automáticamente el sistema X Windows. Los usuarios escriben sus nombres y contraseñas para acceder y seleccionar el entorno. Habitualmente pueden seleccionar otras opciones, como apagar el equipo o reiniciarlo. KDM, del proyecto KDM y su homólogo Gnome, GDM, son los más populares gestores de pantallas, si bien hay una serie de alternativas, como los gestores del legado de XDM o el compacto WDM. El gestor de acceso no influye en la manera en la que se ejecuta el escritorio. Incluso los mayores fans de KDE podrían seguir usando GDM para acceder al sistema y arrancar su entorno favorito. La única desventaja es que instalar GDM incluye muchas librerías de Gnome en nuestro disco duro ocupando un valioso espacio de almacenaje. Este artículo explica como cambiar el gestor de pantalla en Fedora Core 2, Suse Linux 9.1 y Mandrake Linux 10.0 y como podemos añadir gestores de ventanas a la lista desplegable.
gdm bajo Fedora Core 2, Suse y Mandrake Linux, mientras KDM puede encontrarse en varios paquetes RPM. En Suse el paquete se llama kdebase3-kdm, Mandrake Linux lo llama kdebase-kdm y Fedora lo llama kde-base. En Mandrake y en Suse Linux puede que incluso no obtengamos un gestor de ventanas si elegimos el acceso automático al instalar el sistema. Esto puede ser válido para usuarios individuales porque el usuario solo necesita un escritorio, pero hay una serie de desventajas. Para empezar es muy complicado cambiar a un escritorio alternativo y luego cualquiera puede acceder a nuestros datos simplemente encendiendo el equipo. Para deshabilitar el acceso automático en Suse Linux debemos arrancar YaST y seleccionar etc/sysconfig/Editor en System. Debemos editar la entrada Desktop | Display manager | DISPLAYMANAGER_AUTOLOGIN eliminando el nombre del usuario del campo a la derecha de la ventana.
Lo Básico La mayoría de las distribuciones instalan un gestor de ventanas cuando instalan Linux. Suse y Mandrake usan KDM por defecto (figura 1) y Fedora usa GDM (figura 2). Si deseamos probar un gestor alternativo lo primero que debemos hacer es añadirlo a nuestra lista de instalación. GDM se encuentra en el paquete
Mandrake Linux usa drakconf como herramienta de configuración. Seleccionamos Autologin en Boot y cambiamos la selección a No, I don't want autologin. Debemos asegurarnos de que no deshabilitamos la casilla Launch the graphical environment when your system starts por error. Este ajuste evita arrancar el GUI al inicializar el sistema forzándonos a acceder en una consola basada en texto primero y luego debiendo escribir startx para acceder al escritorio KDE.
Cambio entre GDM y KDM
Figura 1: La pantalla de inicio de sesión KDM en Suse Linux.
Para cambiar el gestor de ventanas por defecto debemos realizar algunos cambios manuales a Mandrake Linux y a Fedora Core 2. Ambas distribuciones usan el archivo
www.linuxmagazine.com.es
Número 03
73
LINUX USER
KDM / GDM
Figura 2: GDM da la bienvenida a los usuarios en Fedora Core 2.
/etc/X11/prefdm para arrancar el programa de acceso. prefdm lee los ajustes del gestor de acceso de una variable llamada DISPLAYMANAGER, que viene descrita en /etc/sysconfig/desktop. La línea que describe el gestor contendrá o DISPLAYMANAGER="kdm" o DISPLAYMANAGER="gdm". Al arrancar el GUI, se iniciará el gestor de acceso seleccionado. Mandrake ofrece dos variantes a KDM: una versión específica de Mandrake usada por defecto (figura 3) y la versión simple de KDM. Si ajustamos la variable DISPLAYMANAGER a kdm se muestra el KDM original al arrancar el GUI. La versión Mandrake del gestor de acceso se muestra si cambiamos la variable a DISPLAYMANAGER="KDE" en /etc/sysconfig/desktop. Los usuarios de Suse Linux necesitan /etc/sysconfig/Editor en YaST. Esta herramienta es una portal que proporciona a los usuarios un acceso conveniente al directorio /etc/sysconfig/. Si preferimos un editor de texto a YaST, simplemente debemos editar la variable DISPLAYMANAGER en /etc/sysconfig/displaymanager para Suse Linux.
Control de KDM Cada distribución tiene una configuración por defecto que definen la apariencia de KDM. Bajo Suse, KDE incita al usuario a introducir su Username (nombre de usuario) y Password (contraseña), disponiendo adicionalmente de una Menu (figura 4) que permite al usuario seleccionar el tipo de sesión (Session type) y funciones para el rear-
74
Número 03
Figura 3: KDM en Mandrake Linux – paso a paso.
ranque del servidor X y apagar el sistema (Shutdown). Mandrake Linux espera que el usuario primero seleccione un nombre de usuario y luego muestra un dialogo de contraseña (figura 3) donde el usuario puede especificar el escritorio que desea arrancar. EL KDM de Fedora es muy simple en comparación, pero se comporta exactamente como KDM bajo Suse Linux. Las tres variantes permiten al usuario acceder, pero al menos hay una buena razón para cambiar la opción por defecto. La selección del tipo de sesión está basada en gestores de ventanas preinstaladas y escritorios de entornos. Si instalamos un gestor de ventanas adicional, el gestor de acceso no mostrará una entrada para el nuevo gestor de ventanas al menos que la distribución tenga una macro de seión a juego. Tanto KDM como GDM ignoran los gestores de ventanas sin una macro a juego. El gestor qlwm es un ejemplo de esto. Para indicar a KDM que añada qlwm necesitamos crear un nuevo tipo de sesión. KDE solía tener un Centro de Control para gestionar esto, pero esta opción ha desaparecido en KDE 3.2. En su lugar necesitamos acceder como raíz y crear un archivo de comandos de sesión para la nueva entrada. Un archivo de comandos de sesión es un archivo de texto que contiene parámetros para el gestor de ventanas. Suse Linux almacena los archivos de comandos de sesión en /opt/kde3/share/apps/kdm/sessions/.
www.linuxmagazine.com.es
Mandrake Linux y Fedora Core 2 buscan estas entradas bajo /usr/share/apps/kdm/sessions/. Escribimos el nombre del archivo - qlwm.desktop en nuestro ejemplo (podemos elegir cualquier nombre, pero la extensión es obligatoria) y luego añadimos lo siguiente: [Desktop Entry] Encoding=UTF-8 Type=XSession Exec=/usr/local/bin/qlwm TryExec=/usr/local/bin/qlwm Name=QLWM
¡Hemos acabado! La próxima vez que accedamos KDM tendrá un inicio de sesión del tipo QLWM entre sus opciones. El nombre del tipo de inicio de sesión se define en la línea Name=, QLWM en nuestro caso. Esto supone que hay un archivo llamado /usr/local/bin/qlwm y que el archivo es ejecutable (TryExec). Si ahora seleccionamos QLWM como el tipo de inicio de sesión para acceder, KDM debe ejecutar el programa especificado en la línea que comienza con Exec. KDM ordena el tipo de sesión en el menú desplegable alfabéticamente por el nombre del código de la sesión. Si deseamos que QLWM sea el primero de la lista podemos cambiar el nombre qlwm.desktop creado en el paso previo por 00qlwm.desktop.
Más Bonito Si estamos descontentos con la apariencia y aspecto de KDM, debemos repasar
KDM / GDM
LINUX USER
Figura 4: Suse Linux ofrece a los usuarios un amplio rengo de opciones de KDM a la vez.
Figura 5: Modificando el aspecto y apariencia de KDM.
su herramienta de configuración. La herramienta está localizada en el Centro de Control de KDE bajo System administration | Login manager (figura 5). Aparte de pestañas para una configuración refinada de la apariencia del gestor de acceso (Appearance, Font, BackgroundApariencia, Fuente, Fondo), hay tres pestañas de opciones generales. La pestaña Shutdown (Apagar) permite especificar los usuarios que tienen permiso para apagar y reiniciar el equipo. La pestaña Users (Usuarios) nos permite seleccionar las cuentas de usuario que muestra KDM. Debemos repasar el manual de usuario de KDE en [1] para obtener más información sobre la configuración. Desafortunadamente el manual no está actualizado en todos los aspectos, si bien se supone que cubre hasta KDE 3.3.
Inicio de Sesión con Gnome Al igual que ocurre con KDM, la apariencia de GDM es específica para cada distribución. Suse Linux dispone de una característica para ajustar el lenguaje del procedimiento de acceso (Language). Session (Sesiones) ofrece al
usuario una lista de gestores de ventanas y entornos de escritorio seleccionables y System (Sistema) dispone de opciones para apagar y reiniciar el equipo junto a una opción para configurar XDMCP. También hay una entrada para arrancar el programa de configuración de GDM. GDM en Mandrake Linux es exactamente igual con la excepción del menú System, que se llama Actions (Acciones). Fedora, que usa GDM por defecto, no dispone de un menú para apagar o reiniciar el equipo. Fedora tampoco tiene ninguna opción para arrancar la herramienta de configuración de KDE. No obstante el usuario root puede ejecutar el comando gdmsetup tras iniciar la sesión para acceder a estas características. En la pestaña Security (Seguridad) podemos especificar si deseamos permitir el acceso al diálogo de configuración desde la ventana de acceso. No obstante, aunque marquemos la casilla Allow configuration from the login screen (Permitir configuración desde la pantalla de inicio de sesión) en Fedora Core 2, no veremos el botón de gdmsetup al acceder. Los theme (Temas) de l
GDM de Fedora Core 2 tienen la culpa. Si elegimos un tema diferente en la pestaña Graphical greeter (Saludo gráfico), Fedora GDM nos mostrará sin ningún problema la herramienta de configuración. Debido a que la selección de temas preinstalada es limitada, puede que queramos echar un vistazo a [3] para elegir un nuevo tema. De nuevo tendremos que ejecutar gdmsetup para instalar cualquier tema descargado de Internet. Es muy simple indicar a GDM que muestre una selección de tipos de sesión en cualquier gestor de ventanas que instalemos, de hecho tan simple como hacerlo en KDM. La única diferencia entre las dos configuraciones es la ruta al código de la sesión. GDM en Suse Linux espera encontrar el código en /opt/gnome/share/xsessions. La ruta en Mandrake Linux y Fedora Core 2 es /usr/share/xsessions/. Si buscamos más información respecto a como configurar GDM debemos ver el manual de re■ ferencia en [4].
INFO [1] Manual KDM: http://docs.kde.org/en/ HEAD/kdebase/kdm/
GLOSARIO Theme(Tema): Un tema es una colección de elementos que proporcionan a aplicaciones de base GUI una apariencia predeterminada. Alparte de la mayoría de los gestores de ventanas, aplicaciones como Mozilla o XMMS soportan temas. XDMCP: Protocolo de Control de Gestor de Pantalla X [2] fue desarrollado para permitir el acceso a sesiones X a través de la red. Los usuarios remotos pueden trabajar como si tuvieran acceso directo al equipo desde remotamente y se les permite hasta ejecutar aplicaciones basadas en GUI en el servidor X. Por motivos de seguridad y para reducir la carga de la red, SHH es preferible a XDMCP.
[2] Linux XDMCP HOWTO: http://www.tldp. org/HOWTO/XDMCP-HOWTO/ [3] Temas GDM: http://art.gnome.org/ themes/gdm_greeter/ [4] Manual de referencia de GDM: http:// www.jirka.org/gdm-documentation/t1. ht
www.linuxmagazine.com.es
Número 03
75
LINUX USER
XUL
Programando con Mozilla Xul
Clics Bonitos En los primeros capítulos de nuestra serie de XUL hemos estado principalmente mirando los conceptos básicos del lenguaje. A medida que nuestro viaje ha continuado hemos explorado botones, etiquetas y gestión de geometrías, comenzando el mes pasada conectar funcionalidad a nuestro interfaz. POR JONO BACON
E
ste mes vamos a repasar con mucha atención qué menús se utilizan y para qué y como crearlos. Una vez hecho esto juntaremos toda la información de los últimos números para crear un interfaz XUL completo. Si bien este interfaz no incluirá toda la funcionalidad de una aplicación completa, sí nos permitirá asentar nuestros conocimientos de XUL mediante la creación de un interfaz completo y práctico. Los menús proporcionan una forma de ocultar funcionalidad manteniéndola accesible de forma sencilla para el usuario. El modo de funcionar de los menús es muy ingeniosa. Si necesitásemos mostrar un botón para cada fun-
76
Número 03
ción de una aplicación acabaríamos con un interfaz completamente abarrotado. Los menús disponen de una serie de partes distintas. La primera es la barra de herramientas. Éste es el espacio en la parte superior de la ventana de la aplicación que agrupa los distintos menús. Dentro de este espacio tenemos distintos objetos que se refieren a distintas categorías de opciones. Finalmente, podemos pulsar dentro de esas categorías y podemos mostrar el menú emergente completo con una serie de opciones que están relacionadas con ese menú. Si pulsamos en el menú Archivo de un programa normalmente nos encon-
www.linuxmagazine.com.es
tramos con opciones como Nuevo, Abrir, Cerrar, Guardar o Guardar como entre otros. Mientras que los usuarios sepan el tipo de función que necesitan deben de ser capaces de seleccionar el menú adecuado y acceder a la opción deseada. Siempre debemos tener una idea clara respecto al tipo de funcionalidad que debe ir en cada categoría del menú y asegurarnos de que nuestros menús son lo suficientemente intuitivos como para persuadir al usuario de pulsar en el menú correcto para acceder a la opción deseada. La organización de menús cada vez tiene manos en cuenta su uso y la consecuencia directa de esto es la convivencia de opciones no relacionadas en el mismo
XUL
menú. Un ejemplo puede ser la opción Work Offline (Trabajar desconectado) en el menú Archivo del programa Mozilla Firefox. Otro ejemplo en Microsoft Windows es la aparición de la opción de apagado en el menú de Inicio. Alguno de vosotros no estaréis de acuerdo con estos ejemplo, pero todos debemos prestar atención al uso por parte del usuario de los menús al crearlos.
Creación de Nuestro Primer Menú Para comenzar con nuestro primer menú necesitaremos crear el código base normal que aparece en casi todos los archivos XUL. Usaremos el código que aparece en el listado 1. Ahora podemos crear la estructura de nuestro menú. El primer elemento que necesitamos crear es el que posiciona nuestro menú en la parte superior de la pantalla. Esto es llamado caja de herramientas y lo añadimos con la etiqueta <toolbox> (caja de herramientas): <toolbox>
Como otros contenedores de gestión de geometría, la etiqueta “toolbox” posiciona el código en una parte específica de la pantalla. Otra opción es la de poder añadir el control especial “agarradera” de la barra de herramientas de forma que pueda ser separada de la ventana y ser movida en una ventana separada sobrepuesta. No usaremos esta opción para nuestros menús por
Otros lenguajes y XUL Una de las mayores preguntas que se realiza al mirar a XUL es si hay otros lenguajes disponibles para escribir código XUL. Actualmente el único lenguaje soportado es Javascript, si bien se está pensando en la inclusión de otros lenguajes en versiones futuras de Mozilla. Entre estos lenguajes puede que estén incluidos Python o C#. Muchas de de las discusiones entre los desarrolladores se giran alrededor de la creación de un nuevo nivel de funcionalidad de la aplicación Mozilla: la máquina virtual de Mozilla. Podemos encontrar más información al respecto del progreso del proyecto Mozilla en las Webs Mozillazine (http:// www.mozillazine.org/) y en Planet Mozilla (http://planet.mozilla.org/).
ahora (se usa normalmente en barras de herramientas). Lo siguiente que debemos hacer es crear una barra de menú en las que poner las entradas de nuestro menú. Nos referimos a la típica zona gris sobre la que se superponen los componentes de los menús. Podemos añadir esta zona usando la etiqueta “menubar” (barra de menú): <menubar id="menubar">
Hemos especificado una identidad a esta barra de menú, práctica común cuando manejamos menús y botones en XUL. Ahora estamos listos para agregar componentes a nuestro menú. Con este fin utilizamos la etiqueta “menu” (menú) con su correspondiente identidad para el atributo y nombre con la etiqueta del atributo: <menu id="filemenu"U label="Archivo">
Ahora necesitamos llenar el menú con componentes. Para hacer esto necesitamos añadir el primer menú especial emergente usando la etiqueta <menupopup>:
LINUX USER
El elemento final puede ser la típica opción de cerrar tras el separador: <menuitem label="Salir"/>
Para finalizar añadiremos todas la etiquetas de cierre que completan la estructura de nuestro menú: </menupopup> </menu> </menubar> </toolbox> </window>
Nuestro archivo completo hasta ahora se muestra en el listado 2 y en la figura 1 vemos la estructura completada.
Más Funcionalidades de menú Una de las funcionalidades más habituales en un menú es un sub-menú. Este tipo de menús especiales aparece cuando movemos el cursos sobre un componente del menú principal. Para crear un sub-menú debemos editar parte del código existente y añadir otra estructura para el mismo. Añadiremos un sub-menú al elemento Nuevo de nuestro menú, necesitando cambiar la siguiente línea:
<menupopup id="filepopup"> <menuitem label="Nuevo"/>
con nuestro menú emergente añadido procedemos a insertar objetos usando la etiqueta <menuitem> (elemento de menú) para cada uno de los distintos objetos: <menuitem label="Nuevo"/> <menuitem label="Abrir"/> <menuitem label="Guardar"/>
<menu id="newmenu"U label="Nuevo">
Puede que hayas notado que no hay un atributo de identificación para cada menú. Esto es debido a que vamos a usar un método diferente para gestionar que elemento del menú se pulsa que veremos más adelante. Cuando estemos creando nuestros menús puede que deseemos separarlos en diferentes secciones. Podemos hacerlo usando separadores de menús con la etiqueta <menuseparator> (Separador de menús): <menuseparator/>
Cuando añadimos un sub-menú emergente debemos cambiar el elemento padre del sub-menú, modificando la etiqueta original <menuitem>, por la etiqueta <menu>:
Listado 1: first.xul 01 <?xml version="1.0"?> 02 <xml-stylesheet href="chrome://global/skin/" type="text/css"?> 03 <window 04 id="test-window" 05 title="Test Program" 06 xmlns="http://www.mozilla.org/ keymaster/gatekeeper/there.is. only.xul">
www.linuxmagazine.com.es
Número 03
77
LINUX USER
XUL
Ya hemos creado una estructura nueva. Ahora estamos listos para añadir el sub-menú emergente:
entradas del menú Archivo se añaden con la etiqueta <menuitem>, el objeto Nuevo es añadido con la etiqueta <menu> al ser un sub-menu:
<menupopup id="secondpopup"> <menuitem label="Plantilla"/> <menuitem label="Fichero"/> </menupopup>
<menu id="newmenu"U label="Nuevo"> <menupopup id="secondpopup"> Debemos recordar añadir las etique<menuitem tas de cierre: Figura 1: Un simple menú Figura 2: Añadir un sub-menú label="Plantilla"/> Archivo con una línea de al menú principal en XUL es <menuitem </menu> separación incluida. simple. label="Fichero"/> </menupopup> Ahora debemos ver algo similar a lo que deberíamos asegurarnos de que la eti</menu>
se muestra en la figura 2.
Construcción de un Interfaz Completo XUL nos muestra su potencial real cuando comenzamos a unir diferentes componentes hasta completar un interfaz. Vamos a crear un interfaz completo con XUL que puede utilizarse como base de futuras interfaces. Construiremos este interfaz desde el principio como si de una herramienta de gestión de información se tratase. Esto involucrará la dedicación de determinadas partes de la pantalla a diferentes funciones y usos. Si bien no escribiremos la funcionalidad del interfaz, sí lo usaremos como base para escribir una aplicación completa en XUL. Para hacer que sea más fácil de entender repasaremos cada línea del código individualmente y luego presentaremos el listado del código completo al final del artículo. Comenzaremos añadiendo el código base XUL del listado 1. Este código simplemente especifica a Mozilla que se trata de XUL y luego usa la etiqueta <window> (ventana) para crear la ventana padre. Una vez completado este código debemos especificar el archivo que contiene el Javascript que proporciona funcionalidad a nuestra interfaz: <script src="code.js"/>
En nuestra interfaz ejemplo no estamos realmente escribiendo ningún código en JavaScript y solo nos concentraremos en XUL. Si estuviésemos escribiendo una aplicación XUL funcional
78
Número 03
queta con la que especificamos el código JavaScript es la primera etiqueta dentro de la etiqueta bloque <window>. La primera parte de nuestro interfaz a crear es la estructura del menú. Especificaremos la etiqueta <toolbox> (caja de herramientas) para indicar que nuestro menú está posicionado en la parte superior de nuestra ventana. Esto nos asegura que nuestros menús y barras de herramientas (las veremos más adelante) se agrupan de forma conjunta en la caja de herramientas: <toolbox>
Ahora podemos crear nuestra barra de menú principal y poner un menú y un sub-menú. Debemos recordar que cada menú se especifica con una etiqueta <menu> (esta etiqueta realmente añade el nombre del menú a la barra de menús), pero también debemos crear el menú emergente propiamente dicho (el menú que aparece cuando pulsamos sobre un elemento). Éste es el código: <menubar id="samplemenubar"> <menu id="filemenu"U label="File"> <menupopup id="filepopup">
En este punto no tenemos ningún elemento en el menú emergente. El primer elemento, Nuevo, es un poco diferente porque es en sí un menú emergente. Para añadir este sub-menú creamos nuestras etiquetas <menu> y <submenu> y luego añadimos las etiquetas <menuitem> (elementos del menú). Es importante saber que si bien las otras
www.linuxmagazine.com.es
Tras completar el menú Nuevo y su submenú podemos proceder a añadir el resto de nuestro componentes al menú Archivo. Hacemos esto con una serie de etiquetas <menuitem>, usando la etiqueta <menuseparator> para crear una línea entre las entradas de los elementos: <menuitem label="Abrir"/> <menuitem label="Guardar"/>
Listado 2: second.xul 01 <?xml version="1.0"?> 02 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> 03 <window 04 id="test-window" 05 title="Test Program" 06 xmlns="http://www.mozilla.org/ keymaster/gatekeeper/there.is. only.xul"> 07 <toolbox> 08 <menubar id="menubar"> 09 <menu id="filemenu" label="Fichero"> 10 <menupopup id="filepopup"> 11 <menuitem label="Nuevo"/> 12 <menuitem label="Abrir"/> 13 <menuitem label="Guardar"/> 14 <menuseparator/> 15 <menuitem label="Salir"/> 16 </menupopup> 17 </menu> 18 </menubar> 19 </toolbox> 20 </window>
XUL
<menuseparator/> <menuitem label="Salir"/> </menupopup> </menu>
Ahora procedemos a añadir el segundo menú a la barra de herramientas. Éste será el menú de edición(Edit), usando de nuevo las etiquetas <menu>, <menupopup>, y <menuitem>: <menu id="editmenu"U label="Edit"> <menupopup id="editpopup"> <menuitem label="Deshacer"/> <menuitem label="Rehacer"/> </menupopup> </menu>
Para finalizar nuestra estructura, necesitamos añadir las etiquetas de cierre <menubar> y <toolbox>: </menubar> </toolbox>
La parte principal de nuestra interfaz va ha estar compuesta, a la izquierda, por una combinación de una caja combo, una caja de listado y una barra de división reajustable, y a la derecha el área principal de texto y algunos otros botones. Con esto en mente debemos tener algunos componentes encima de otros (la caja combo está encima de la caja de listado, por ejemplo) y algunos otros componentes al lado de otros (por ejemplo botones). Esto implica la combinación de la etiquetas <hbox> y <vbox> con el fin de agrupar componentes de determinadas formas. Comenzaremos usando la etiqueta <box> (caja) para indicar que estamos usando un diseño tipo caja para todos nuestros componentes, y luego creamos la etiqueta <vbox> para disponer la caja combo y la caja de listado una encima de la otra. Cada uno de los componentes usa <flex=1> para extender el propio componente y ocupar todo el espacio disponible. Esta
LINUX USER
coletilla se utiliza a lo largo de todo el código. <box flex="1"> <vbox flex="1">
Nuestro primeros componentes van ha ser una etiqueta y una caja combo, los cuales van ha estar agrupados por la etiqueta <hbox> para que se coloquen uno al lado del otro. Primero creamos la etiqueta <label> con el modo texto y luego creamos la caja combo (es como se denomina en XUL una lista de menú) con la etiqueta <menulist>. Dentro de esta etiqueta creamos una serie de entradas <menuitem> para cada objeto en la caja. También hemos dispuesto el atributo editable como falso para la lista de nuestro menú con la intención de que los usuarios no puedan cambiar los contenidos de la caja: @LI<hbox> <label value=“Mode”/ > <menulist editable=“false” flex=“1”> <menupopup> <menu-
Listado 3: third.xul Completo 01 <?xml version="1.0"?> 02 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> 03 <window 04 id="testwindow" 05 title="XUL Interface" 06 xmlns="http://www.mozilla.org/ keymaster/gatekeeper/there.is. only.xul"> 07 <script src="code.js"/> 08 <toolbox> 09 <menubar id="samplemenubar"> 10 <menu id="filemenu" label="Fichero"> 11 <menupopup id="filepopup"> 12 <menu id="newmenu" label="Nuevo"> 13 <menupopup id="secondpopup"> 14 <menuitem label="Plantilla"/> 15 <menuitem label="Fichero"/> 16 </menupopup> 17 18 </menu> 19 <menuitem label="Abrir"/> 20 <menuitem label="Guardar"/> 21 <menuseparator/>
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
<menuitem label="Salir"/> </menupopup> </menu> <menu id="editmenu" label="Editar"> <menupopup id="editpopup"> <menuitem label="Deshacer"/> <menuitem label="Rehacer"/> </menupopup> </menu> </menubar> </toolbox> <box flex="1"> <vbox flex="1"> <hbox> <label value="Mode"/> <menulist editable="false" flex="1"> <menupopup> <menuitem label="Simple"/> <menuitem label="Avanzado"/> <menuitem label="Experto"/> </menupopup> </menulist> </hbox> <listbox> <listitem label="Facturas"/> <listitem label="Gastos"/> <listitem label="Pequeños
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
65 66 67 68 69
Gastos"/> <listitem label="Otro"/> </listbox> </vbox> <splitter collapse="before"> <grippy/> </splitter> <vbox flex="1"> <hbox> <button id="addbutton" label="Añadir"/> <button id="deletebutton" label="Eliminar"/> <button id="editbutton" label="Editar"/> </hbox> <textbox id="posttext" multiline="true" flex="1"/> <hbox> <button id="findbutton" label="Previsualizar" default="true"/> <button id="cancelbutton" label="Publicar"/> </hbox> </vbox> </box> </window>
www.linuxmagazine.com.es
Número 03
79
LINUX USER
XUL
El siguiente componente es un componente de entrada de datos de mucho texto. Éste es el tipo de componente que se utilizaría para introducir texto en un editor de textos, por lo que nos debemos asegurar de que el componente es capaz de soportar más de una línea de texto. Podemos hacer esto con el atributo multilínea: <textbox id="posttext"U multiline="true" flex="1"/>
Nuestro conjunto final de componentes es una colección de botones que funcionan de la misma forma que los botones Añadir, Eliminar y Editar que hemos creado con anterioridad:
Figura 3: Un interfaz XUL completo.
item label= “Simple”/> <menuitem label= “Avanzado”/> <menuitem label= “Experto”/> </menupopup> </menulist> </hbox> El componente que falta por añadir es la caja de listado. Para crearlo usamos la etiqueta <listbox> y añadimos cada objeto a la etiqueta <listitem>: <listbox> <listitem <listitem <listitem Gastos"/> <listitem </listbox>
label= "Factura"/> label= "Gastos"/> label= "PequeñosU label= "Otros"/>
Con anterioridad abrimos la etiqueta <vbox> en el código para disponer las cajas combo y de listado una encima de la otra. Ahora debemos cerrar esta etiqueta usando la etiqueta de cierre <vbox>: </vbox>
Hasta ahora hemos credo componentes que aparecen en la parte izquierda de nuestro interfaz. En casos en los que claramente separemos un lado del interfaz del otro debemos usar la etiqueta <splitter> para tener un separador ajustable entre las dos zonas. Una de las posibilidades de esta etiqueta es que podemos colapsar un lado y especifi-
80
Número 03
camos el atributo <collapse> (colapsar) para especificar los componentes antes de la etiqueta en el código (nuestra caja combo y listado). También hemos añadido la etiqueta <grippy> (agarradera) para proporcionar una manera de mover el separador: <splitter collapse="before"> <grippy/> </splitter>
Para componentes situados a la derecha del separador vamos a agrupar grupos de componentes unos encima de otros. Primero creamos la etiqueta <vbox>: <vbox flex="1">
Nuestro primer grupo de componentes esta formado por los tres botones que aparecen cerca del marco superior de la ventana. Creamos la etiqueta “hbox” para disponerlos unos al lado de los otros y luego añadimos la etiqueta “button”: <hbox> <button id="addbutton"U label="Añadir"/> <button id="deletebutton"U label="Eliminar"/> <button id="editbutton"U label="Editar"/> </hbox>
www.linuxmagazine.com.es
<hbox> <button id="findbutton" label=U "Previsualización"U default="true"/> <button id="cancelbutton" U label="Publicar"/> </hbox>
Para completar nuestro código ahora debemos añadir la etiquetas de cierre <vbox>, <box> y <window>: </vbox> </box> </window>
El listado 3 es el código completo. Cuando ejecutemos este código debemos ver algo parecido a lo que se muestra en la figura 3.
El Siguiente Paso En este número hemos agrupado todos nuestro conocimientos actuales de construcción de interfaces en XUL. A medida que continuemos explorando XUL veremos las funcionalidades de aplicaciones XUL en más detalle, incluyendo el uso de PHP para conseguir archivos XUL más dinámicos. Hasta que continuemos el próximo mes debemos seguir jugando con las diferentes etiquetas de interfaz de XUL y experimentando con distintas combinaciones de componentes. Cuantas más experiencia tengamos mejor vamos a ser capaces de resolver pro■ blemas.
Educación
LINUX USER
El servidor interactivo multipropósito de actividades WIMS
Ejemplo Práctico con WIMS En los artículos anteriores hemos aprendido a generar y a configurar los ejercicios interactivos y las hojas de trabajo asignando a cada actividad un peso en puntos. La explicación era que la realización de una tarea va acompañada del registro de los puntos correspondientes hasta que el número de puntos que se obtiene llegue al número requerido para dar el ejercicio por superado con éxito. POR JUAN RAFAEL FERNÁNDEZ
E
l servidor WIMS también calcula la calidad de los puntos y la muestra cuando acaba el ejercicio. El profesor puede servirse de estas dos categorías de datos (el número de puntos obtenidos y la calidad de los mismos) para controlar el progreso de los alumnos. Los alumnos pueden también comparar su puntuación con la puntuación media de la clase. Releo el párrafo anterior. Lo encuentro abstracto, quizás necesario, pero no convincente. La forma de captar la utilidad de la aplicación es con ejemplos prácticos en una situación real, a esto dedicaremos el resto del artículo.
WIMS en la práctica Aunque en este tiempo de plurilingüismo no hay mucha excusa para no utilizarlo ya, dentro de poco tiempo dispon-
dremos de paquetes wims con la mayoría de los módulos y de las ayudas traducidas al castellano. En ese momento será muy fácil instalar el servidor en una máquina de nuestro centro, y aprovechar la agilidad que proporciona una red local y por otro lado el control sobre accesos, incorporación de actividades, etc. que permite ser nuestros propios administradores. Sólo será necesario instalar WIMS en un ordenador: los demás usuarios se conectarán a través del navegador web desde cualquier sistema operativo. Por otro lado el tema de los permisos también queda resuelto: dejando aparte la administración pura y dura del servidor, las cuentas son las del profesorsupervisor de las hojas de ejercicios, y las de los alumnos, a los que los profesores proporcionan la contraseña para participar en las clases virtuales (otras
Cuadro 1: Traducción de WIMS Lo que anunciábamos como una primicia se va poco a poco convirtiendo en una realidad: a iniciativa de la Junta de Extremadura y dirigidos por Antonio Ullán, un equipo de traductores formado por Pepe Grimaldos, Javier Sánchez, José Rafael Rodríguez, Carlos Entrena, Antonio Saorín y en el que tengo el honor de colaborar estamos procediendo a la traducción de los módulos y de la interfaz de usuario de WIMS. Esperemos que para cuando este artículo llegue a los kioskos el proceso esté terminado o próximo a su conclusión; algunas de las capturas de pantalla que acompañan a este artículo son verdaderos estrenos.
cuentas mencionables son las de los administradores propiamente dichos del servidor WIMS y las de los desarrolladores de módulos). Planteémonos el caso de un centro educativo de varios niveles donde se dispone de un servidor WIMS. Varios profesores crean clases virtuales, como vimos en la segunda parte de esta serie, y se encargan de que los alumnos se inscriban en la clase; hasta que no se participa de una clase virtual no se habilita el sistema de registro y seguimiento de la evolución de los alumnos. Seguidamente el profesor crea varias hojas de ejercicios, de distintos niveles de dificultad en la selección de los ejercicios y en el grado de dificultad que los módulos individuales permiten configurar. Para crear las hojas dispone de todos los módulos y actividades instalados en el servidor, y a su vez puede crear o adaptar de forma interactiva actividades mediante dos lenguajes integrados en el sistema: uno más sencillo, el OEF de Createxo, que fue el que mostramos en su momento, y otro, Modtool, que utiliza la verdadera potencia de WIMS pero que escapa de las posibilidades expositivas de una introducción que se está haciendo demasiado larga y que por supuesto está documentado en el
www.linuxmagazine.com.es
Número 03
81
LINUX USER
Educación
propio servidor (enlace módulos a toda potencia). El resultado sería algo similar a la figura 1. ¿Como sería una sesión? Los alumnos se conectan al servidor, y trabajan individualmente o por equipos en la hoja asignada. Recordemos que las hojas pueden incluir lecciones y apuntes, que el profesor puede configurar en qué momento comienzan a registrarse los resultados de los ejercicios y puede habilitar un tiempo de ensayo previo, y que puede decidirse el tiempo que va a dedicarse a la realización de cada ejercicio o grupo de ejercicios. Un detalle importante es que los procesos de consulta, razonamiento, borradores y desarrollos de cálculos, discusión entre alumnos sobre la solución o la forma de alcanzarla son provocados por el sistema pero no se realizan necesariamente en él. Los alumnos trabajan con los medios habituales, papel, libretas, pizarra, calculadoras, su propio cerebro. Nuestro alumno Pepe Pruebas vería la clase virtual como en la figura 2. Cuando la repetición (recordemos, no reiterativa) lleva a un grado de confianza suficiente el alumno realiza un examen (figura 3), nunca igual que el alumno de al lado.
Figura 1: Una clase virtual vista por el profesor.
Figura 2: La clase vista por el alumno.
Balance pedagógico en diez puntos Parto en esta sección del balance que del uso para la enseñanza de matemáticas del servidor WIMS se ha efectuado en el sitio http:// www.poitou-charentes.iufm.fr/ wims/cd/bilan/bilan.htm. 1. Un servidor WIMS permite individualizar la enseñanza. Como el resto de las herramientas informáticas, WIMS colabora a la atención a la diversidad. Además la gran riqueza de actividades y la generación aleatoria de parámetros conllevan que cada alumno realice Figura 3: El examen. un recorrido propio o un ritmo individualizado por el entorno WIMS. Por otro lado esta variación per2. Un servidor WIMS es una herramite que la repetición de los ejercicios mienta para trabajar sobre determinados hasta la comprensión de las nociones en tipos de ejercicios. A pesar de su gran juego no se haga frustrante. potencia, no es la panacea, ni puede
82
Número 03
www.linuxmagazine.com.es
esperarse que ésta exista. WIMS necesita una determinada codificación de las tareas; por otro lado su modularidad hace que puedan desarrollarse nuevas herramientas («programas satélite» les llama Georges Khaznadar) que permitan su aplicación a nuevos campos. Un campo en especial donde debe progresar es en el lingüístico, en el que los módulos dedicados y las herramientas aplicadas son insuficientes. Independientemente de lo anterior la usabilidad por los usuarios finales es alta, y la creación de recursos con Createxo es relativamente fácil, aunque la herramienta es mejorable en su intuitividad. También sería deseable un módulo de importación de actividades de generación externa (pienso especialmente en código html y javascript) más sofisticado que el mero cortar y pegar. 3. Un servidor WIMS constituye una interfaz muy potente y unificada para el uso de numerosos programas, en especial matemáticos y científicos, que de otro modo son difíciles de utilizar. Además el hecho de que pueda utilizarse desde cualquier navegador implica que las actualizaciones no conllevan ninguna modificación en los clientes y benefician automáticamente a todos los usuarios. 4. WIMS es un programa seguro y ligero para los usuarios. A diferencia de los programas realizados en java, flash o javascript, que exigen la presencia de plugins y de potencia de cálculo en los ordenadores de los usuarios, las actividades WIMS se ejecutan en el servidor. Sólo es necesario un navegador con javascript habilitado para conectarse a un servidor WIMS, que será el que realice los cálculos o genere los gráficos. Por supuesto la máquina que haga de servidor sí debe ser potente y tener instalados los programas que van a utilizarse. 5. Una sesión de trabajo con un servidor WIMS no elimina el trabajo de cálculo, razonamiento, etc. del alumno. Esto contradice uno de los temores más comunes de los detractores del uso de
Educación
Cuadro 2: Programaciones en WIMS Aquellos profesores de mentalidad práctica y que se atrevan directamente con el francés disponen en http://wims.auto.u-psud.fr/wims/faq/fr/program.html de programaciones de Secundaria y Bachillerato (recordatorio: Sixième corresponde a nuestro Sexto de Primaria, y es el primer curso de Secundaria en el sistema francés; la cuenta de cursos es descendente, sixième, cinquième…).
samente para integrar múltiples aportaciones (interfaz a otros ejecutables, creación interactiva de actividades…); pretende dar respuesta a casi todas las exigencias de la enseñanza realizada con ayuda del ordenador: generar actividades, clasificarlas y presentarlas al alumno, controlar acceso a clases, evaluar y seguir la evolución de los estudiantes. Tareas tan distintas admitirían, en la tradición Unix (pequeños programas que hacen una sola cosa pero la hacen bien y que son compatibles y complementarios), una solución más modular y fiel a estándares. Por poner unos ejemplos la traducción de los módulos es innecesariamente complicada porque los mensajes no están separados del código de ninguna manera identificable: es necesario comparar las versiones inglesa y francesa para averiguar qué fragmentos hay que traducir y cuáles no. Las actividades están escritas en un lenguaje de alto nivel de creación propia y sintaxis similar a la de LaTeX pero totalmente independiente de todo lo conocido. Por otro lado es difícil plantearse una comparación o un acercamiento a los estándares educativos IMS o SCORM. Esperamos que esta no tan breve introducción a WIMS haya sido interesante y útil. En el próximo número vamos a tratar un tema cada vez más urgente en nuestras escuelas: ¿cómo escribir otras lenguas y alfabetos? Antes era una pregunta que sólo hacían los profesores de griego y los traductores, ahora es una exigencia de la integración de nuestros nuevos alumnos chinos, árabes, ■ eslavos…
EL AUTOR
los ordenadores en clase: se ha observado que en una sesión WIMS los alumnos dedican más tiempo a pensar y al papel que al ordenador propiamente dicho. 6. Me voy a inventar la terminología: WIMS es agnóstico a la presencia. Dicho en un idioma terráqueo algo pedago-retórico, el sistema de clases virtuales facilita el trabajo tanto a distancia como presencial y permite un uso flexible de los recursos, los espacios y los tiempos. 7. El enseñante que utiliza un servidor WIMS puede trabajar con el gran número de ejercicios y Figura 4: La plataforma educativa epistemon. módulos libres disponibles (varios cientos), modificarlos, o escribir él mismo o solicitar la creación de código que se adapte a sus objetivos pedagógicos. Hay una comunidad internacional creciente de usuarios y desarrolladores de módulos WIMS. 8. El seguimiento completo de los alumnos de una clase virtual permite al profesor conocer fácilmente los progresos y dificultades de un alumno. WIMS proporciona estadísticas sobre el nivel de dificultad, el grado de éxito y el tiempo dedicado a la resolución de los ejercicios. 9. El servidor WIMS puede hacer Figura 5: WIMS integrado con epistemon. funciones de un pequeño gestor de contenidos educativos, permitir la comu(http://adullact.net/projects/ nicación entre alumnos en un foro, subir epistemon/), mediante la creación de documentos, etc. También es posible una interfaz entre la plataforma y el integrarlo en una plataforma educativa servidor WIMS, puesta en práctica en la (lo que en inglés se llama un Learning Universidad del Litoral francés (ver la Management System, LMS); mediante un figura 4). Los alumnos pueden trabajar modo que permite la colaboración con en un ejercicio WIMS dentro de una una de estas plataformas: lo que Xiao sesión de epistemon (figura 5); cuando llama «el protocolo para la conexión cierran la ventana de WIMS todos los directa de WIMS con otros servidores datos del ejercicio son enviados al LMS web» (http://localhost/wims/wims. para que los procese. cgi?lang=es&+module=adm/ 10. WIMS es esencialmente obra de raw&job=help). una sola persona; este carácter personal Nos informa Khaznadar (en correo tiene consecuencias positivas y negatipersonal) de que se está trabajando en vas. En este sentido es una aplicación la compatibilidad con epistemon muy creativa y original, diseñada expre-
LINUX USER
Juan Rafael Fernández García es profesor de educación secundaria y tiene una larga experiencia en la traducción y documentación del software libre. De hecho está colaborando en la traducción de los módulos y la interfaz de WIMS. Ha sido coordinador de uno de los Centros que participan en la experiencia andaluza de integrar las TIC en la educación y actualmente trabaja como asesor de formación del profesorado.
www.linuxmagazine.com.es
Número 03
83
LINUX USER
su, sudo
su, sudo
Identidad Para más seguridad, aunque tenga privilegios de root para un sistema, tiene sentido utilizarlos solo temporalmente para prevenir daños accidentales. su y sudo le permiten cambiar la identidad rápidamente desde la línea de ordenes. POR HEIKE JURZIK
L
os privilegios de root son necesarios para tareas administrativas, pero no tiene sentido ser el superusuario todo el tiempo. Es preferible convertirse en root para una tarea administrativa y luego volver a ser un usuario “normal”. Dos ordenes , su y sudo, le permiten cambiar de identidad.
su La orden su (“substitute user”) le permite cambiar su ID en la línea de ordenes. La orden lanza un nuevo intérprete de ordenes en segundo plano usando nuevos IDs de usuario (UID) y de grupo (GID). Cuando teclee su para convertirse en superusuario, u otro usuario con privilegios, deberá conocer la contraseña para la cuenta de ese usuario. La sintaxis básica del comando es su [-] [nombredeusuario]; pero hay una sutil diferencia, dependiendo de si teclea el signo menos o no . El signo menos (o alternativamente el parámetro
84
Número 03
www.linuxmagazine.com.es
-l o su forma larga --login) se asegura de que realmente entra en el sistema, fijando así las variables de entorno apropiadas y el intérprete de ordenes y cambiando al directorio de trabajo de ese usuario (su directorio ‘home’). Las variables de entorno no cambiaran si omite el signo menos y esto podría significar que el nuevo usuario no tiene ningún privilegio para el directorio actual (Véase la Figura 1). Si no suministra un nombre, se supondrá root, la cuenta del superusuario. Esto también es lo qué conduce a la falsa idea que su es realmente una abreviatura de “superuser”. Por omisión la orden su no permite al nuevo usuario lanzar aplicaciones X. Los usuarios externos primero deben tener permiso para utilizar el servidor de X para salida y esto significa editar el archivo .Xauthority en el directorio de trabajo adecuado (véase también man xauth). Para permitir al usuario root lanzar un programa X en un
su, sudo
Xterm que pertenezca al usuario petronella, necesita extraer una clave desde .Xauthority, añadirla al .Xauthority del administrador y entonces redefinir la variable DISPLAY (véase el Listado 1). su también le permite usar otra cuenta para lanzar una sola orden. Para hacer esto, indique la opción -c (--command):
Figura 1: Sin el apropiado ingreso en el sistema, no tiene ningún privilegio.
huhn@asteroid:~$ su -c"lessU /var/log/messages" Password:
El uso de la orden su se anota en la bitácora (log). En función de la distribución que use, esas entradas de bitácora se localizaran en /var/log/auth.log (p. e. en Debian) o en /var/log/messages (p. e. en Suse Linux). Los intentos inválidos son fácilmente localizados, permitiendo al usuario admin ver rápidamente quien ha intentado apropiarse indebidamente de los privilegios de root Dec 22 14:50:50 asteroidU PAM_unix[2108]: authenticationU failure; (uid=500) -> root for su service Dec 22 14:50:52 asteroidU su[2108]: pam_authenticate:U Authentication failure Dec 22 14:50:52 asteroidU su[2108]: - pts/8 huhn-root
Si es el usuario admin, no necesita introducir una contraseña después de teclear la orden su. Usted puede asumir cualquier identidad para probar rápidamente una modificación desde la perspectiva de otro usuario.
sudo La orden sudo le permite evitar dar a conocer la contraseña de root de una máquina, lo cual es comprensible por motivos de seguridad. La orden realiza lo
que el nombre sugiere: “sudo” es la abreviatura de “substitute user, do” (sustituye el usuario, haz) y facilita a usuarios individuales o grupos los privilegios administrativos por un período limitado y limitándose a una tarea especifica. Un usuario puede entonces simplemente teclear su propia contraseña para lanzar una orden privilegiada. El usuario admin necesita crear una lista de usuario autorizados a ejecutar ordenes especificas privilegiadas en el archivo /etc/sudoers. Mientras trabaja como root, edite el archivo con la orden visudo. este programa ofrece las características habituales del editor vi con algunas funciones adicionales. visudo “bloquea” el fichero /etc/sudoers para evitar que sea editado por multiples usuarios a la vez. Además visudo comprueba la sintaxis del fichero al terminar y le informa de cualquier error si lo encuentra: >>> sudoers file: syntaxU error, line 20 <<< What now?
Dispone de tres alternativas: pulsar e para editar el fichero de nuevo, x para cancelar los cambios y salir del editor o Q para salvar los cambios a pesar del error. Hay una entrada predeterminada para root ALL=(ALL) ALL en /etc/sudoers. Esto permite hacer todo al usuario root,
GLOSARIO UID: Cada usuario se identifica mediante un UID (“User IDentification number”), que lo mapea de manera única a la cuenta del usuario. Puede encontrar fácilmente su propio ID tecleando “echo $UID” GID: Además del UID, los usuarios tienen un GID (“Group IDentification number”) que indica su pertenencia a un grupo. Los miembros de un grupo pueden compartir privilegios. La orden “id” indica su UID y su GID actual.
LINUX USER
pero por supuesto root también puede hacerlo sin sudo. Si necesita conceder a otro usuario privilegios de root sin restricciones en una máquina, simplemente copie esta línea y sustituya root por el nombre de ese usuario. Después de salvar el archivo, este usuario podrá ejecutar órdenes de administración mediante sudo, por ejemplo: huhn@asteroid:~$ sudoU /sbin/shutdown Password:
Si no se permite al usuario usar sudo, aparecerá un mensaje como este: “sudo: huhn is not in the sudoers file. This incident will be reported.” (sudo: huhn no está en el archivo sudoers. Se informará de este suceso). La medida predeterminada, que puede ser cambiada en /etc/sudoers, es enviar un correo alertando al administrador con los detalles del usuario que ha intentado lanzar sudo (véase la Figura 2). Para estar seguros, los usuarios sin privilegios pueden teclear sudo -l para mostrar una lista de las ordenes permitidas.
Control Minucioso La sección Host alias specification de /etc/sudoers le permite especificar las máquinas donde las ordenes específicas de sudo deben aplicarse. Podemos utilizar el Host_Alias para crear un grupo de ordenadores mediante la especificación de sus nombre o definiendo un rango de direcciones IP. Esta característica solamente tiene sentido si aplicamos una configuración centralizada de sudo en múltiples ordenadores. La sección User_Alias le permite crear grupos que necesiten los mismos privilegios. Primero definimos el tipo de alias (p. e. User_Alias), después un nombre de alias (que puede contener mayúsculas, subrayados y números), un mapeo indicado por el signo “=” y finalmente los nombres de usuario separados por comas. Vamos agregar los usuarios huhn y petronella a un grupo que se le permite parar la máquina: # User alias specification User_Alias SHUTTERSDOWN=U petronella,huhn
www.linuxmagazine.com.es
Número 03
85
LINUX USER
su sudo
Figura 3: Se recomienda editar el fichero /etc/sudoers solamente con el Figura 2: La seguridad es muy valiosa; sudo informa de los accesos ilegítimos.
El próximo paso es definir un alias para la orden shutdown en la sección Cmnd alias specification. Para hacer esto, introduzca la ruta absoluta al programa requerido: # Cmnd alias specification Cmnd_Alias DOWN = /sbin/shutdown
Para decirle a sudo que los SHUTTERSDOWN estan autorizados a ejecutar esta orden, necesitamos otra entrada debajo de User privilege specification: SHUTTERSDOWN ALL = DOWN
Los usuarios del grupo SHUTTERSDOWN ahora pueden apagar la máquina tecleando sudo /sbin/shutdown. Pero hay una forma más fácil de otorgar a un solo usuario permiso para ejecutar una sola orden. Por ejemplo, la entrada:
programa /usr/sbin/visudo.
que el archivo se analiza desde arriba hacia abajo. Esto le permitirá mantener el grupo SHUTTERSDOWN, al cuál se le puede permitir ejecutar otras ordenes, mientras que al mismo tiempo se restringe a petronella el permiso para apagar la máquina. Si petronella intenta ejecutar la orden, simplemente le mostrará un mensaje como el siguiente: “Sorry, user petronella is not allowed to execute ‘/usr/sbin/visudo’ as root on asteroid.linux-magazine.com.” (Lo siento, el usuario petronella no tiene permiso para ejecutar ‘/usr/sbin/visudo’ como root en asteroid.linuxmagazine.com). Si quiere eliminar el indicador (prompt) de contraseña para una o varias ordenes, simplemente active el indicador NOPASSWD: SHUTTERSDOWN ALL=NOPASSWD:DOWN
huhn ALL = /usr/sbin/visudo
otorga al usuario huhns permiso para editar el archivo /etc/sudoers usando la orden sudo /usr/sbin/visudo.
En vez de reducir el nivel de la seguridad que sudo proporciona, puede incrementarlo, obligando al usuario que
Listado 1: Display
¿Libre o Restringido? Una simple entrada en /etc/sudoers le permite restar privilegios a un usuario individual. La sintaxis para hacer esto es como sigue: SHUTTERSDOWN ALL = DOWN petronella ALL = !DOWN
Es importante especificar la excepción inmediatamente después de la regla, ya
86
Número 03
01 02 03 04 05 06 07
petronella@asteroid:~$ xauth extract key $DISPLAY huhn@asteroid:~$ su Password: asteroid:~# xauth merge home/huhn/key asteroid:~# export DISPLAY=:0.0
www.linuxmagazine.com.es
introduzca la contraseña cada vez que ejecute sudo. Por omisión sudo ejecuta una especie de sistema de boletos con un intervalo que asegura, por ejemplo, que no pueda abrirse en la máquina una consola del intérprete de ordenes con privilegios de root que pueda comprometer todo el sistema sin excepción. La validez predeterminada para el boleto para la mayoría de las distros es de 15 minutos. Pero se puede configurar a 0 minutos añadiendo la siguiente línea a /etc/sudoers: Defaults timestamp_timeout = 0
Opcional sudotambién tiene algunos parámetros de línea de ordenes. Probablemente el más importante de ellos sea -s, que le permite lanzar un intérprete de ordenes como root. No es necesario configurar accesos al servidor X, solamente teclear sudo -s será suficiente para que el administrador lance programas sobre el servidor gráfico. El conmutador -L lista todas las opciones en el archivo /etc/sudoers. Si quiere extender su boleto sin ejecutar una orden, solo tiene que introducir sudo -v. Si el intervalo se ha agotado, se le indicara que teclee la contraseña. También puede dar de baja un boleto tecleando sudo -k. El indicador -b le permite ejecutar una orden en segundo plano; sin embargo, no podrá moverlo de nuevo al primer plano con la orden normal de control de trabajos del intér■ prete de ordenes, fg.
LaTeX
LINUX USER
LaTeX en Linux (3ª Parte)
La Tabla de Multiplicar (y otras) Con este artículo continuamos nuestro paseo por el mundo de la escritura con LaTeX. En las dos entregas anteriores hemos aprendido que LaTeX es un sistema de escritura profesional en el que, a pesar de no ser de tipo WYSIWYG, se obtienen resultados de calidad brillante con poco esfuerzo y donde fundamentalmente el escritor se dedica a contar en su documento lo que le interesa sin preocuparse del formato, que para eso LaTeX se ocupa de “todo”. POR JOSE MANUEL GONZÁLEZ VIDA
E
n esta penúltima entrega vamos a abordar en primer lugar la creación de tablas con LaTeX. Después trataremos la escritura matemática, donde podremos comprobar que LaTeX es infinitamente mejor y más potente que cualquier editor científico del tipo WYSIWYG. Posteriormente, en el próximo número, terminaremos nuestra serie sobre LaTeX viendo cómo incluir la bibliografía en nuestro documento (bien directamente o creándonos nuestra propia base de datos) y terminaremos con un ejemplo de un proyecto donde se usan todos los conceptos que hemos tratado en esta serie de artículos.
¿Cómo construir tablas con LaTeX? Las tablas son construcciones alineadas que aunque no son demasiado fáciles de construir con LaTeX, sin embargo éste permite una enorme flexibilidad en su construcción y manipulación. Como siempre lo mejor será que vayamos aprendiendo viendo un ejemplo: %Sintaxis de una tabla básica \begin{tabular}[<I>Posición<I>]U
{<I>FormatoColumnas<I>} Fila1_Columna1 & Fila1_Columna2U & \dots & Fila1_ColumnaN \\ Fila2_Columna1 & Fila2_Columna2U & \dots & Fila2_ColumnaN \\ \dots & \dots & \dots & \dots \\ FilaM_Columna1 & FilaM_Columna2U & \dots & FilaM_ColumnaN \end{tabular}
Como se puede comprobar, el entorno que LaTeX usa para construir tablas es el entorno tabular con determinados argumentos obligatorios y opcionales que vamos a ir viendo. La Posición es un argumento opcional e indica la posición vertical de la tabla respecto de la línea en la que se ha incluido. Puede tomar uno de los tres valores siguientes: • t: la línea inferior de la tabla se alinea con la línea base de la línea actual. • b: la línea superior de la tabla se alinea con la línea base de la línea actual. • c: es la opción que se toma por defecto y alinea la tabla de manera centrada respecto de la línea base.
El argumento FormatoColumnas se refiere a la alineación de las columnas. Siempre debe aparecer una entrada por cada columna de la tabla. Se pueden incluir ciertos elementos opcionales (separadores para delimitar los bordes entre cada columna -los veremos en el siguiente ejemplo-). Las posibilidades son: • l: alineación a la izquierda. • r: alineación a la derecha. • c: alineación centrada de la columna. • p{ancho}: crea una columna de anchura ancho. El texto que se coloque dentro se trata como un párrafo (sin sangría inicial) con la línea superior alineada con las otras columnas. Los Separadores son elementos opcionales. Pueden tomarse entre los siguientes: • |: introduce una línea vertical. • ||: introduce dos líneas verticales. • @{texto}: elimina el espacio entre columnas e inserta el texto señalado entre las columnas especificadas. Una vez vistos todos los argumentos del entorno tabular es el momento de pasar
www.linuxmagazine.com.es
Número 03
87
LINUX USER
LaTeX
Figura 1: Un primer ejemplo de una tabla.
Figura 2: Una tabla con una “multicolumna”.
a la práctica escribiendo en nuestro editor de texto el siguiente ejemplo: 01 \documentclass[a4paper,12pt] {article} 02 \usepackage[latin1]{inputenc} 03 \usepackage[T1]{fontenc} 04 \usepackage[spanish]{babel} 05 \begin{document} 06 \begin{tabular}{|l|c|c|r|} 07 {\bf Nombre} & {\bf Apellidos} & {\bf DNI} & {\bf Calificación} \\ 08 Juan & López & 43434322L & 5.3 \\ 09 Emilio & Pérez & 45989845K & 7.2 \\ 10 Gema & Gutiérrez & 21388383A & 8.1 11 \end{tabular} 12 \end{document}
El resultado de compilar el ejemplo anterior lo tenemos en la Figura 1. Podemos observar en el listado de nuestro ejemplo que no hemos usado los argumentos opcionales y que en el formato de las columnas hemos escogido separadores simples para las columnas verticales. Otro detalle importante que conviene observar es la utilización de los símbolos & y \\ en las distintas filas de la tabla que
hemos construido. Con el símbolo & separamos las distintas columnas en una fila. Podemos dejar una casilla vacía colocando dos && o bien dejando un espacio en blanco entre ellos. Con las dos barras \\ indicamos a LaTeX que comienza una nueva fila. Para separadores horizontales tenemos el comando \hline que dibuja una línea horizontal entre fila y fila. Debe aparecer justo antes de la primera fila o justo después de \\ si está entre dos filas. Dos comandos \hline seguidos dibujan dos líneas horizontales con un pequeño espacio entre ellas. \cline{n - m} dibuja una línea horizontal entre las columnas n y m. Si retocamos el ejemplo anterior cambiando la tabla usando el siguiente código:
Obtenemos una tabla. Ahora me gustaría que probaseis a sustituir la tabla de nuestro ejemplo por la siguiente
\begin{tabular}{|l|c|c|r|} \hline {\bf Nombre} & {\bf Apellidos}U & {\bf DNI} & {\bfU Calificación} \\ \hline \hline Juan & López & 43434322L &U 5.3 \\ Emilio & Pérez &U 45989845K & 7.2 \\ Gema & Gutiérrez &U 21388383A & 8.1 \\ \hline \end{tabular}
El resultado, como podemos observar en la Figura 2, difiere del anterior en que hemos empleado el comando \multicolumn que se usa para unir varias columnas de una misma fila. \multicolumn usa como argumentos el número de columnas a unir, la alineación del texto a incluir en la “multicolumna” y, por último, el texto que deseamos incluir. Por último probad a sustituir la tabla anterior por la siguiente:
Tabla 1. Algunas fórmulas matemáticas sencillas Instrucción
Uso
_{subíndice}
Texto en subíndice
^{superíndice}
Texto en superíndice
\sqrt[n]{radicando}
Raíz enésima del radicando
\frac{numerador}{denominador}
Cociente entre el numerador y el denominador
88
Número 03
www.linuxmagazine.com.es
\begin{tabular}{|l|c|c|r|} \hline {\bf Nombre} & {\bfU Apellidos} & {\bf DNI}U & {\bf Calificación} \\ \hline Juan & López & 43434322LU & 5.3 \\ Emilio & Pérez & 45989845KU & 7.2 \\ Gema & Gutiérez &U \multicolumn{2}U {c|}{Dos celdas unidas} \\ \hline \end{tabular}
\begin{tabular}{|@{\bfU Capítulo: } r@{\qquadU Temas: }c@{ - }c|} \hline 1 & 1 & 5 \\ 2 & 6 & 9 \\ 3 & 10 & 14 \\ \hline \end{tabular}
Figura 3: Un ejemplo de escritura en modo texto y en modo matemático.
Fijaros en que en este ejemplo los separadores de las columnas son las palabras que hemos incluido en los argumentos del entorno tabular.
Tablas como objetos flotantes Recordareis que en el artículo del número anterior explicábamos el concepto de objeto flotante basándonos en la idea de que las figuras son objetos indivisibles y por tanto pueden “flotar” y ser reubicadas en nuestro documento (dentro de unas determinadas pautas) con el fin de que el aspecto global del documento cumpla nuestras expectativas. En este sentido las tablas no deberían (aunque hay excepciones) ser separadas en más de una página, por tanto su ubicación debe ser determinada por el compilador. Para tratar las tablas como objetos flotantes disponemos del entorno table. Su sintaxis es: %Sintaxis del entorno table \begin{table} Entorno tabular \caption{Pie de la tabla} \label{Etiqueta} \end{table}
Las tablas, al igual que las figuras, pueden llevar su etiqueta con el fin de referenciarlas en nuestro documento y también su pie, que nos servirá también para crear el índice de tablas.
Modo Texto y Modo Matemático Básicamente LaTeX distingue el texto matemático según se introduzca a lo
Figura 4: Un ejemplo de escritura matemática con fórmulas sencillas.
largo del párrafo que se está escribiendo o en párrafos separados. El texto de tipo matemático introducido en la misma línea de escritura (modo texto) ha de ser introducido entre los símbolos $ y $. Para introducir el texto matemático en líneas separadas se suele hacer encerrándolo entre los símbolos $$ y $$ o bien entre los símbolos \[ y \]. Introducimos el siguiente ejemplo dentro de un documento LaTeX con las cabeceras estándares que estamos usando y lo compilamos. Sean $x$, $y$ y $z$U funciones de $u$ y $v$, continuas en un dominioU $D$ del plano $u,v$. El conjunto de puntosU dados por: $$ \vec{r}(u,v)=(x(u,v),yU (u,v),z(u)), $$ se llama superficieU paramétrica.
El resultado debe ser parecido al que mostramos en la Figura 2. Observemos que los caracteres que usa LaTeX para la escritura en modo matemático son distintos a los hemos visto hasta ahora. Se trata de letras ligeramente cursivas y se emplea una fuente más redondeada.
El Entorno Equation Es frecuente, cuando se escriben textos científicos, hacer referencias a determinadas fórmulas que aparecen en el texto.
Para ello en LaTeX emplearemos el entorno equation. La sintaxis que tiene este entorno es: %Sintaxis del entorno equation \begin{equation} \label{Etiqueta} Fórmula \end{equation}
Este entorno numera automáticamente las ecuaciones utilizando el contador denominado equation. De este modo podemos hacer referencia a las distintas fórmulas con los comandos \ref{Etiqueta} y \pageref{Etiqueta}. Además también disponemos del comando \eqref{Etiqueta} que, a diferencia de los anteriores, encierra el número asignado a la ecuación entre paréntesis. A diferencia del modo texto, en modo matemático LaTeX presenta un comportamiento distinto, es decir, además de usar una fuente distinta y con letras de tipo itálico, no respeta los espacios entre palabras, sólo deja espacios cuando lo considera necesario. No se permite escribir vocales acentuadas ni la “ñ” en el modo matemático. LaTeX se ocupa de modo automático de elegir los tamaños adecuados de letra adecuados a diversas circunstancias (fracciones, superíndices o subíndices, etc.).
Algunas Fórmulas Sencillas En la Tabla 1 mostramos la forma de escribir super y subíndices, raíces desde cuadradas a cualquier orden, fracciones, etc. Una vez que veamos la sintaxis a usar en esta tabla, podemos escribir el
www.linuxmagazine.com.es
Número 03
89
LINUX USER
LaTeX
Figura 5: Una función definida a trozos.
siguiente ejemplo en el cuerpo de nuestro documento: Sea $p(x)=a_0+a_1x+a_2x^2+U \cdots +a_nx^n$. Sea $p(x)=\sqrt{a_0}+\sqrt[3]U {a_1}x+\sqrt{a_2}x^2+ \cdotsU +a_nx^n$. Sea $p(x)=\frac{a_0}{a_n}+\sqrtU [3]{a_1}x+\sqrt{a_2}x^2+ \cdotsU +a_nx^n$.
Lo compilamos y visualizamos el resultado, que debe ser parecido al que mostramos en la Figura 4.
El paquete amsmath El paquete amsmath es una extensión para LaTeX que proporciona nuevas características para facilitar la escritura de fórmulas matemáticas y mejorar la calidad tipográfica del documento final. Como regla general incluiremos siempre este paquete en nuestros documentos cuando éstos contengan fórmulas y no distinguiremos en esta sección los comandos propios de LaTeX de los que nos proporciona el paquete amsmath. Hemos visto antes que cuando escribimos texto en modo matemático LaTeX no respeta los espacios, y entonces ¿cómo incluir texto en nuestras fórmulas? La respuesta se halla en el comando \text{texto a incluir}. El texto que incluyamos dentro de este comando será tratado exactamente como los textos que hemos visto hasta ahora. También tenemos en LaTeX otra serie de comandos que nos proporcionan la posibilidad de dejar espacios de distinto tamaño en nuestras fórmulas en modo
90
Número 03
Figura 6: Uso de estructuras de tipo teorema.
matemático. Los podemos encontrar en la Tabla 2.
Construcciones Especiales en Modo Matemático Como estaréis comprobando el modo matemático da mucho de sí en LaTeX. En este apartado vamos a aprender a construir matrices y lo que se denominan funciones definidas a trozos. Si imaginamos una matriz en matemáticas podemos pensar que para escribirla con LaTeX hay que usar el entorno tabular que vimos antes pero este entorno es válido sólo en modo texto. El entorno equivalente en modo matemático es array. Su sintaxis es parecida a la del entorno tabular. Lo vemos en el siguiente ejemplo: 01 \documentclass[a4paper, 12pt]{article} 02 \usepackage[latin1]{inputenc} 03 \usepackage[T1]{fontenc} 04 \usepackage[spanish]{babel} 05 \usepackage{amsmath} 06 \begin{document} 07 $$ 08 \left( 09 \begin{array}{ccc} 10 1 & 2 & 3 \\ 11 4 & 5 & 6 \\ 12 7 & 8 & 9 13 \end{array} 14 \right) 15 $$ 16 \end{document}
El resultado obtenido al compilar, hablando sólo en términos de formato, es una tabla (como las del entorno tabular) precedida y terminada por unos paréntesis
www.linuxmagazine.com.es
que se adaptan al tamaño de la misma. Pues bien, el entorno array permite ir precedido por el comando comandos \left y terminado por \right. Observemos que en nuestro ejemplo hemos escrito el símbolo ( justo después del comando \left y ) justo después del comando \right. Son estos comandos los que hacen que el símbolo que colocamos justo después adapte el tamaño del array. Además permiten estructuran un poco más especiales. Escribid el siguiente código en el cuerpo del ejemplo anterior: $$ f(x)= \left\{ \begin{array}{ll} 1 & \mbox{ si $x>1$} \\ 0 & \mbox{ en el resto deU los casos} \end{array} \right. $$
El resultado de compilar el ejemplo anterior lo tenemos en la Figura 5. Se trata de una función definida a trozos, que de hecho, no es más que un array de dos columnas que va precedido de un símbolo de llave ({) y que no se cierra con otra llave (fijaros que para no cerrar el array con un símbolo usamos \right.). Además hemos usado otro nuevo comando \mbox que nos sirve al igual que el \text para poder escribir texto dentro del modo matemático.
Simbología Matemática La simbología matemática en LaTeX es increíblemente extensa y abarca varios
LaTeX
dor propio del entorno que hemos creado. Para las demostraciones podemos usar el paquete amsmath que contiene el entorno proof. Este entorno produce un encabezamiento con la palabra Proof. y produce un símbolo en forma de cuadradito al final. Para redefinir el encabezamiento ejecutaremos el siguiente código dentro de nuestro documento (da igual si se hace en el preámbulo o en el cuerpo del mismo):
Tabla 2. Espaciados en Modo Matemático Comando
Abreviatura
\thinspace
\,
pequeño
\medspace
\:
mediano
Espacio proporcionado
\thickspace
\;
grande
\negthinspace
\!
espacio negativo pequeño
\negmedspace
espacio negativo mediano
\negthickspace
espacio negativo grande
miles de símbolos que van desde las clásicas letras griegas, todo tipo de flechas, operadores binarios, funciones matemáticas y un largo etcétera que por razones de espacio no podemos incluir aquí pero que podemos encontrar en el libro “Una Descripción de LaTeX2e” realizado por Tomás Bautista, sobre el trabajo inicial de Hubert Partl, Irene Hyna, Elisabeth Schlegl y Tobias Oetiker y del que hemos puesto un enlace a una versión en PDF en el punto [3] de la bibliografía de este artículo. Además, a modo de ejemplo, os he incluido en la Figura 7cómo se escriben todas las letras clásicas griegas con LaTeX.
13 \end{teorema} 14 \begin{lema}[Lema de fulanito] 15 Esto es una lema 16 \end{lema} 17 \end{document}
\renewcommand*{\proofname}U {Demostración}
El resultado de compilar el texto anterior lo mostramos en la Figura 6. ¿Qué hemos conseguido? Pues mediante el comando \newthorem hemos creado nuestros propios entornos y les hemos asignado un nombre de entorno y un contador propio. Me explico, mediante la línea \newtheorem{teorema}{Teorema} esta-
Teoremas y Demostraciones Otros elementos comunes dentro de artículos de investigación y libros de contenido matemático son los teoremas y demostraciones. Atendiendo al sistema de numeración llamaremos entornos de tipo teorema a estructuras de tipo teorema, proposición, lema, corolario, definición, conjetura, etc. En LaTeX tenemos el comando \newtheorem que nos permitirá definir en nuestro documento tantos entornos de tipo teorema como necesitemos. Como siempre, lo mejor es comprender su manejo con un ejemplo: 01 \documentclass[a4paper,12pt] {article} 02 \usepackage[latin1]{inputenc} 03 \usepackage[T1]{fontenc} 04 \usepackage[spanish]{babel} 05 \begin{document} 06 \newtheorem{teorema}{Teorema} 07 \newtheorem{lema}{Lema}[section] 08 \begin{teorema} 09 Aquí tenemos un teorema\dots 10 \end{teorema} 11 \begin{teorema} 12 Y aquí otro.
LINUX USER
En el siguiente ejemplo os muestro cómo se usa. 01 \documentclass[a4paper, 12pt]{article} 02 \usepackage[latin1]{inputenc} 03 \usepackage[T1]{fontenc} 04 \usepackage[spanish]{babel} 05 \begin{document} 06 \renewcommand*{\proofname} {Demostración} 07 \begin{proof} 08 Prueba del resultado\dots 09 \end{proof} 10 \end{document}
Conclusión Figura 7: Las letras griegas con LaTeX.
mos creando un nuevo entorno que se llama teorema de tal manera que cada vez que usamos un entorno de este tipo actualizamos un contador que va desde el 1,2,… y creamos un texto que comienza con Teorema x seguido del enunciado que queremos escribir dentro de este entorno (fijaros en el ejemplo anterior). Pero a veces nos puede gustar más que el contador de un entorno de este tipo vaya ligado a la sección donde se encuentra, con el fin de que, al referenciarlo, el lector sepa en qué sección tiene que buscarlo. ¿Cómo se hace? Pues muy fácil, en el ejemplo anterior hemos creado un entorno con nombre lema y cuyo contador está referenciado a las secciones (mirad en el ejemplo cómo ha resultado). El contador resultante lleva en primer lugar el número de la sección actual y separado con un punto el conta-
Con lo visto hasta ahora sois ya unos casi LaTeXpertos, pero remataremos nuestros conocimientos en la próxima entrega donde podremos ver a LaTeX en todo su esplendor, creando un proyecto con capítulos, índices, figuras, tablas, bibliografía y ¡todo de manera automática! Además os pondremos en nuestra página http://www.linux-magazine.com. es los listados de este proyecto para que los tengáis de referencia para vuestros ■ propios trabajos.
RECURSOS [1] El libro de LaTeX. B. Cascales y otros. Ed. Prentice Hall. 2003. [2] LaTeX, a document preparation system. L. Lamport. 2ª Ed. Ed. Addison-Wesley. 1994. [3] “Una Descripción de LaTeX2e”.Tomás Bautista. http://www.iuma.ulpgc.es/ users/bautista/other/tex/ldesc2e/misc/ ldesc2e.pdf
www.linuxmagazine.com.es
Número 03
91
LINUX MAGAZINE
Humor
Nuevas licencia, nuevos retos
Autores al Gulag S
egún la CCCP (Cooperativa de Corporaciones de Comunicación y Producción), debida a la laguna legal abierta por licencias tipo Creative Commons y creciente número de denuncias infundadas de algunos autores por los abusos practicados por parte de ciertas empresas del sector de las comunicaciones con sus obras, existe la necesidad de un tipo de licencia intermedia, que tanto proteja los derechos de las corporaciones como defina los deberes de los autores para con las corporaciones de la comunicación y que exima a éstas últimas de responsabilidades legales derivadas de la mala fe y ambiguas interpretaciones que hacen los autores de las condiciones descritas en las licencias actuales. Para los autores, la CCCP propone el GULAG (Granted User’s License And Guarantee - Licencia y Garantía de Cesión a Usuarios), un texto que servirá como alternativa a las licencias CC habituales y que prevalecerá sobre éstas en caso de conflicto. José Estallín, presidente de la CCCP, nos comenta: “No hay diferencias sustanciales entre los términos de una licencia CC actual y un GULAG. La única diferencia es la seguridad jurídica que otorga nuestra licencia”. Como muestra, un botón: Reproducimos a continuación la lista de restricciones del texto del GULAG, para que los autores y autoras se convenzan de de la buena fe para llegar a un entendimiento que posee la CCCP: . . . Restricciones a.- Usted puede reproducir, distribuir o comunicar públicamente la obra solamente bajo términos de esta licencia y debe incluir una copia de la misma, o su Identificador Uniforme de Recurso (URI), con cada copia o grabación de la obra que usted reproduzca, distribuya o comunique públicamente. Usted no puede ofrecer o imponer ningún término sobre la obra que altere o restrinja los términos de esta licencia o el ejercicio de sus derechos por parte de los cesionarios de la misma.
92
Número 03
Usted no puede sublicenciar la obra. Usted debe mantener intactos todos los avisos que se refieran a esta licencia y a la ausencia de garantías. Usted no puede reproducir, distribuir o comunicar públicamente la obra con medidas tecnológicas que controlen el acceso o uso de la obra de una manera contraria a los términos de esta licencia. b.- Bueno, je, en lo que se refiere a lo anterior, vaaaale, yo a usted sí le dejo reproducir, distribuir o comunicar públicamente la obra bajo términos de esta licencia o cualquier otra que se le ocurra. Después de todo ¿quien va a saber más de esto? Yo no quiero ir de nada. c.- Y en cuanto a lo de que “debe” incluir una copia de la licencia, pues mire, siempre y cuando le parezca a usted bien, porque no veas el precio al que se han puesto las fotocopias con la subida de los hidrocarburos. Y si la obra le llega en formato electrónico, mucho peor: Yo tampoco consigo acordarme nunca de como se copia y pega. d.- Tampoco quisiera abusar con lo de que no puede ofrecer o imponer ningún término sobre la obra que altere o restrinja los términos de esta licencia. Vamos, que si cree que algo se puede mejorar, pues usted sabrá. Adelante. ¿Podría usted avisarme cuando…? Bueno, mejor me callo que ya han hablado con mi jefe y de momento me puedo ir despidiendo de la cesta de Navidad con el chopped y el Delapierre Glasé.
www.linuxmagazine.com.es
f.- En lo que se refiere a lo de “no poder sublicenciar la obra”, bueno, eso es una errata. Se me fue el dedo y lo que debería decir es “no quiero que presionen a mi banco para que me embarguen el piso por ponerme demasiado pesado con lo de mis derechos”. g.- ¿Qué si lo de la reproducción…? Sí, claro hombre: tache, tache. Ya se sabe, eso se pone por poner. Venía escrito de serie y yo ni me había fijado. Oiga, si yo firmo esto ¿conseguirán que vuelvan a admitir a mi padre en la lista de candidatos para un trasplante de corazón? h.- Muy bien, muy bien, hagan lo que quieran con mi obra: modifíquenla, manipúlenla, distribúyanla, tergivérsenla, saquen mis palabras de contexto o hagan que diga justo lo contrario de lo que dije en el original, con mi consentimiento expreso o sin él, citándome como el autor o a su sobrino el de Cuenca, me da igual. Pero por favor, por favor, por favor, devuélvanme a mi familia. . . . No hay nada que temer. (Dedicado a Mercè Molist y a Bill Gates. A la primera deseándole lo mejor en su lucha para que prevalezcan sus derechos - ver http://barrapunto.com/ article.pl?sid=04/11/12/1522255 -. Al segundo por mira con qué nos sale ahora: http://news.com.com/ Gates+taking+a+seat+in+your+de n/2008-1041_3-5514121. ■ html?tag=nefd.ac.)
Proyectos
COMUNIDAD
Software Libre y sus Creadores
Proyectos en Marcha El software libre incluyes un abanico tan amplio de aplicaciones que puede ser difícil encontrar la herramienta perfecta. En esta sección, escogemos lo mejor de la cosecha. Este mes probamos FlightGear, un fabuloso simulador de vuelo, y Amarok, un reproductor musical de nueva generación.
V
olar… un sueño para los humanos desde la antigüedad. Grandes genios han dedicado su tiempo e inteligencia a intentar construir aparatos voladores. Curiosamente, hoy en día, cuando el coste de volar con compañías comerciales está al alcance de todo el mundo, existe un creciente número de programas, que permiten surcar los aires desde el salón de tu casa.
Despegue con FlightGear Microsoft introdujo un simulador de vuelo ya hace tiempo, pero este producto no corre en Linux. Sin embargo, como bien sabemos, la comunidad del código abierto es autosuficente: FlightGear trae la experiencia de sentarse a los mandos de un avión a tu escritorio favorito. Y aterriza con licencia GPL. Los desarrolladores de FlightGear dicen que el programa es el resultado de su disconformidad con simuladores de vuelo comerciales; el hecho de que el código de MS fuera cerrado impedía que se añadieran extensiones y mejoras de terceros.
Ronald Raefle, visipix.com
POR MARTIN LOSCHWITZ
FlightGear rápidamente se convirtió en un proyecto con ambiciones globales. Innumerables programadores de todo el mundo trabajan ahora en este simulador de vuelo.
Descarga Gigantesca El paquete FlightGear básico, con varios modelos de aviones y un pequeño mapa de San Francisco (Figura 1), pesa más de 90 Mbytes. Y se necesitan mas mapas digitales FlightGear para el resto del mundo. Si la descarga es demasiado para tu conexión a Internet, puedes pedir el paquete completo de FlightGear en la página de inicio de FlightGear [1]. El paquete viene con tres DVDs u once CDs, conteniendo un total de 12 Gbytes de datos. A pesar de ello, los diferentes sectores del mundo pueden descargarse por separado. Después de completar la instalación, los usuarios simplemente pueden teclear fgfs para arrancar Flightgear. Arrancar el programa sin ninguna opción nos coloca en un Cessna en la mencionada zona de vuelo de San Francisco. Un joystick es
perfecto para el control de un avión, pero también se puede utilizar un ratón. En el modo estándar, el ratón se utiliza para operar la instrumentación de la carlinga y acceder a los programas de los menús. Al hacer clic con el botón derecho, se cambia a modo joystick. Otro clic derecho y se cambia la perspectiva. Se puede ver el avión desde fuera (a ambos lados, vista frontal o vista de pájaro), pero los jugadores preferirán la vista desde el asiento del pilot. Si el Cessna nos sabe a poco, simplemente hemos de seleccionar un nuevo avión. Disponemos de una gran variedad de aviones, desde un Boeing 747 hasta un Antonov (ver Figura 2), así como dos cazas: el F16 y el prototipo de un Northrop/McDonell Douglas. Para los apasionados de la historia de la aviación, existe hasta un modelo del primer avión creado por los hermanos Wright, el Wright Flyer. Existen muchos otros modelos en Internet, desarrollados por los aficionados a FlightGear. A diferencia de simuladores de vuelo comerciales, FlightGear es bastante fru-
www.linuxmagazine.com.es
Número 03
95
COMUNIDAD
Proyectos
desplegable de artistas, la que permite al usuario seleccionar pistas o artistas individuales y añadir pistas a la lista de reproducción. La vista contextual muestra a los usuarios detalles sobre la pista en reproducción. Aparte del título y el nombre del artista, incluye estadísticas sobre la frecuencia con el que se ha reproducido la canción, cuando se reprodujo por primera vez, y cuando fue la última vez
gal en lo que se refiere a sus exigencias de hardware. Necesitaremos un adaptador de gráficos bastante reciente con soporte para aceleración 3D OpenGL. Sin embargo, es bastante difícil dominar el mundo del pilotaje virtual y el manual en la página de inicio de FlightGear nos da un rápido repaso de los instrumentos y teclas más importantes.
Amar a Amarok A medida que Linux ha invadido los escritorios, el número de aplicaciones de entretenimiento ha ido en aumento, entre ellas, los reproductores de música MP3 y Ogg. A pesar de que los puristas puedan preferir la herramienta de la línea de comandos mpg123 [2], los usuarios de GUIs están bastante contentos con el clon Winamp, Xmms, o la herramienta estándar de KDE, Noatun. Ambos programas tienen sus desventajas. Por un lado, ambos tienen interfaces bastante estáticos. Xmms puede utilizar skins de Winamp, siempre y cuando sean para la versión 2 del programa de Windows, ya que los desarrolladores de Winamp diseñaron un nuevo sistema de skins por que creían que la anterior versión era muy aburrida. Noatun cambia según el tema que se aplique a KDE, sin ningún extra. La segunda desventaja es que ninguno de los dos ayuda al usuario a administrar una gran colección de música. Tanto Xmms como Noatun trabajan con listas
96
Número 03
de reproducción sencillas, almacenando los caminos a los ficheros de audio consecutivamente en un fichero de texto. Ya hace algún tiempo que Amarok [3] entró en escena como nuevo reproductor de audio con la intención de resolver ambos problemas. Amarok está pensado principalmente para usuarios de KDE y esto se hace patente al no disponer de un plugin para el acceso directo al módulo Alsa del kernel, sino que hace uso de sistema de sonido Arts de KDE, aunque existen extensiones para los motores GStreamer y Xine. El GUI de Amarok muestra un lista de reproducción completa con abundante información sobre la pista actual, el artista y otras listas de reproducción. Si se requiere, el reproductor puede mostrar una ventana separada de reproducción al estilo de Xmms para visualizar la salida músical. Existe un creciente número de plugins para extender las características estándar. Al igual que otros programas, Amarok cuenta con una lista de reproducción que permite ver cual es la siguiente pista, sin embargo, el programa permite al usuario compilar listas de reproducción flexiblemente a partir de varias colecciones. Para hacer esto, los usuarios definen uno o más directorios fuentes de ficheros de sonido donde Amarok buscará. A continuación, la aplicación muestra un lista
www.linuxmagazine.com.es
que se escuchó. Debajo de esta información, el programa muestra otras pistas del mismo álbum y las pistas mejor puntuadas del mismo artista, puntuación ésta basada en el ranking Amarok. Por que Amarok clasifica cada canción según tus gustos personales, sí, subiendo una pista en el ranking basándose en las veces que se reproduce y bajándolo si no se escucha tan menudo o se reproduce mal. Este sistema permite a Amarok crear gradualmente una lista con las pistas favoritas de cada usuario. En lo que se refiere a skins, Amarok no tiene mucho que ofrecer: los usuarios pueden cambiar los colores de fondo y del panel a su gusto y el aspecto se adapta los temas por defecto de Qt. A pesar de lo anterior, la potencia de Amarok en lo que se refiere a la administración de listas de reproducción, lo convierten en un serio competidor para el resto de los repro■ ductores de música.
RECURSOS [1] FlightGear: http://www.flightgear.org [2] Mpg123: http://www.mpg123.de [3] Amarok: http://amarok.kde.org/
Eventos
LINUX MAGAZINE
Eventos Seleccionados
LinuxWorld Expo
FOSDEM 2005
LinuxPark CeBIT 2005
Fecha: 14–17 Febrero
Fecha: 26–27 Febrero
Fecha: 10-16 Marzo
Ciudad: Boston, MA, EE.UU.
Ciudad: Bruselas, Bélgica
Ciudad: Hannover, Alemania
Sitio Web: www.linuxworld expo.com
Sitio Web: www.fosdem.org
Sitio Web: www.cebit.de/ homepage_e
Calendario de Eventos Evento CodeCon 4.0 Southern California Linux Expo LinuxWorld Conference & Expo UKUUG LISA/Winter Conference FOSDEM 2005 Solutions Linux Linux Park CeBIT 2005 O’Reilly Emerging Technology Conference Novell BrainShare 2005 YAPC::Taipei 2005 Festival Latinoamericano de Instalación de Software Libre LinuxWorld Conference & Expo, Canada MySQL Users Conference & Expo 2005
Fecha 11-13 Febrero 12 Febrero 14-17 Febrero 24-25 Febrero 26-27 Febrero 01-03 Marzo 10-16 Marzo 14-17 Marzo 20-25 Marzo 26-27 Marzo 2 de Abril 18-20 Abril 18-21 Abril
linux.conf.au 18-23 Abril 3rd International Linux Audio Conference 21-24 Abril GUADEC 2005 29-31 Mayo I Congreso de Tecnologías del Software Libre 7-8 Julio
Ciudad San Francisco, CA, EE.UU. Los Angeles, CA, EE.UU. Boston, MA, EE.UU. Birmingham, R.U. Bruselas, Bélgica París, Francia Hannover, Alemania San Diego, CA, EE.UU. Salt Lake City, UT, EE.UU. Taipei,Taiwan Venezuela, Argentina y Colombia Toronto, Canadá Santa Clara, CA, EE.UU. Canberra, Australia Karlsruhe, Alemania Stuttgart, Alemania A Coruña
Sitio Web www.codecon.org/2005 www.socallinuxexpo.org www.linuxworldexpo.com www.ukuug.org/events/winter2005 www.fosdem.org www.solutionslinux.fr www.cebit.de/homepage_e conferences.oreillynet.com/etech www.novell.com/brainshare taipei.pm.org http://ingenieria.ean.edu.co/~azul/ svnwiki.cgi/colibri/fisl www.linuxworldcanada.com www.mysql.com/news-and-events/usersconference conf.linux.org.au/ www.zkm.de:81/lac http://2005.guadec.org http://congreso.gpul.org
Información de Contacto Director Paul C. Brown Coolaboradores Paul C. Brown, Jose Manuel González Vida, Juan Rafael Fernández, Pedro Orantes, José María Ruíz Traductores Paqui Martín Vergara, Paul C. Brown, Jesús Reyes Delgado, Antonio Rueda. Maquetación Sergio Hardasmal Diseño de Portada Paul C. Brown, Pinball (info@pinball-werbeagentur.de) Publicidad www.linuxmagazine.com.es/pub/ Para España Paul C. Brown pbrown@linuxmagazine.com.es pbrown@linuxnewmedia.es Tel.: (+ 34) 951 010 556 Móvil.: (+ 34) 655 036 836 Fax.: (+ 34) 951 010 516 Sergio Hardasmal anuncios@linuxmagazine.com.es Tel.: (+ 34) 951 010 556 Para Alemania, Austria y Suiza Osmund Schmidt anzeigen@linux-magazine.com Tel.: (+49) 6335 9110 Fax.: (+49) 6335 7779
Para el Resto del Mundo Brian Osborn ads@linux-magazine.com Tel.: (+49) 6509 910 495 Fax.: (+49) 6509 910 497 Director Editorial Paul C. Brown Director de Producción Sergio Hardasmal anuncios@linux-magazine.com Subscripciones: www.linuxmagazine.com.es/ magazine/subs Precios Subscripción (12 números + 1 DVD cada 3 números) España: 49,50 € Europa: 59,90 € Resto del Mundo - Euros: 79,90 € Resto del Mundo - Dólares U.S.A.: $94,90 € Tel.: (+34) 951 010 556 Fax.: (+34) 951 010 516 subs@linuxmagazine.com.es Linux Magazine Linux New Media Spain, S.L. Avda. Juan López Peñalver, 21 29590 - Campanillas Málaga ESPAÑA info@linuxnewmedia.es Tel.: (+34) 951 010 556 Fax.: (+34) 951 010 516
www.linuxmagazine.com.es - España www.linux-magazine.com - Mundo www.linux-magazine.de - Alemania Si bien se toman todas las medidas posibles para garantizar la precisión del contenido de los artículos publicados en Linux Magazine, la editorial no se hace responsable de imprecisiones aparecidas en la revista. Asimismo, Linux Magazine no comparte necesariamente las opiniones vertidas por sus colaboradores en sus artículos. El riesgo derivado del uso del DVD y el material que contiene corren por cuenta del lector. El DVD es estudiado escrupulosamente para confirmar que está libre de virus y errores. Copyright y Marcas Registradas © 2004 Linux New Media Spain, S.L. Linux New Media Spain S.L. prohíbe la reproducción total o parcial de los contenidos de Linux Magazine sin su permiso previo y por escrito. Linux es una Marca Registrada de Linus Torvalds. Impreso en Alemania Impresión: Dierichs Druck + Media GmBH Distribución: SGEL
www.linuxmagazine.com.es
Número 03
97
PRÓXIMO NÚMERO
Número 3
... Y Además Abril 2005: Número 4
Próximo Número Especial Wireless Las redes inalámbricas son geniales… si consigues configurarlas. Sin embargo, la gran variedad de dispositivos (no siempre compatibles) y el problema de integrar el hardware con el sistema de software, a menudo intimidan hasta el administrador más experimentado. El mes que viene
mostramos como configurar Linux en una red wireless. Nuestros especialistas en LANs inalámbricas abordarán una amplio espectro de temas relacionados: Primero veremos los fundamentos de redes wireless, para después estudiar dispositivos enrutadores DSL WLAN. Asimismo, veremos como configurar una red privada utilizando OpenVPN en una red inalámbrica. Finalmente, veremos como mejorar la seguridad con la ayuda de la detección de redes desprotegidas utilizando un aparato ideal para estos menesteres: un Sharp Zaurus cargado con Linux.
Práctico Inauguramos sección: Linux Práctico, dedicada al uso de Linux en ámbitos profesionales. En el número del mes que viene empezaremos a ver como utilizar una máquina Linux como estación de trabajo para la autoedición con uno de los paquetes de maquetación más interesantes existentes: Scribus. Asimismo veremos como montar fotos panorámicos utilizando Hugin y aprenderemos a actualizar nuestra instalación Fedora de manera automática y regular con Yum.
El DVD de Linux Mandrake 10.1 Official al completo. Desarrollo En nuestra sección dedicada a la programación, veremos como crear un lector de flujos RSS con Perl, crearemos una araña buscadora web con Ruby y daremos buenos consejos sobre como montar un portal de contenidos utilizando PHPNuke
SysAdmins En la sección dedicada a los administradores de sistemas tendremos más útiles consejos de Charly, hablaremos de metodologías de seguridad para aplicaciones web y desentrañaremos los misterios de los servidores de correo IMAP.
Linux User
Boletín Linux Magazine El Boletín de Linux Magazine te da la oportunidad de ver lo que se avecina en el siguiente número de Linux Magazine e incluye enlaces a artículos que aparecen en nuestro sitio web antes de que la versión impresa llegue a los quioscos. Suscríbete en www.linuxmagazine.com.es/boletin.
En nuestra sección de educación, veremos como representar grafías no occidentales para la enseñanza de idiomas. Finalizamos nuestro curso de LaTeX con un caso práctico que nos servirá de plantilla para futuros documentos. Seguiremos conociendo la línea de comandos para que todos puedan aprovechar la potencia de las instrucciones del shell.
A LA VENTA MARZO 2005 98
Número 03
www.linuxmagazine.com.es