Archive for the ‘Código’ Category.

De Superkb, GCC pedante y portabilidad

Por fin se me hizo: cambiar el Makefile de Superkb para usar gcc -std=c99 -pedantic-errors en lugar de -std=gnu99.

Lo que me impedía hacerlo era que uso algunas extensiones de GNU, BSD o POSIX que no se encuentran en el estándar C.

Yo no sabía, pero basta con añadir la línea

#define _GNU_SOURCE

o, según el caso,

#define _POSIX_C_SOURCE 2

al principio del código fuente y glibc reconoce y habilita las funciones que hagan falta.

Esto es un paso hacia adelante, pues ahora ya puedo usar un simple “grep” para ver en qué archivos están “solicitando extensiones”.

Desafortunadamente aún falta bastante para llegar al ideal, pues sigo atado a las herramientas de GNU. Por ejemplo ¿qué pasa si trato de compilar sobre OpenSolaris? La última vez que lo intenté, resultó que el Makefile usa extensiones que dependen de gmake (una de ellas es el include no fatal). Pero si hubiera gmake, ¿compilaría?

Sólo hay una manera de saberlo… ;-)

Bash prompting

Al diagnosticar un problema intermitente, tener la hora exacta en la que una prueba arrojó un determinado resultado puede ser muy útil al momento de tratarlo con los proveedores o intercambiar información con otro técnico.

Por medio de cambiar el prompt PS1 de Bash he resuelto el problema de saber a qué hora ejecuté un comando.

Continue reading ‘Bash prompting’ »

Bell on new line

To have a Linux beep each time a new line is printed on standard output, just filter your output through the following code:

gawk '{print "\007" $0 }'

This will effectively “prepend” a bell to each line.

You can convert this into an alias or a command (say /usr/local/bin/line-beep.gawk):

#!/usr/bin/gawk -f

{ print "\007" $0; }

So it can be used in a code like the following:

tail -f /var/log/messages | grep --line-buffered dhcpd | line-beep.bash

title_wrapper.bash

Escribí este script porque yo soy de los que llegan a tener —sin exagerar— 20 ó 30 ventanas de GNOME Terminal abiertas simultáneamente.

El resultado es que las ventanas tendrán en su título algo como 192.168.1.0 - ping para aquellos comandos a los que les declare un alias en el paso 2.

1. Colocar este código en /usr/local/bin/title_wrapper.bash

#!/bin/bash

# Copyright 2009, Octavio Alvarez Piza, alvarezp@alvarezp.ods.org
# Licencia: GPLv3.
# Garantía: absolutamente ninguna.

function settitle() {
	echo -ne "\033]0;$*\007"
}

while getopts "" OPT; do
	true
done

shift $(($OPTIND-1))

COMMAND=$1
COMPLETE_COMMAND="$*"
shift

case $COMMAND in
telnet)
	OPTIONS='468ELadrS:b:l:n:';;
ssh)
	OPTIONS='1246AaCfgKkMNnqsTtVvXxYb:c:D:e:F:i:L:l:m:O:o:p:R:S:w:';;
ping)
	OPTIONS='LRUbdfnqrvVaABc:i:l:p:s:t:w:F:I:M:Q:S:T:W:';;
dynagen)
	OPTIONS='ndh';;
webshare)
	OPTIONS=''
	FORCED_PARAM="`pwd`";;
else)
	OPTIONS=""
esac

while getopts $OPTIONS OPT; do
	true
done

shift $(($OPTIND-1))

PARAM="$*"
[ ! -z "$FORCED_PARAM" ] && PARAM="$FORCED_PARAM"

settitle "$PARAM - $COMMAND"

$COMPLETE_COMMAND

2. Configurar en mi .bashrc (o correspondiente script de inicio de Bash):

alias ping='title_wrapper.bash ping'
alias telnet='title_wrapper.bash telnet'
alias ssh='title_wrapper.bash ssh'
alias rsh='title_wrapper.bash rsh'

3. Configurar GNOME Terminal para que permita la modificación a los títulos de las ventanas.

Qué falló durante mi plática en el SFD2008

A todas las personas que estuvieron presentes en la plática “Invitación al Desarrollo del Software Libre”:

Quiero expresar mi agradecimiento por su presencia en mi plática; en general, en el evento SFD 2008 en Tijuana.

Recordarán que al terminar la presentación realicé en vivo un cambio al código de audiosum; específicamente, al componente audiodup. Con este cambio busqué mostrarles de manera práctica un ejemplo de cómo se desarrolla en el mundo del software libre mediante Git.

También recordarán que el experimento no funcionó del todo:

  1. descargamos el código desde repo.or.cz con git clone http://repo.or.cz/audiosum.git,
  2. compilamos audiosum y lo vimos funcionando con ./autogen.sh && ./configure && make,
  3. realizamos un cambio en audiodup,
  4. mostramos el parche resultante con git diff,
  5. revisamos el estado del repositorio local con git status,
  6. aplicamos el cambio en el repositorio local con git commit -a,
  7. observamos las diferencias entre el repositorio local y el repositorio público con git log origin..master,
  8. pero no pudimos publicar el cambio con git push.

El motivo fue muy sencillo: no tenía autorizada la laptop para enviar cambios al repositorio. En repo.or.cz se deben dar de alta las claves públicas de cada persona@computadora autorizada para enviar cambios. Tengo diferentes claves públicas en cada máquina, y sólo tenía dada de alta la PC del trabajo y la PC de la casa. Mi cuenta de la laptop no estaba autorizada para enviar cambios.

Finalmente el cambio fue aplicado con git push y pueden observar en el historial de cambios de audiosum el cambio “Added support for file pattern matching“. En el segundo enlace pueden ver que la fecha es del 13 de septiembre a las 17:56, hora local, es decir, que el commit fue realizado durante la conferencia.

Saludos.

convert-mailq-to-tabbed.gawk

Escribí este código para convertir la salida del mailq de Postfix a un formato tabular. Al tener el mailq en un formato tabular, se puede leer más fácilmente con scripts de Bash, filtrar con grep, etc.

El script ignora los mensajes de error de entrega que mailq pudiera indicar.

Está hecho en GNU Awk.

Se usa así: mailq | convert-mailq-to-tabbed.gawk.

#!/usr/bin/gawk -f

# Autor: Octavio Alvarez Piza
# Licencia: GPLv3.

BEGIN {
	OFS="\t";
	mode = "from";
}

/\(/ || /^--/ || /^-Queue/ {
	next;
}

$1 !~ /^$/ && mode == "to" {
	TO = TO $1 ";"
}

$1 ~ /[0-9]/ && mode == "from" {
	ID=$1
	SIZE=$2
	DOW=$3
	MONTH=$4
	DAY=$5
	TIME=$6
	FROM=$7;
	TO=""
	mode="to";
}

/^$/ && mode == "to" {
	print ID, SIZE, DOW, MONTH, DAY, TIME, FROM, TO
	mode="from";
}

strvcat & strvcpy

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

/* Just like strcat(), but allows multiple strings
 * on the same line.
 */
char *strvcat(char * s1, char * args, ...) {
	va_list ap;

	va_start(ap, args);
	while (args != NULL) {
		strcat(s1, args);
		args = va_arg(ap, char *);
	}
	va_end(ap);
	return s1;
}

/* Just like strcpy(), but allows multiple strings
 * on the same line.
 */
char *strvcpy(char * s1, char * args, ...) {
	va_list ap;

	va_start(ap, args);
	strcpy(s1, args);

	args = va_arg(ap, char *);
	while (args != NULL) {
		strcat(s1, args);
		args = va_arg(ap, char *);
	}
	va_end(ap);
	return s1;
}

int main() {

	char a[8192] = "HOLA MUNDO ! -- ";

	strvcpy(a, "Hola", " ", "mundo", "!", "\n", NULL);
	strvcat(a, "Hola", " ", "mundo", "!", "\n", NULL);

	printf("%s\n", a);

}

Conversión entre IP y decimal con Bash

Obtener la lista de direcciones entre 10.20.30.40 y 10.20.30.250 no es tan complicado, pero obtener la lista entre la 10.20.30.40 y la 11.25.60.250, se vuelve algo complejo, considerando ambas direcciones IP como variables arbitrarias.

Un método puede ser convertir la IP de bytes (octetos) a decimal puro y recorrer con un “for” los decimales y convertir nuevamente al final.
Continue reading ‘Conversión entre IP y decimal con Bash’ »