<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Calcifer</title>
	<atom:link href="http://blog.calcifer.com.ar/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.calcifer.com.ar</link>
	<description></description>
	<lastBuildDate>Mon, 19 Jul 2010 11:42:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Debian squeeze en Samsung N210</title>
		<link>http://blog.calcifer.com.ar/2010/07/debian-squeeze-en-samsung-n210/</link>
		<comments>http://blog.calcifer.com.ar/2010/07/debian-squeeze-en-samsung-n210/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 18:07:03 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[gnu/linux]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=731</guid>
		<description><![CDATA[La semana pasada me compré una netbook Samsung N210 con la cual estoy muy contento. Le instalé Debian squeeze (testing) y logré configurarle todas las teclas especiales, incluyendo las usadas para regular el brillo de la pantalla. Me basé en varias guías como esta y esta otra, aunque no las seguí exactamente y es por [...]]]></description>
			<content:encoded><![CDATA[<p>La semana pasada me compré una netbook <a href="http://www.samsung.com/sg/consumer/pc-peripherals-printer/notebook-pc/n-series/NP-N210-JA01SG/index.idx?pagetype=prd_detail" class="external">Samsung N210</a> con la cual estoy muy contento. Le instalé Debian squeeze (testing) y logré configurarle todas las teclas especiales, incluyendo las usadas para regular el brillo de la pantalla. Me basé en varias guías como <a href="http://artipc10.vub.ac.be/wordpress/uncategorized/samsung-n210-netbook-on-debian-gnulinux.html" title="Samsung N210 netbook on Debian GNU/Linux" class="external">esta</a> y <a href="http://josthalen.wordpress.com/2010/07/03/linux-on-samsung-n210/" title="Linux on Samsung N210" class="external">esta otra</a>, aunque no las seguí exactamente y es por eso el motivo del post.</p>
<p>Antes de comenzar la guía (y suponiendo que como yo, estás leyendo esto antes de comprar la máquina) te cuento mi experiencia con este aparatito. Algo que me hacía dudar en comprarme o no una netbook era el teclado que traían: demasiado chicos o sin espacio entre teclas. La N210 tiene casi la misma distancia entre la A y la Ñ que los teclados de escritorio y además tiene las teclas separadas como para que los dedos reconozcan mejor dónde están ubicados. Lo encuentro bastante cómodo y agradable de usar y salvo por un par de teclas que complican un poco (la &lt; se encuentra sobre la derecha y el shift derecho es chico) me siento a gusto con él. Por otro lado la batería dura aprox. 7 hs (con el brillo casi a tope) contra las 11 que declara Samsung. Dudo que llegue a eso incluso desconectando la wifi, bluetooth y poniendo el brillo al mínimo, pero aun así destaca su autonomía. Otra característica que me gusta es que es silenciosa y calienta muy poco.</p>
<p>Una última cosa antes de comenzar: El microprocesador <a href="http://ark.intel.com/Product.aspx?id=42503" class="external">Atom N450</a> tiene tecnología <a href="http://en.wikipedia.org/wiki/Hyper-threading" class="wikipedia">Hyperthreading</a> que paraleliza el procesador físico en dos procesadores virtuales. Es por eso que la salida de<code>/proc/cpuinfo</code>muestra dos cpus.</p>
<p>Ahora sí, vamos a la guía.</p>
<p><span id="more-731"></span></p>
<h3>Preparando el instalador</h3>
<p>El boot del instalador lo hice a través de la red, mediante un servidor <a href="http://en.wikipedia.org/wiki/Preboot_Execution_Environment" title="Preboot eXecution Environment" class="wikipedia">PXE</a> que armé en otra máquina. En realidad PXE no es un único servicio sino varios que en conjunto crean el entorno para que el boot remoto sea posible. Los servicios que lo componen son <a href="http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol" title="Dynamic Host Configuration Protocol" class="wikipedia">DHCP</a>, <a href="http://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol" title="Trivial File Transfer Protocol" class="wikipedia">TFTP</a> e <a href="http://en.wikipedia.org/wiki/Inetd" title="InterNET Daemon" class="wikipedia">inetd</a> (o xinetd). Hay muchas guías por ahí para hacer esto: <a href="http://www.debian.org/releases/etch/i386/ch04s06.html.en" title="Preparing Files for TFTP Net Booting" class="external">1</a>, <a href="http://www.debian-administration.org/articles/478" title="Setting up a server for PXE network booting" class="external">2</a>, <a href="http://andys.org.uk/wiki/Guide:PXE_network_booting_Debian_install" title="PXE network booting Debian install" class="external">3</a>. Aquí va la receta que yo usé:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace"># apt-get install tftpd tftp dhcp3-server</div></div>
<p>En el archivo<code>/etc/dhcp3/dhcpd.conf</code>agregar lo siguiente:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">group {<br />
&nbsp; allow bootp;<br />
&nbsp; next-server 192.168.1.2;<br />
&nbsp; &nbsp; filename &quot;pxelinux.0&quot;;<br />
&nbsp; &nbsp; host samsung-n210 {<br />
&nbsp; &nbsp; &nbsp; &nbsp; hardware ethernet 00:24:54:76:EC:08;<br />
&nbsp; &nbsp; &nbsp; &nbsp; fixed-address 192.168.1.10;<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p>Donde<code>192.168.1.2</code>es la IP del servidor que tiene el servidor TFTP.<code>00:24:54:76:EC:08</code>es la MAC address de la netbook y<code>192.168.1.10</code>es la IP fija que se le asignará a la netbook.</p>
<p>El instalador de Debian agrega la siguiente línea a<code>/etc/inetd.conf</code>al momento de la instalación de tftpd así que ni hay que tocarlo:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /srv/tftp/</div></div>
<p>Notar que el directorio<code>/srv/tftp/</code>es el raíz del servidor TFTP y es el lugar donde se debe descomprimir el <a href="http://d-i.debian.org/daily-images/amd64/daily/netboot/" title="" class="external">instalador de Debian</a>.</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace"># tar xvf netboot.tar.gz -C /srv/tftp<br />
# chown -R nobody:nogroup /srv/tftp<br />
# chmod -R 777 /srv/tftp</div></div>
<p>El funcionamiento del servidor TFTP se puede comprobar ingresando y pidiendo un archivo:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ tftp localhost<br />
tftp&gt; get version.info<br />
Received 65 bytes in 0.1 seconds</div></div>
<p>Finalmente hay que reinciar inetd, dhcp y setear la bios de la netbook para que haga el boot por la placa de red. Para no perder tiempo y poder ver cualquier error que se produzca es conveniente dejar sólo la placa de red en la secuencia de booteo.</p>
<h3>Instalación</h3>
<p>Bueno, no tengo mucho que decir acá. Yo preferí (por ansiedad) instalar el sistema base (pelado, sin X), instalar grub y finalizar; Reiniciar, cambiar la secuencia de boot y comprobar que Linux levantara correctamente.</p>
<p>Lo segundo entonces fue instalar<code>gnome-desktop-environment</code>y<code>firmware-linux-nonfree</code>y<code>network-manager-gnome</code>para la wifi.</p>
<p>El entorno gráfico levantó sin problemas y sin que tuviera que tocar nada. Out-of-the-box como le dicen.</p>
<h3>Ajuste de brillo y otras teclas rebeldes</h3>
<p>Antes de comprarme la máquina sabía que las teclas de ajuste de brillo no funcionaban pero ni bien instalé Gnome descubrí con sorpresa que sí andaban. Fue luego de un tiempo y de varios apt-get install que dejaron de funcionar. Además tampoco andaban las teclas activar/desactivar wifi, bluetooth y pantalla.</p>
<p>En la segunda guía que mencioné al principio del post cuentan que existe un proyecto llamado <a href="http://www.voria.org/forum/" title="" class="external">Linux on my Samsung</a> que lidera un tano copado llamado Fortunato Ventre y que escribió<code>samsung-tools</code>(en Python) y que sirve para darle vida a esas teclas que tanto nos angustian cuano no hacen lo que dicen hacer. El programa usa un módulo, escrito por otra gente, llamado<code>samsung_backlight</code>que se distribuye bajo el paquete <a href="http://code.google.com/p/easy-slow-down-manager/" title="" class="external">easy-slow-down-manager</a> y que según palabras de sus creadores hace lo siguiente:</p>
<blockquote><p>Easy slow down manager provides Linux users with functionality similar to &#8220;Samsung Easy Speed Up Manager&#8221;. It also allows to turn WiFi on and off.
</p></blockquote>
<p>Entonces hay que instalar primero este módulo, para lo cual necesitamos descargar el <a href="http://code.google.com/p/easy-slow-down-manager/downloads/list" title="" class="external">.deb</a> y compilarlo con los headers correspondientes al kernel que estemos usando.</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace"># apt-get install linux-headers-`uname -r`<br />
# dpkg -i easy-slow-down-manager-dkms_0.13.1_all.deb</div></div>
<p>Luego de instalar el módulo, bajamos el paquete <a href="https://launchpad.net/samsung-tools" title="" class="external">samsung-tools</a> y lo compilamos también, no sin antes instalar sus dependencias.</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace"># apt-get install xbindkeys dbus-python rfkill gettext<br />
# tar xzf samsung-tools-1.1.1.tar.gz<br />
# cd &nbsp;samsung-tools-1.1.1<br />
# make<br />
# make install</div></div>
<p>Las teclas de brillo deberían funcionar tras reiniciar el sistema. Si no, puede que no esté cargado el módulo. Acá dejo la salida de algunos comandos de mi sistema funcionando:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace"># modprobe -l | grep -i samsung-backlight<br />
updates/samsung-backlight/samsung-backlight.ko<br />
# lsmod | grep samsung<br />
samsung_backlight &nbsp; &nbsp; &nbsp; 2740 &nbsp;0<br />
# dmesg | grep Samsung<br />
[ &nbsp; &nbsp;4.009833] Samsung-backlight: checking for SABI support.<br />
[ &nbsp; &nbsp;4.010082] Samsung-backlight: SABI is supported (f5191)</div></div>
<h3>El TouchPad</h3>
<p>Sólo nos resta ocuparnos de este, que de movida funciona pero tiene algunas opciones ocultas que pueden ser interesantes, como el scolling circular. El TouchPad puede setearse directamente desde la consola mediante el comando<code>synclient</code>pasándole como parámetro la propiedad a modificar y su nuevo valor. Las siguientes dos líneas habilitan el scrolling horizontal:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ synclient HorizEdgeScroll=1<br />
$ synclient TouchpadOff=0</div></div>
<p>Se puede obtener un listado completo de todas las propiedades con sus valores actuales ejecutando</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ synclient -l</div></div>
<p>Lindo, pero es un poco engorroso manejarlo así (y yo quiero habilitar y setear el scrolling circular). Por suerte existe <a href="http://live.gnome.org/GPointingDeviceSettings" title="" class="external">gpointing-device-settings</a> que permite configurar el TouchPad en forma gráfica.</p>
<p><img src="http://blog.calcifer.com.ar/uploads/2010/07/GPointingDeviceSettings.png" alt="" title="GPointingDeviceSettings" width="420" height="345" class="noborder" /></p>
<p>Lamentablemente la versión actual (1.5.1-2) tiene un <a href="https://bugs.launchpad.net/ubuntu/+source/gpointing-device-settings/+bug/489830" title="Settings of gpointing-device-settings are non-persistent" class="external">bug conocido</a> que no persiste los cambios al salir de la sesión. Seguramente lo arreglarán pronto. Mientras tanto se me ocurrió lo siguiente: setear todas las propiedades con gpointing-device-settings, recolectar el estado completo con synclient -l y generar un .sh que se ejecute al inicio de la sesión:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ synclient -l | awk '{if(NR==1)print &quot;#!/bin/bash&quot;;else print &quot;synclient &quot; $1 $2 $3}' &gt; touchpad-settings.sh &amp;&amp; chmod u+x touchpad-settings.sh</div></div>
<p>Sólo queda añadir<code>touchpad-settings.sh</code>al listado de aplicaciones que se ejecutan al iniciar la sesión de Gnome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2010/07/debian-squeeze-en-samsung-n210/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reemplazo de discos en RAID con mdadm</title>
		<link>http://blog.calcifer.com.ar/2010/06/reemplazo-de-discos-en-raid-con-mdadm/</link>
		<comments>http://blog.calcifer.com.ar/2010/06/reemplazo-de-discos-en-raid-con-mdadm/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 03:05:28 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[gnu/linux]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=692</guid>
		<description><![CDATA[Hace unos días hice mi segundo reemplazo completo de discos de un array MD y quería compartir aquí los pasos que he utilizado (con éxito :D) en ambos casos.
Los dos escenarios fueron similares: dos discos iguales, con iguales particiones y RAID-1 que deben ser reemplazados por otros dos discos iguales pero de mayor tamaño, por [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días hice mi segundo reemplazo completo de discos de un array <a href="http://linux.die.net/man/4/md" class="external">MD</a> y quería compartir aquí los pasos que he utilizado (con éxito :D) en ambos casos.</p>
<p>Los dos escenarios fueron similares: dos discos iguales, con iguales particiones y <a href="http://es.wikipedia.org/wiki/RAID#RAID_1_.28Data_Mirroring.29" class="wikipedia">RAID-1</a> que deben ser reemplazados por otros dos discos iguales pero de mayor tamaño, por lo que el procedimiento fue el mismo en ambos casos.</p>
<p>Para simplificar la guía decidí usar discos con sólo tres particiones: una para<code>/</code>, una para<code>/var</code>y otra para<code>swap</code>(que no está en RAID). El esquema entonces queda definido de la siguiente manera:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">sda (grub) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RAID's 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sdb (grub)<br />
+------------------+ &nbsp; &nbsp; +-----------------+ &nbsp; &nbsp; +------------------+<br />
| /dev/sda1 &nbsp; &nbsp; &nbsp; &nbsp;|-----| /dev/md0 (/) &nbsp; &nbsp;|-----| /dev/sdb1 &nbsp; &nbsp; &nbsp; &nbsp;|<br />
+------------------+ &nbsp; &nbsp; +-----------------+ &nbsp; &nbsp; +------------------+<br />
| /dev/sda2 &nbsp; &nbsp; &nbsp; &nbsp;|-----| /dev/md1 (/var) |-----| /dev/sdb2 &nbsp; &nbsp; &nbsp; &nbsp;|<br />
+------------------+ &nbsp; &nbsp; +-----------------+ &nbsp; &nbsp; +------------------+<br />
| /dev/sda3 (swap) | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | /dev/sdb3 (swap) |<br />
+------------------+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +------------------+</div></div>
<p>Los discos que se usarán para reemplazo son<code>sdc</code>y<code>sdd</code>.</p>
<p><strong>NOTA:</strong> En la guía sólo se muestra el reemplazo completo de sda por sdc ya que el procedimiento para reemplazar sdb por sdd es el mismo.</p>
<h3>1. Particionado de disco</h3>
<p>La manera sencilla de copiar la tabla de particiones de una unidad a otra es:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># sfdisk -d /dev/sda | sfdisk /dev/sdc</span></div></div>
<p>Esto copia completamente el esquema del disco origen (sda) al disco destino (sdc). Si el destino es mayor simplemente quedará espacio libre (sin asignar) al final del disco.</p>
<h3>2. Reemplazo de particiones en arrays</h3>
<p><strong>TIP:</strong> Es útil tener visible, en otra terminal y durante todo el proceso, la salida de<code>/proc/mdstat</code>para visualizar en todo momento el estado del array y poder ver el sincronizado de los discos:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># watch -t cat /proc/mdstat</span></div></div>
<p><span id="more-692"></span><br />
Ahora sí, empecemos por el RAID sobre el que está montado<code>/var</code>y quitemos<code>sda2</code>:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># mdadm /dev/md1 --fail /dev/sda2</span><br />
mdadm: <span class="kw1">set</span> <span class="sy0">/</span>dev<span class="sy0">/</span>sda2 faulty <span class="kw1">in</span> <span class="sy0">/</span>dev<span class="sy0">/</span>md1<br />
<br />
papua:~<span class="co0"># mdadm /dev/md1 --remove /dev/sda2</span><br />
mdadm: hot removed <span class="sy0">/</span>dev<span class="sy0">/</span>sda2</div></div>
<p>La salida de<code>/proc/mdstat</code>debería mostrar con<code>U_</code>el array degradado:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># cat /proc/mdstat </span><br />
Personalities : <span class="br0">&#91;</span>raid1<span class="br0">&#93;</span> <br />
md1 : active raid1 sdb2<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; <span class="nu0">14651200</span> blocks <span class="br0">&#91;</span><span class="nu0">2</span><span class="sy0">/</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="br0">&#91;</span>U_<span class="br0">&#93;</span><br />
<br />
md0 : active raid1 sdb1<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> sda1<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; <span class="nu0">29294400</span> blocks <span class="br0">&#91;</span><span class="nu0">2</span><span class="sy0">/</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="br0">&#91;</span>UU<span class="br0">&#93;</span></div></div>
<p>Ahora agreguemos<code>sdc2</code>:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># mdadm /dev/md1 --add /dev/sdc2</span><br />
mdadm: added <span class="sy0">/</span>dev<span class="sy0">/</span>sdc2</div></div>
<p>Esperamos a que la sincronización termine (nuevamente ver la salida de /proc/mdstat) y hacemos lo mismo para<code>/</code>: repetimos completo el punto 2 cambiando sda2 por sda1 y sdc2 por sdc1.</p>
<h3>4. Instalación de GRUB</h3>
<p>Instalaremos grub en el MBR de<code>sdc</code>para que el sistema pueda bootear con cualquiera de los discos del array. Agregamos una entrada para el nuevo disco en el archivo<code>/boot/grub/device.map</code>:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw3">echo</span> <span class="st_h">'(hd2) &nbsp; &nbsp; /dev/sdc'</span> <span class="sy0">&gt;&gt;</span> <span class="sy0">/</span>boot<span class="sy0">/</span>grub<span class="sy0">/</span>device.map</div></div>
<p>Luego procedemos a la instalación:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># grub --device-map=/boot/grub/device.map</span><br />
grub<span class="sy0">&gt;</span> root <span class="br0">&#40;</span>hd2,<span class="nu0">0</span><span class="br0">&#41;</span><br />
root <span class="br0">&#40;</span>hd2,<span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp;Filesystem <span class="kw3">type</span> is reiserfs, partition <span class="kw3">type</span> 0xfd<br />
grub<span class="sy0">&gt;</span> setup <span class="br0">&#40;</span>hd2<span class="br0">&#41;</span><br />
setup <span class="br0">&#40;</span>hd2<span class="br0">&#41;</span><br />
...<br />
grub<span class="sy0">&gt;</span> quit</div></div>
<h3>5. Reemplazo de swap</h3>
<p>Seteamos la partición:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># mkswap /dev/sdc3</span><br />
Setting up swapspace version <span class="nu0">1</span>, <span class="kw2">size</span> = <span class="nu0">10001936</span> kB<br />
no label, <span class="re2">UUID</span>=b00c3665-151b-4a16-ba57-e0c032f14520</div></div>
<p>Desmontamos la swap de<code>sda3</code>y la montamos en<code>sdc3</code>:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">papua:~<span class="co0"># swapoff /dev/sda3</span><br />
papua:~<span class="co0"># swapon /dev/sdc3</span></div></div>
<p>También es necesario modificar<code>/etc/fstab</code>para que la swap sea correctamente montada al reiniciar el equipo:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">UUID=b00c3665-151b-4a16-ba57-e0c032f14520 &nbsp;none &nbsp;swap &nbsp;sw &nbsp; 0 &nbsp; &nbsp;0</div></div>
<p>Recordar que el<code>UUID</code>debe ser el que nos devuelva la salida de<code>mkswap</code>, aunque también puede averiguarse mediante</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw2">ls</span> <span class="re5">-l</span> <span class="sy0">/</span>dev<span class="sy0">/</span>disk<span class="sy0">/</span>by-uuid<span class="sy0">/</span> <span class="sy0">|</span> <span class="kw2">grep</span> sdc3</div></div>
<h3>6. Fin</h3>
<p>Eso es todo. Para remover el otro disco repetimos los pasos del 1 al 5 reemplazando sda por sdb, sdc por sdd y hd2 por hd3.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2010/06/reemplazo-de-discos-en-raid-con-mdadm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vim scripting con Python</title>
		<link>http://blog.calcifer.com.ar/2010/02/vim-scripting-con-python/</link>
		<comments>http://blog.calcifer.com.ar/2010/02/vim-scripting-con-python/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 01:20:00 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=549</guid>
		<description><![CDATA[Vim permite agregar funcionalidades mediante varios lenguajes externos, entre ellos Perl, Python, Ruby y Tcl. Para poder hacer uso de esta característica es necesario haber compilado Vim con el soporte para el lenguaje necesario (con el flag-python, para soporte python). En debian existe un paquete llamado vim-nox (no X) que contiene una versión compilada con [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.vim.org/" title="Vim the editor" class="external">Vim</a> permite agregar funcionalidades mediante varios lenguajes externos, entre ellos Perl, Python, Ruby y Tcl. Para poder hacer uso de esta característica es necesario haber compilado Vim con el soporte para el lenguaje necesario (con el flag<code>-python</code>, para soporte python). En debian existe un paquete llamado <a href="http://packages.debian.org/stable/vim-nox" title="Debian Package: vim-nox" class="external">vim-nox</a> (no X) que contiene una versión compilada con soporte para los cuatro lenguajes mencionados:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">sudo apt-get install vim-nox</div></div>
<p>Para comprobar que efectivamente se encuentre habilitado el soporte para Python ejecutar Vim y en modo comando escribir:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:echo has(&quot;python&quot;)</div></div>
<p>Un 1 indica que Vim interpreta Python ;)</p>
<p>Es muy recomendable leer la ayuda en línea:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:help python</div></div>
<p>También se puede acceder vía web desde <a href="http://vimdoc.sourceforge.net/htmldoc/if_pyth.html" title="Vim documentation: if_pyth" class="external">http://vimdoc.sourceforge.net/htmldoc/if_pyth.html</a></p>
<h3>Ejecución de código Python</h3>
<p>La ejecución de una línea de código Python se realiza según la sintaxis:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:[range]py[thon] {stmt}</div></div>
<p>Ejemplo:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:python print &quot;hello world&quot;</div></div>
<p>Aquí el prompt mostrará el mensaje &#8220;hello world&#8221;.</p>
<p>En cambio para escribir código en varias líneas hay que usar la siguiente forma:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">[range]:py[thon] &lt;&lt; {endmarker}<br />
{script}<br />
{endmarker}</div></div>
<p>Ejemplo:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:python &lt;&lt; EOF<br />
def get_user():<br />
&nbsp; import os<br />
&nbsp; return os.getenv('USER')<br />
EOF</div></div>
<p>De esta manera la función queda guardada en la memoria de la sesión actual. Luego su uso podría ser el siguiente:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py user = get_user()</div></div>
<p>Tambien es posible cargar y/o ejecutar código desde un archivo externo. La sintaxis es:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:[range]pyf[ile] {file}</div></div>
<p>Ejemplo:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:pyfile myscript.py</div></div>
<p>Si<code>myscript.py</code>necesitara parámetros la forma de pasárselos es la siguiente:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py import sys<br />
:py sys.argv = ['foo', 'bar']<br />
:pyf myscript.py</div></div>
<h3>El módulo vim</h3>
<p>La comunicación entre Python y Vim se realiza a través del módulo vim, el cual hay que importar antes de usar:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:python import vim</div></div>
<p>Como indica la ayuda de Vim, el módulo implementa dos métodos (<code>vim.command(str)</code>y<code>vim.eval(str)</code>), tres constantes (<code>vim.buffers</code>,<code>vim.windows</code>y<code>vim.current</code>) y un objeto error (<code>vim.error</code>). Las tres constantes mencionadas no son realmente constantes sino variables que pueden ser reasignadas pero, como dice también la ayuda, esto sería absurdo ya que se perdería acceso a los objetos de Vim que referencian. Por otra parte cabe recordar que no existen constantes en Python. Como cita el libro &#8220;<a href="http://www.gulic.org/almacen/diveintopython-5.4-es/object_oriented_framework/class_attributes.html" title="Capítulo 5.8. - Presentación de los atributos de clase" class="external">Inmersión en Python</a>&#8220;:</p>
<blockquote><p>Todo puede cambiar si lo intenta con ahínco. Esto se ajusta a uno de los principios básicos de Python: los comportamientos inadecuados sólo deben desaconsejarse, no prohibirse.</p></blockquote>
<p><span id="more-549"></span><br />
A continuación transcribo un detalle de cada una de las constantes mencionadas:</p>
<dl>
<dt>vim.buffers</dt>
<dd>
Objeto de tipo secuencia que provee acceso al listado de buffers actuales. El objeto soporta las siguiente operaciones:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py b = vim.buffers[i] &nbsp; &nbsp; # Indexación (Read-Only)<br />
:py b in vim.buffers &nbsp; &nbsp; &nbsp; # Prueba de existencia<br />
:py n = len(vim.buffers) &nbsp; # Número de elementos<br />
:py for b in vim.buffers: &nbsp;# Acceso secuencial</div></div>
</dd>
<dt>vim.windows</dt>
<dd>
Objeto de tipo secuencia que provee acceso al listado de ventanas actuales. El objeto soporta las mismas operaciones que vim.buffers:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py w = vim.windows[i] &nbsp; &nbsp; # Indexación (RO)<br />
:py w in vim.windows &nbsp; &nbsp; &nbsp; # Prueba de existencia<br />
:py n = len(vim.windows) &nbsp; # Número de elementos<br />
:py for w in vim.windows: &nbsp;# Acceso secuencial</div></div>
</dd>
<dt>vim.current</dt>
<dd>
Objeto que provee acceso (vía atributos específicos) a distintos objetos actuales:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">vim.current.line &nbsp; &nbsp;# (RW) String<br />
vim.current.buffer &nbsp;# (RO) Buffer<br />
vim.current.window &nbsp;# (RO) Window<br />
vim.current.range &nbsp; # (RO) Range</div></div>
</dd>
</dl>
<h3>Ejemplos básicos de uso del módulo vim</h3>
<p>Usando<code>vim.current.line</code>:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py from string import upper<br />
:py vim.current.line = upper(vim.current.line)</div></div>
<p>Usando<code>vim.current.buffer</code>:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py b = vim.current.buffer &nbsp; &nbsp; &nbsp;# obtiene buffer actual<br />
:py name = b.name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # nombre de archivo del buffer actual<br />
:py num = len(b) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# total de líneas en el buffer<br />
:py line = b[n] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # obtiene la línea n+1<br />
:py lines = b[n:m] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# obtiene una lista de líneas<br />
:py b[n] = str &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# reemplaza la línea n+1<br />
:py b[n:m] = [str1, str2, str3] # reemplaza varias líneas a la vez<br />
:py b[0:0] = [&quot;hola mundo&quot;] &nbsp; &nbsp; # inserta una línea al comienzo<br />
:py b.append(&quot;fin&quot;) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # inserta una línea al final<br />
:py del b[n] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# borra la línea n+1<br />
:py del b[n:m] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# borra varias líneas a la vez<br />
:py b[:] = None &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # borra el buffer completo</div></div>
<p>Usando<code>vim.current.window</code>:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py cw = vim.current.window &nbsp; &nbsp; &nbsp;# obtiene la ventana actual<br />
:py cw.height = 30 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # setea el alto de la ventana<br />
:py cw.width = 80 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# setea el ancho<br />
:py pos = cw.cursor &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# posicion del cursor (row, col)</div></div>
<h3>Script para subrayado de títulos</h3>
<p>El siguiente script (<a href="http://blog.calcifer.com.ar/uploads/2010/02/heading.vim" title="">heading.vim</a>) lo escribí para no tener que, manualmente, subrayar títulos y delimitar bloques de texto. Especialmente quería que reconociera cuando se tratara de texto dentro de comentarios de código fuente y que respetara los caracteres especiales al comienzo (y final) de los mismos.</p>
<p>El script tiene una función que decora la línea actual colocando él o los caracteres decoradores tanto arriba como debajo de la misma (comportamiento por defecto). El largo (también por defecto) es el largo de la línea, pero se puede fijar un límite (ejemplo 80 columnas) y pedirle que ocupe todo el espacio disponible. Esta opción funciona bien sólamente cuando el indentado es con espacios. La opción uppercase funciona como se espera.</p>
<p>El código es el siguiente:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px;height:500px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">&quot; ============================================================================<br />
&quot; File: &nbsp; &nbsp; &nbsp; &nbsp;heading.vim<br />
&quot; Version: &nbsp; &nbsp; 0.1<br />
&quot; Description: vim global plugin that provides a way to create headings.<br />
&quot; Maintainer: &nbsp;Leonardo Vidarte &lt;lvidarte at gmail dot com&gt;<br />
&quot; Last Change: 21 February, 2010<br />
&quot; ============================================================================<br />
if has('python')<br />
python &lt;&lt; EOF<br />
def heading(decorator='=', top=True, bottom=True, limit=0, uppercase=False):<br />
<br />
&nbsp; &nbsp; import vim<br />
&nbsp; &nbsp; from string import upper, rstrip, lstrip<br />
<br />
&nbsp; &nbsp; if not top and not bottom:<br />
&nbsp; &nbsp; &nbsp; &nbsp; return None # nothing to do<br />
<br />
&nbsp; &nbsp; (row, col) = vim.current.window.cursor<br />
&nbsp; &nbsp; line = vim.current.buffer[row-1].rstrip()<br />
&nbsp; &nbsp; line_length = len(line.decode('utf8'))<br />
&nbsp; &nbsp; title = line.lstrip()<br />
&nbsp; &nbsp; word_length = len(title.decode('utf8'))<br />
&nbsp; &nbsp; whitespace = line[0:line_length - word_length]<br />
<br />
&nbsp; &nbsp; if limit &gt; 0:<br />
&nbsp; &nbsp; &nbsp; &nbsp; decorator *= limit<br />
&nbsp; &nbsp; &nbsp; &nbsp; total_length = limit<br />
&nbsp; &nbsp; else:<br />
&nbsp; &nbsp; &nbsp; &nbsp; decorator *= word_length<br />
&nbsp; &nbsp; &nbsp; &nbsp; total_length = line_length<br />
<br />
&nbsp; &nbsp; if title[0:3] in ('// ', '/* ', '-- '):<br />
&nbsp; &nbsp; &nbsp; &nbsp; decoline = whitespace + title[0:3] + decorator<br />
&nbsp; &nbsp; elif title[0:2] in ('//', '/*', '--', '# ', '* ', '&quot; '):<br />
&nbsp; &nbsp; &nbsp; &nbsp; decoline = whitespace + title[0:2] + decorator<br />
&nbsp; &nbsp; elif title[0:1] in ('#', '*', '&quot;'):<br />
&nbsp; &nbsp; &nbsp; &nbsp; decoline = whitespace + title[0:1] + decorator<br />
&nbsp; &nbsp; else:<br />
&nbsp; &nbsp; &nbsp; &nbsp; decoline = whitespace + decorator<br />
<br />
&nbsp; &nbsp; # Special case: comments like C /* hello world */<br />
&nbsp; &nbsp; cend = ''<br />
&nbsp; &nbsp; if title[0:2] == '/*':<br />
&nbsp; &nbsp; &nbsp; &nbsp; if title[-3:] == ' */':<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cend = ' */'<br />
&nbsp; &nbsp; &nbsp; &nbsp; elif title[-2:] == '*/':<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cend = '*/'<br />
<br />
&nbsp; &nbsp; decoline = decoline[0:total_length - len(cend)] + cend<br />
&nbsp; &nbsp; final_heading = []<br />
<br />
&nbsp; &nbsp; if top:<br />
&nbsp; &nbsp; &nbsp; &nbsp; final_heading.append(decoline)<br />
<br />
&nbsp; &nbsp; if uppercase:<br />
&nbsp; &nbsp; &nbsp; &nbsp; final_heading.append(line.upper())<br />
&nbsp; &nbsp; else:<br />
&nbsp; &nbsp; &nbsp; &nbsp; final_heading.append(line)<br />
<br />
&nbsp; &nbsp; if bottom:<br />
&nbsp; &nbsp; &nbsp; &nbsp; final_heading.append(decoline)<br />
<br />
&nbsp; &nbsp; del vim.current.buffer[row-1]<br />
&nbsp; &nbsp; vim.current.buffer[row-1:0] = final_heading<br />
<br />
&nbsp; &nbsp; # Set final cursor position<br />
&nbsp; &nbsp; if top and bottom:<br />
&nbsp; &nbsp; &nbsp; &nbsp; vim.current.window.cursor = (row + 2, 0)<br />
&nbsp; &nbsp; else:<br />
&nbsp; &nbsp; &nbsp; &nbsp; vim.current.window.cursor = (row + 1, 0)<br />
<br />
H = heading # shortcut<br />
EOF<br />
<br />
&quot; ============================================================================<br />
&quot; Vim maps (see :help leader)<br />
&quot; ============================================================================<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;hh :python heading()&lt;CR&gt;<br />
<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;h1 :python heading('#', uppercase=True)&lt;CR&gt;<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;h2 :python heading('*', uppercase=True)&lt;CR&gt;<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;h3 :python heading('=')&lt;CR&gt;<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;h4 :python heading('-')&lt;CR&gt;<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;h5 :python heading('~', top=False)&lt;CR&gt;<br />
<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;HH :python heading(limit=78)&lt;CR&gt;<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;Hb :python heading(limit=78, top=False)&lt;CR&gt;<br />
nnoremap &lt;silent&gt; &lt;Leader&gt;Ht :python heading(limit=78, bottom=False)&lt;CR&gt;<br />
<br />
endif</div></td></tr></tbody></table></div>
<p>Para usarlo hay que colocar el archivo <a href="http://blog.calcifer.com.ar/uploads/2010/02/heading.vim" title="">heading.vim</a> en el directorio<code>~/.vim/plugins</code>.</p>
<h4>Ejemplos de uso</h4>
<p>1. Texto normal</p>
<pre>Título</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H()</div></div>
<pre>======
Título
======</pre>
<p>2. Comentario en línea (Python, Bash, Perl, PHP, Ruby)</p>
<pre>    # Comment</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H()</div></div>
<pre>    # =======
    # Comment
    # =======</pre>
<p>3. Comentario en bloque, estilo javadoc (C, C++, Java, Javascript, CSS, PHP, SQL)</p>
<pre>    /**
     * Comment
     */</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H('#', uppercase=True)</div></div>
<pre>    /**
     * #######
     * COMMENT
     * #######
     */</pre>
<p>4. Comentario en línea (C, C++, Java, Javascript, CSS, PHP, SQL)</p>
<pre>/* Comment */</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H('~+')</div></div>
<pre>/* ~+~+~+~ */
/* Comment */
/* ~+~+~+~ */</pre>
<p>5. Comentario en línea (C, Java, Javascript, PHP)</p>
<pre>// Comment</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H(limit=40)</div></div>
<pre>// =====================================
// Comment
// =====================================</pre>
<p>6. Comentario en línea (Vim script)</p>
<pre>" Comment</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H(top=None)</div></div>
<pre>" Comment
" ======</pre>
<p>7. Comentario en línea (Lua, SQL)</p>
<pre>-- Comment</pre>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">:py H()</div></div>
<pre>-- =======
-- Comment
-- =======</pre>
<h4>Atajos de teclado</h4>
<p>El script también define algunos atajos en modo normal para Vim. Para los mismos se usa la tecla especial<code>&lt;Leader&gt;</code>que es definida por la variable<code>mapleader</code>y que generealmente es el caracter<code>\</code>.</p>
<table>
<tr>
<th>Atajo</th>
<th>Comando</th>
</tr>
<tr>
<td>\hh</td>
<td>:python heading()</td>
</tr>
<tr>
<td>\h1</td>
<td>:python heading(&#8216;#&#8217;, uppercase=True)</td>
</tr>
<tr>
<td>\h2</td>
<td>:python heading(&#8216;*&#8217;, uppercase=True)</td>
</tr>
<tr>
<td>\h3</td>
<td>:python heading(&#8216;=&#8217;)</td>
</tr>
<tr>
<td>\h4</td>
<td>:python heading(&#8216;-&#8217;)</td>
</tr>
<tr>
<td>\h5</td>
<td>:python heading(&#8216;~&#8217;, top=False)</td>
</tr>
<tr>
<td>\HH</td>
<td>:python heading(limit=78)</td>
</tr>
<tr>
<td>\Hb</td>
<td>:python heading(limit=78, top=False)</td>
</tr>
<tr>
<td>\Ht</td>
<td>:python heading(limit=78, bottom=False)</td>
</tr>
</table>
<h3>Lectura adicional</h3>
<ul>
<li><a href="http://www.builderau.com.au/program/python/soa/Extending-Vim-with-Python/0,2000064084,339283181,00.htm">Extending Vim with Python</a></li>
<li><a href="http://www.tummy.com/Community/Presentations/vimpython-20070225/vim.html">Python and vim: Two great tastes that go great together</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2010/02/vim-scripting-con-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sincronizar Motorola Q y Evolution con SynCE y MultiSync en Ubuntu Jaunty</title>
		<link>http://blog.calcifer.com.ar/2009/09/sincronizar-motorola-q-y-evolution/</link>
		<comments>http://blog.calcifer.com.ar/2009/09/sincronizar-motorola-q-y-evolution/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 13:27:38 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=465</guid>
		<description><![CDATA[Para sincronizar contactos, calendario y tareas entre un Motorola Q y Evolution se necesitan dos programas: SynCE y MultiSync.
Como dice el sitio web de SynCE, el objetivo del proyecto es proporcionar un medio de comunicación entre un dispositivo con Windows Mobile y un equipo con Linux, *BSD u otro UNIX, mediante una conexión USB o [...]]]></description>
			<content:encoded><![CDATA[<p>Para sincronizar contactos, calendario y tareas entre un <a href="http://www.motorola-rm.com/motoq/es/q-home.asp" class="external">Motorola Q</a> y <a href="http://projects.gnome.org/evolution/" class="external">Evolution</a> se necesitan dos programas: SynCE y MultiSync.</p>
<p>Como dice el <a href="http://www.synce.org/moin/" class="external">sitio web de SynCE</a>, el objetivo del proyecto es proporcionar un medio de comunicación entre un dispositivo con Windows Mobile y un equipo con Linux, *BSD u otro UNIX, mediante una conexión USB o Bluetooth. Esto permite utilizar la PC para navegar el sistema de archivos del teléfono e instalar aplicaciones y proporciona el medio de comunicación para que mediante otro programa (MultiSync) sea posible sincronizar contactos, calendario y tareas entre el teléfono y una aplicación <a href="http://en.wikipedia.org/wiki/Personal_information_management" class="wikipedia">PIM</a> de escritorio como Evolution.</p>
<p><a href="http://multisync.sourceforge.net/news.php" class="external">MultiSync</a> es una herramienta de software libre que sincroniza calendarios, libretas de direcciones y otra información PIM, entre programas de una PC o de otras PC, dispositivos móviles o teléfonos móviles. Depende del framework de desarrollo <a href="http://opensync.org/" class="external">OpenSync</a>.</p>
<p><span id="more-465"></span><br />
El primer paso entonces será instalar SynCE y comprobar que la conexión sea exitosa.</p>
<h3>1. Instalación de SynCE</h3>
<p>Agregar los siguientes repositorios a<code>/etc/apt/sources.list</code></p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">deb http://ppa.launchpad.net/synce/ubuntu jaunty main<br />
deb-src http://ppa.launchpad.net/synce/ubuntu jaunty main</div></div>
<p>Importar la clave pública</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">sudo apt-key adv --recv-keys --keyserver subkeys.pgp.net 7D2C7A23BF810CD5</div></div>
<p>Actualizar la lista de paquetes e instalar los necesarios para SynCE</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">sudo apt-get udpate<br />
sudo apt-get install synce-hal librra-tools librapi2-tools</div></div>
<p><strong>TIP:</strong> Desinstalar<code>odccm</code>en caso de estar instalado. Dejar solo<code>synce-hal</code>.</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">sudo apt-get remove odccm</div></div>
<p>Antes de conectar el teléfono hay que deshabilitarle la opción <strong>&#8220;Enable advanced network funcionality&#8221;</strong> que se encuentra en Start / Settings / Connections / USB to PC.</p>
<p>Al conectar el teléfono es conveniente mirar la entrada de<code>/var/log/messages</code>ya que brinda información que puede ser útil para resolver problemas:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ tail -f /var/log/messages<br />
...<br />
[ 5082.864026] usb 2-2: new full speed USB device using uhci_hcd and address 3<br />
[ 5083.068779] usb 2-2: configuration #1 chosen from 1 choice <br />
[ 5083.071136] ipaq 2-2:1.0: PocketPC PDA converter detected <br />
[ 5083.106975] usb 2-2: PocketPC PDA converter now attached to ttyUSB0</div></div>
<p>La última línea indica que el teléfono ha sido conectado al dispositivo<code>/dev/ttyUSB0</code>. Este dispositivo se crea cuando se detecta la conexión. Si no se crea es probable que no esten cargados los módulos<code>usbserial</code>e<code>ipaq</code>. Chequear esto mediante<code>lsmod | grep ipaq</code>. (más info <a href="http://www.kernel.org/doc/Documentation/usb/usb-serial.txt" class="external">aquí</a>).</p>
<p>La conexión se prueba con siguiente comando</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">synce-pls</div></div>
<p>Si la conexión se ha establecido correctamente el comando devolverá el listado de archivos del directorio raíz del teléfono. En caso contrario hay que revisar los pasos anteriores, reiniciar el servicio hal (<code>sudo /etc/init.d/hal restart</code>) y reconectar el teléfono. Una herramienta que brinda información sobre las conexiones USB es<code>lsusb</code>(con la opción -v muestra información aun más detallada).</p>
<h4>Integración con Gnome</h4>
<p>Hay dos herramientas que son útiles para ver el estado del teléfono (conexión, carga de la batería, memoria utilizada, programas instalados, etc.) y navegar por su estructura de directorios utilizando <a href="http://live.gnome.org/Nautilus">Nautilus</a>.</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">sudo apt-get install synce-trayicon synce-gvfs</div></div>
<p><strong>TIP:</strong> Luego de instalar<code>synce-gvfs</code>es necesario reiniciar el equipo.</p>
<h3>2. Instalación de MultiSync</h3>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">apt-get install multisync-tools opensync-plugin-synce synce-sync-engine opensync-plugin-evolution</div></div>
<p>Para que la sincronización pueda llevarse a cabo es necesario crear una asociación (partnership) entre el teléfono y Evolution. Hay al menos dos formas de hacer esto. Una es en forma gráfica utilizando<code>SynCE-Trayicon</code>y la otra es desde línea de comandos:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">synce-create-partnership &quot;Linux desktop&quot; &quot;Contacts,Calendar,Tasks&quot;</div></div>
<p>Ahora es necesario crear un grupo y asociar a él los dos plugins previamente instalados:<code>synce-opensync-plugin</code>y<code>evo2-sync</code>. Se puede comprobar que efectivamente se encuentren instalados utilizando<code>msynctool --listplugins</code>.</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">msynctool --addgroup synce-sync<br />
msynctool --addmember synce-sync synce-opensync-plugin<br />
msynctool --addmember synce-sync evo2-sync</div></div>
<h4>Sincronizando datos</h4>
<p>En este punto ya es posible sincronizar datos ejecutando</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">msynctool --sync synce-sync</div></div>
<h3>Referencias</h3>
<ul>
<li><a href="http://www.synce.org/moin/SynceInstallation/Ubuntu/ModernDevice" class="external">SynCE with Windows Mobile 5/6/6.1 on Ubuntu</a></li>
<li><a href="http://www.kernel.org/doc/Documentation/usb/usb-serial.txt" class="external">Kernel.org: USB-Serial</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/09/sincronizar-motorola-q-y-evolution/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>umask</title>
		<link>http://blog.calcifer.com.ar/2009/08/umask/</link>
		<comments>http://blog.calcifer.com.ar/2009/08/umask/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 04:38:27 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[*N?X]]></category>
		<category><![CDATA[gnu/linux]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=451</guid>
		<description><![CDATA[Umask (user mask) es un número octal que UNIX utiliza para determinar qué permisos NO asignar automáticamente a los nuevos archivos y directorios creados. Umask sólo restringe permisos; no concede permisos adicionales más allá de lo especificado por defecto.
La mayoría de los sistemas UNIX especifican el valor octal 666 (rw-rw-rw-) para la creación de archivos [...]]]></description>
			<content:encoded><![CDATA[<p>Umask (user mask) es un número octal que UNIX utiliza para determinar qué permisos NO asignar automáticamente a los nuevos archivos y directorios creados. Umask sólo restringe permisos; no concede permisos adicionales más allá de lo especificado por defecto.</p>
<p>La mayoría de los sistemas UNIX especifican el valor octal 666 (rw-rw-rw-) para la creación de archivos y el valor octal 777 (rwxrwxrwx) para la creación de directorios. Luego, el kernel utiliza el valor de umask asignado al usuario como máscara para quitar permisos a los definidos por defecto. Todo proceso tiene su umask, heredado del proceso padre del cual desciende.</p>
<p>Los valores más comunes para umask son 022, 027 y 077.<br />
Normalmente el valor de umask se define en /etc/profile</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co0"># Set the user's umask</span><br />
<span class="kw3">umask</span> 022</div></div>
<p>aunque es posible setearlo en algún archivo de sesión como ~/.bash_profile, e incluso manualmente para la sessión actual. En todos los casos se utiliza el comando umask que es una función interna de Bash, y de otros shells como ksh y csh. (Si umask fuera un programa separado del shell no podríamos cambiar el valor de umask del proceso shell actual).</p>
<h3>Cálculo de permisos</h3>
<p>Los permisos de creación se obtienen realizando un AND binario entre el permiso por defecto y el complemento unario (NOT binario) de umask:</p>
<p>Suponiendo que quisiéramos averiguar los permisos de creación de archivos y directorios para umask 027:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">permisos archivos: &nbsp; &nbsp;666 &amp; ~027<br />
permisos directorios: 777 &amp; ~027</div></div>
<p>Recordemos que el complemento unario puede obtenerse fácilmente reemplazando ceros por unos y unos por ceros:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">Complemento unario:<br />
&nbsp;027 = 000 010 111<br />
~027 = 111 101 000</div></div>
<p>Luego de obtener el complemento unario se procede a realizar el AND binario:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">Archivos:<br />
&nbsp;666 = 110 110 110<br />
~027 = 111 101 000<br />
------------------<br />
&nbsp;640 = 110 100 000 &nbsp;&lt;-- (rw-r-----)</div></div>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">Directorios:<br />
&nbsp;777 = 111 111 111<br />
~027 = 111 101 000<br />
------------------<br />
&nbsp;750 = 111 101 000 &nbsp;&lt;-- (rwxr-x---)</div></div>
<h3>En bash</h3>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ <span class="kw3">umask</span> 027<br />
$ <span class="kw2">mkdir</span> foo<br />
$ <span class="kw2">touch</span> bar<br />
$ <span class="kw2">ls</span> <span class="re5">-l</span><br />
drwxr-x--- &nbsp;<span class="nu0">2</span> xleo xleo &nbsp; &nbsp;<span class="nu0">48</span> <span class="nu0">2009</span>-08-<span class="nu0">19</span> 01:09 foo<br />
<span class="re5">-rw-r-----</span> &nbsp;<span class="nu0">1</span> xleo xleo &nbsp; &nbsp; <span class="nu0">0</span> <span class="nu0">2009</span>-08-<span class="nu0">19</span> 01:<span class="nu0">10</span> bar</div></div>
<h3>Referencias</h3>
<ul>
<li><a href="http://www.gnu.org/software/libc/manual/html_node/Setting-Permissions.html" class="external">gnu.org &#8211; Assigning File Permissions</a></li>
<li><a href="http://docstore.mik.ua/orelly/networking/puis/ch05_03.htm" class="external">Practical UNIX &#038; Internet Security &#8211; umask</a></li>
<li><a href="http://en.wikipedia.org/wiki/Umask" class="external">Wikipedia &#8211; umask</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/08/umask/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Humor en comentarios de códigos fuente</title>
		<link>http://blog.calcifer.com.ar/2009/07/humor-en-comentarios-de-codigos-fuente/</link>
		<comments>http://blog.calcifer.com.ar/2009/07/humor-en-comentarios-de-codigos-fuente/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 21:48:46 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[humor]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=443</guid>
		<description><![CDATA[Visto en stackoverflow.com
Algunos de ellos:
// sometimes I believe compiler ignores
// all my comments
// When I wrote this, only God and I understood
// what I was doing. Now, God only knows
if &#40;/*you*/ $_GET&#91;'action'&#93;&#41; &#123; //celebrate
// 
// Dear maintainer:
// 
// Once you are done trying to 'optimize'
// this routine, and have realized what
// a terrible mistake that [...]]]></description>
			<content:encoded><![CDATA[<p class="from">Visto en <a href="http://stackoverflow.com/questions/184618" class="external">stackoverflow.com</a></p>
<p>Algunos de ellos:</p>
<div class="codecolorer-container c " style="overflow:auto;white-space:nowrap;width:435px"><div class="c codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co1">// sometimes I believe compiler ignores</span><br />
<span class="co1">// all my comments</span></div></div>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">// When I wrote this, only God and I understood<br />
// what I was doing. Now, God only knows</div></div>
<div class="codecolorer-container php " style="overflow:auto;white-space:nowrap;width:435px"><div class="php codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="coMULTI">/*you*/</span> <span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st_h">'action'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//celebrate</span></div></div>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">// <br />
// Dear maintainer:<br />
// <br />
// Once you are done trying to 'optimize'<br />
// this routine, and have realized what<br />
// a terrible mistake that was, please<br />
// increment the following counter as a<br />
// warning to the next guy:<br />
// <br />
// total_hours_wasted_here = 16<br />
//</div></div>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">// I'm sorry.</div></div>
<div class="codecolorer-container c " style="overflow:auto;white-space:nowrap;width:435px"><div class="c codecolorer" style="font-family:Monaco,Lucida Console,monospace">virgin <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="coMULTI">/* you're not a virgin anymore, sweety */</span></div></div>
<div class="codecolorer-container php " style="overflow:auto;white-space:nowrap;width:435px"><div class="php codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="sy0">...</span> or <a href="http://www.php.net/die"><span class="kw3">die</span></a> <span class="co1">// bitch</span></div></div>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">// This is crap code but it's 3 a.m. and<br />
// I need to get this working.</div></div>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">// Hard to explain</div></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/07/humor-en-comentarios-de-codigos-fuente/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calculadora de notación polaca inversa en C</title>
		<link>http://blog.calcifer.com.ar/2009/04/calculadora-de-notacion-polaca-inversa-en-c/</link>
		<comments>http://blog.calcifer.com.ar/2009/04/calculadora-de-notacion-polaca-inversa-en-c/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 18:16:13 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=419</guid>
		<description><![CDATA[La Notación Polaca Inversa (RPN en inglés, Reverse Polish Notation) es un método de introducción de datos alternativo al algebráico. Fue creada en 1920 por el matemático polaco Jan Lukasiewicz como una forma de escribir expresiones matemáticas sin tener que utilizar paréntesis y corchetes.
En la notación polaca inversa los operadores suceden a sus operandos. Por [...]]]></description>
			<content:encoded><![CDATA[<p>La Notación Polaca Inversa (RPN en inglés, Reverse Polish Notation) es un método de introducción de datos alternativo al algebráico. Fue creada en 1920 por el matemático polaco Jan Lukasiewicz como una forma de escribir expresiones matemáticas sin tener que utilizar paréntesis y corchetes.</p>
<p>En la notación polaca inversa los operadores suceden a sus operandos. Por ejemplo, la expresión algebráica<code>5+((1+2)*4)-3</code>se traduce a la notación polaca inversa como<code>5 1 2 + 4 * + 3 -</code>.</p>
<p>Su principio es el de evaluar los datos directamente cuando se introducen y manejarlos dentro de una estructura LIFO (Last In First Out), lo que optimiza los procesos a la hora de programar.</p>
<p>El siguiente programa es una implementación en C de una calculadora que funciona con notación polaca inversa. El programa es una versión modificada del que figura en el libro &#8220;<a href="http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)" class="external">El lenguaje de programación C</a>&#8221; de Kernighan y Ritchie.</p>
<div class="codecolorer-container c blackboard" style="overflow:auto;white-space:nowrap;width:435px;height:500px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br /></div></td><td><div class="c codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co2">## ************</span><br />
<span class="co2">## @file calc.c</span><br />
<span class="co2">## ************</span><br />
<br />
<span class="co2">#include &lt;stdio.h&gt;</span><br />
<span class="co2">#include &lt;stdlib.h&gt;</span><br />
<br />
<span class="co2">#define MAXVAL 100</span><br />
<span class="co2">#define NUMBER '0'</span><br />
<br />
<span class="coMULTI">/**<br />
&nbsp;* &nbsp;Variables<br />
&nbsp;*/</span><br />
<span class="kw4">int</span> verbose<span class="sy0">;</span><br />
<span class="kw4">int</span> sp <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="kw4">double</span> val<span class="br0">&#91;</span>MAXVAL<span class="br0">&#93;</span><span class="sy0">;</span><br />
<br />
<span class="coMULTI">/**<br />
&nbsp;* &nbsp;Prototypes<br />
&nbsp;*/</span><br />
<span class="kw4">int</span> toi <span class="br0">&#40;</span><span class="kw4">char</span> <span class="kw4">const</span> <span class="sy0">*</span>s<span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="kw4">void</span> push <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="kw4">double</span> pop <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="coMULTI">/**<br />
&nbsp;* &nbsp;Main<br />
&nbsp;*/</span><br />
<span class="kw4">int</span> main <span class="br0">&#40;</span><span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="kw4">const</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw4">int</span> offset<span class="sy0">,</span> i<span class="sy0">;</span><br />
&nbsp; <span class="kw4">double</span> op2<span class="sy0">;</span><br />
<br />
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>argc <span class="sy0">&lt;</span> <span class="nu0">2</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; fprintf <span class="br0">&#40;</span>stderr<span class="sy0">,</span> <br />
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;Usage: %s [-v] EXP<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; verbose <span class="sy0">=</span> offset <span class="sy0">=</span> <br />
&nbsp; &nbsp; <span class="br0">&#40;</span>strcmp <span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="st0">&quot;-v&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">?</span> <span class="nu0">1</span> <span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; <br />
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span>i <span class="sy0">=</span> <span class="nu0">1</span> <span class="sy0">+</span> offset<span class="sy0">;</span> i <span class="sy0">&lt;</span> argc<span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>toi <span class="br0">&#40;</span>argv<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">'+'</span> <span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>verbose<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;operator +<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; push <span class="br0">&#40;</span>pop<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> pop<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">'-'</span> <span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>verbose<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;operator -<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; op2 <span class="sy0">=</span> pop<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; push <span class="br0">&#40;</span>pop<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">-</span> op2<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">'*'</span> <span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>verbose<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;operator *<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; push <span class="br0">&#40;</span>pop<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">*</span> pop<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">'/'</span> <span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>verbose<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;operator /<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; op2 <span class="sy0">=</span> pop<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>op2 <span class="sy0">!=</span> <span class="nu16">0.0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push <span class="br0">&#40;</span>pop<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">/</span> op2<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fprintf <span class="br0">&#40;</span>stderr<span class="sy0">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Error: division by zero<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> NUMBER <span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; push <span class="br0">&#40;</span>atof <span class="br0">&#40;</span>argv<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">default</span> <span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fprintf <span class="br0">&#40;</span>stderr<span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Error: unknown operator %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; argv<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; <span class="co1">// Result</span><br />
&nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;%f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> val<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/**<br />
&nbsp;* &nbsp;Toi<br />
&nbsp;*/</span><br />
<span class="kw4">int</span> toi <span class="br0">&#40;</span><span class="kw4">char</span> <span class="kw4">const</span> <span class="sy0">*</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>isdigit<span class="br0">&#40;</span>s<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">?</span> <br />
&nbsp; &nbsp; NUMBER <span class="sy0">:</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span> s<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/**<br />
&nbsp;* &nbsp;Push<br />
&nbsp;*/</span><br />
<span class="kw4">void</span> push <span class="br0">&#40;</span><span class="kw4">double</span> e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sp <span class="sy0">&lt;</span> MAXVAL<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>verbose<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;push %f in %d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> e<span class="sy0">,</span> sp<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; val<span class="br0">&#91;</span>sp<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> e<span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; fprintf <span class="br0">&#40;</span>stderr<span class="sy0">,</span> <span class="st0">&quot;Error: full stack<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/**<br />
&nbsp;* &nbsp;Pop<br />
&nbsp;*/</span><br />
<span class="kw4">double</span> pop <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sp <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="sy0">--</span>sp<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>verbose<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a> <span class="br0">&#40;</span><span class="st0">&quot;pop %f from %d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> val<span class="br0">&#91;</span>sp<span class="br0">&#93;</span><span class="sy0">,</span> sp<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> val<span class="br0">&#91;</span>sp<span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="kw1">else</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; fprintf <span class="br0">&#40;</span>stderr<span class="sy0">,</span> <span class="st0">&quot;Error: empty stack<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu16">0.0</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></td></tr></tbody></table></div>
<p>Para compilarlo ejecutamos</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ <span class="kw2">gcc</span> <span class="re5">-o</span> calc calc.c</div></div>
<p>A diferencia del programa original publicado en el libro de C, aquí se utiliza el array<code>argv[]</code>como fuente de operandos y operadores. Esto permite que podamos llamar al programa desde línea de comandos de la siguiente manera:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ .<span class="sy0">/</span>calc <span class="nu0">5</span> <span class="nu0">1</span> <span class="nu0">2</span> + <span class="nu0">4</span> \<span class="sy0">*</span> + <span class="nu0">3</span> -</div></div>
<p>Notar que para el caso especial del operador multiplicación, debemos <i>escaparlo</i> para evitar la expansión propia de bash antes de la llamada efectiva al programa.</p>
<p>El programa admite la opción<code>-v</code>(verbose), que muestra información acerca de uno de los pasos realizados.</p>
<h4>Ejemplo I</h4>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:435px;height:300px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ ./calc -v 5 1 2 + 4 \* + 3 -<br />
push 5.000000 in 0<br />
push 1.000000 in 1<br />
push 2.000000 in 2<br />
operator +<br />
pop 2.000000 from 2<br />
pop 1.000000 from 1<br />
push 3.000000 in 1<br />
push 4.000000 in 2<br />
operator *<br />
pop 4.000000 from 2<br />
pop 3.000000 from 1<br />
push 12.000000 in 1<br />
operator +<br />
pop 12.000000 from 1<br />
pop 5.000000 from 0<br />
push 17.000000 in 0<br />
push 3.000000 in 1<br />
operator -<br />
pop 3.000000 from 1<br />
pop 17.000000 from 0<br />
push 14.000000 in 0<br />
14.000000</div></div>
<p><span id="more-419"></span></p>
<h4>Ejemplo II</h4>
<p>La expresión algebráica (de resultado -3)</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">(3 * 9 / ((4 - 1) * 3)) - 6</div></div>
<p>Tiene la siguiente notación polaca inversa</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;width:435px;height:300px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ ./calc -v 3 9 \* 4 1 - 3 \* / 6 -<br />
push 3.000000 in 0<br />
push 9.000000 in 1<br />
operator *<br />
pop 9.000000 from 1<br />
pop 3.000000 from 0<br />
push 27.000000 in 0<br />
push 4.000000 in 1<br />
push 1.000000 in 2<br />
operator -<br />
pop 1.000000 from 2<br />
pop 4.000000 from 1<br />
push 3.000000 in 1<br />
push 3.000000 in 2<br />
operator *<br />
pop 3.000000 from 2<br />
pop 3.000000 from 1<br />
push 9.000000 in 1<br />
operator /<br />
pop 9.000000 from 1<br />
pop 27.000000 from 0<br />
push 3.000000 in 0<br />
push 6.000000 in 1<br />
operator -<br />
pop 6.000000 from 1<br />
pop 3.000000 from 0<br />
push -3.000000 in 0<br />
-3.000000</div></div>
<h4>Referencias</h4>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Polish_notation" class="external">Polish notation</a></li>
<li><a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation" class="external">Reverse Polish notation</a></li>
<li><a href="http://h41111.www4.hp.com/calculators/es/es/articles/rpn.html" class="external">RPN: Introducción a la notación polaca inversa</a></li>
<li><a href="http://codigomaldito.blogspot.com/2008/04/calculadora-con-notacin-polaca-inversa.html" class="external">Calculadora con notación polaca inversa en C</a><br />(código original publicado en libro de C)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/04/calculadora-de-notacion-polaca-inversa-en-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tiempos de ejecución de un proceso</title>
		<link>http://blog.calcifer.com.ar/2009/04/tiempos-de-ejecucion-de-un-proceso/</link>
		<comments>http://blog.calcifer.com.ar/2009/04/tiempos-de-ejecucion-de-un-proceso/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 15:32:10 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[gnu/linux]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=404</guid>
		<description><![CDATA[Traducción de What do ‘real’, ‘user’ and ‘sys’ mean in the output of time?
$ time foo
real &#160;0m13.520s 
user &#160;0m1.628s
sys &#160; 0m1.420s

Real
Tiempo real transcurrido desde que el proceso comienza hasta que finaliza. Esto implica el tiempo utilizado por otros procesos ejecutándose al mismo tiempo y el tiempo en que el proceso se encuentra bloquedo (por ejemplo, [...]]]></description>
			<content:encoded><![CDATA[<p class="from">Traducción de <a href="http://stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1/556411" class="external">What do ‘real’, ‘user’ and ‘sys’ mean in the output of time?</a></p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ <span class="kw1">time</span> foo<br />
real &nbsp;0m13.520s <br />
user &nbsp;0m1.628s<br />
sys &nbsp; 0m1.420s</div></div>
<dl>
<dt>Real</dt>
<dd>Tiempo real transcurrido desde que el proceso comienza hasta que finaliza. Esto implica el tiempo utilizado por otros procesos ejecutándose al mismo tiempo y el tiempo en que el proceso se encuentra bloquedo (por ejemplo, esperando que una llamada al sistema como I/O se complete).</dd>
<dt>User</dt>
<dd>Tiempo de CPU empleado por el proceso en modo usuario (fuera del núcleo). El tiempo de CPU de otros procesos y el tiempo de espera de una llamada al sistema no cuentan en este valor.</dd>
<dt>Sys</dt>
<dd>Tiempo empleado por el núcleo para atender peticiones del proceso. Esto significa tiempo de uso de CPU en llamadas al sistema dentro del núcleo, como por ejemplo I/O.</dd>
</dl>
<p><strong>User+Sys</strong> equivale al total de tiempo de CPU usado por el proceso.</p>
<p><span id="more-404"></span></p>
<h4>Diferencia entre &#8216;Kernel mode&#8217; y &#8216;User mode&#8217;</h4>
<p>En Unix, o cualquier otro sistema operativo de memoria protegida, &#8216;Kernel&#8217; o &#8216;Supervisor&#8217; es el modo privilegiado en que la CPU puede operar. Ciertas acciones que pueden afectar la seguridad o estabilidad del sistema solo pueden ser realizadas cuando la CPU funciona en este modo. Estas acciones no están disponibles para aplicaciones de usuario. Un ejemplo de este tipo de acciones podría ser la de manipular la <a href="http://en.wikipedia.org/wiki/Memory_management_unit" class="wikipedia">MMU</a> para tener acceso al espacio de direcciones de otro proceso. Normalmente, el código en modo usuario no puede hacer esto, aunque puede solicitar memoria compartida desde el Kernel, la que podría ser leída y escrita por más de un proceso. En este caso la memoria compartida es solicitada explícitamente por el Kernel a través de un mecanismo seguro y los diferentes procesos pueden utilizarla mediante llamadas también explícitas.</p>
<p>El modo privilegiado es generalmente denominado &#8216;Kernel mode&#8217; debido a que es el núcleo el ejecutado por la CPU cuando se ejecuta en este modo.</p>
<p>Las llamadas al sistema en la librería C (particularmente aquellas que se describen en la sección 2 de las páginas man) tienen un componente en modo usuario, que es el que realmente hace la llamada desde el programa. Una página que describe el sistema de llamadas proporcionadas por el núcleo Linux puede encontrarse <a href="http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html" class="external">aquí</a>.</p>
<h4>Aclaración acerca de Sys time</h4>
<p>Hay ciertas cosas que el código de usuario no puede hacer. Asignar memoria o acceder a un hardware (HDD, red, etc) solo pueden hacerse bajo supervisión del núcleo, y sólo él puede hacerlo. Algunas operaciones como<code>malloc</code>o<code>fread/fwrite</code>, invocarán esta supervisión del núcleo y entonces contarán como &#8216;Sys time&#8217;. Desafortunadamente no es tan sencillo como &#8220;cada llamada a malloc será contada como Sys time&#8221;. Una llamada a malloc pasa cierto tiempo procesando su componente de modo usuario (entonces contará como &#8216;User time&#8217;), luego invocará la función del núcleo (lo que contará como &#8216;Sys time&#8217;) y finalmente, cuando retome el control luego de la llamada al sistema, usará probablemente algo más de tiempo de usuario (que contará como &#8216;User time&#8217;).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/04/tiempos-de-ejecucion-de-un-proceso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Snippets en Vim con snipMate</title>
		<link>http://blog.calcifer.com.ar/2009/03/snippets-en-vim-con-snipmate/</link>
		<comments>http://blog.calcifer.com.ar/2009/03/snippets-en-vim-con-snipmate/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 04:13:42 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=392</guid>
		<description><![CDATA[Basado en el editor TextMate (mac), snipMate.vim es un plugin que permite insertar pedazos de código de uso frecuente simplemente tipeando parte del mismo y apretando&#60;tab&#62;.
Por ejemplo, supongamos que estamos editando un programa en C y queremos agregar un ciclo for, simplemente escribimosfor&#60;tab&#62;y esto se expandirá en un típico bucle de C
for &#40;i = 0; [...]]]></description>
			<content:encoded><![CDATA[<p>Basado en el editor <a href="http://macromates.com/" class="external">TextMate</a> (mac), <a href="http://www.vim.org/scripts/script.php?script_id=2540" class="external">snipMate.vim</a> es un plugin que permite insertar pedazos de código de uso frecuente simplemente tipeando parte del mismo y apretando<code>&lt;tab&gt;</code>.</p>
<p>Por ejemplo, supongamos que estamos editando un programa en C y queremos agregar un ciclo for, simplemente escribimos<code>for&lt;tab&gt;</code>y esto se expandirá en un típico bucle de C</p>
<div class="codecolorer-container c blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="c codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">for</span> <span class="br0">&#40;</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> count<span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="coMULTI">/* code */</span><br />
<span class="br0">&#125;</span></div></div>
<p>Inmediatamente después el cursor quedará resaltando la palabra &#8220;count&#8221; para que podamos reemplazarla por nuestra condición de fin. Un par de tabs más nos llevarán al cuerpo del ciclo donde podremos seguir utlizando snippets como<code>pr&lt;tab&gt;</code>, lo que expandirá en la función printf</p>
<div class="codecolorer-container c blackboard" style="overflow:auto;white-space:nowrap;width:435px"><div class="c codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw1">for</span> <span class="br0">&#40;</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> <span class="nu0">10</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></div></div>
<p>snipMate tiene una sintáxis muy sencilla (según dicen, muy similar a la usada por TextMate) lo que permite crear nuestros propios snippets, o mejorar los existentes. La versión actual (0.77) trae una colección de snippets para los siguientes lenguajes: C, Obj-C, C++, Sh, TeX, Java, Ruby, Perl, Python, PHP, JavaScript, y HTML.</p>
<p>El proyecto parace estar bastante activo y la última versión es del 30/03/2009.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/03/snippets-en-vim-con-snipmate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Accediendo a MySQL con Python y MySQLdb</title>
		<link>http://blog.calcifer.com.ar/2009/03/accediendo-a-mysql-con-python-y-mysqldb/</link>
		<comments>http://blog.calcifer.com.ar/2009/03/accediendo-a-mysql-con-python-y-mysqldb/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 15:00:27 +0000</pubDate>
		<dc:creator>lvidarte</dc:creator>
				<category><![CDATA[None]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.calcifer.com.ar/?p=330</guid>
		<description><![CDATA[MySQLdb es un módulo que implementa la API estándar (PEP249) para manejo de bases de datos, en este caso MySQL. MySQLdb es en realidad un wrapper del módulo _mysql que provee Python, el cual implementa la mayoría de las funciones definidas en la API C de MySQL. La idea de definir una API estándar es [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sourceforge.net/projects/mysql-python" class="external">MySQLdb</a> es un módulo que implementa la <a href="http://www.python.org/dev/peps/pep-0249/">API estándar (PEP249)</a> para manejo de bases de datos, en este caso <a href="http://www.mysql.com" class="external">MySQL</a>. MySQLdb es en realidad un wrapper del módulo _mysql que provee Python, el cual implementa la mayoría de las funciones definidas en la <a href="http://mysql-python.sourceforge.net/MySQLdb.html#mysql-c-api-function-mapping">API C de MySQL</a>. La idea de definir una API estándar es que uno debería poder cambiar a otra base de datos sin modificar demasiado el código.</p>
<blockquote title="python.org"><p>This API has been defined to encourage similarity between the Python modules that are used to access databases.</p></blockquote>
<h3>Instalación MySQLdb</h3>
<p>El paquete que nos provee el módulo se llama python-mysqldb. Podemos comprobar que lo tenemos instalado mediante</p>
<div class="codecolorer-container bash " style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw2">dpkg</span> <span class="re5">--get-selections</span> <span class="sy0">|</span> <span class="kw2">grep</span> python-mysqldb</div></div>
<p>Si no existe lo instalamos</p>
<div class="codecolorer-container bash " style="overflow:auto;white-space:nowrap;width:435px"><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="kw2">sudo</span> <span class="kw2">apt-get</span> <span class="kw2">install</span> python-mysqldb</div></div>
<p>Para comprobar que efectivamente tenemos el módulo disponible y funcionando llamamos al <a href="http://docs.python.org/tutorial/interpreter.html" class="external">intérprete de Python</a> y escribimos</p>
<div class="codecolorer-container python " style="overflow:auto;white-space:nowrap;width:435px"><div class="python codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="sy0">&gt;&gt;&gt;</span> <span class="kw1">import</span> MySQLdb</div></div>
<p>Un silencioso retorno de carro indica que podemos <a href="http://xkcd.com/353/" class="external">el módulo ha sido cargado</a>. Salimos del intérprete con<code>C-d</code>.</p>
<h3>Creación de una DB de pruebas</h3>
<p>Para nuestro ejemplo crearemos una base de datos con una única tabla. Entramos a la <a href="http://dev.mysql.com/doc/refman/5.1/en/mysql.html" class="external">consola de MySQL</a> y escribimos</p>
<div class="codecolorer-container mysql " style="overflow:auto;white-space:nowrap;width:435px"><div class="mysql codecolorer" style="font-family:Monaco,Lucida Console,monospace">mysql<span class="sy1">&gt;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=CREATE&amp;lr=lang_en"><span class="kw1">CREATE</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=DATABASE&amp;lr=lang_en"><span class="kw2">database</span></a> test<span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> <span class="nu0">1</span> row affected <span class="br0">&#40;</span><span class="nu0">0.01</span> sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=USE&amp;lr=lang_en"><span class="kw1">USE</span></a> test<span class="sy2">;</span><br />
<a href="http://search.mysql.com/search?site=refman-51&amp;q=DATABASE&amp;lr=lang_en"><span class="kw2">Database</span></a> changed<br />
mysql<span class="sy1">&gt;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=CREATE&amp;lr=lang_en"><span class="kw1">CREATE</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=TABLE&amp;lr=lang_en"><span class="kw1">TABLE</span></a> users <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> id <a href="http://search.mysql.com/search?site=refman-51&amp;q=INT&amp;lr=lang_en"><span class="kw4">INT</span></a> <a href="http://dev.mysql.com/doc/refman/5.1/en/non-typed-operators.html"><span class="kw10">NOT</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=NULL&amp;lr=lang_en"><span class="kw3">NULL</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=AUTO_INCREMENT&amp;lr=lang_en"><span class="kw6">AUTO_INCREMENT</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=PRIMARY%20KEY&amp;lr=lang_en"><span class="kw1">PRIMARY KEY</span></a><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> name <a href="http://search.mysql.com/search?site=refman-51&amp;q=VARCHAR&amp;lr=lang_en"><span class="kw4">VARCHAR</span></a><span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> lastname <a href="http://search.mysql.com/search?site=refman-51&amp;q=VARCHAR&amp;lr=lang_en"><span class="kw4">VARCHAR</span></a><span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> <span class="br0">&#41;</span><span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> <span class="nu0">0</span> rows affected <span class="br0">&#40;</span><span class="nu0">0.01</span> sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=INSERT&amp;lr=lang_en"><span class="kw2">INSERT</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=INTO&amp;lr=lang_en"><span class="kw1">INTO</span></a> users <span class="br0">&#40;</span>name<span class="sy2">,</span> lastname<span class="br0">&#41;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=VALUES&amp;lr=lang_en"><span class="kw1">VALUES</span></a><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> <span class="br0">&#40;</span><span class="st0">'Juan'</span><span class="sy2">,</span> <span class="st0">'Perez'</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> <span class="br0">&#40;</span><span class="st0">'Ana Maria'</span><span class="sy2">,</span> <span class="st0">'Lopez'</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="sy1">-&gt;</span> <span class="br0">&#40;</span><span class="st0">'Carlos L.'</span><span class="sy2">,</span> <span class="st0">'Gutierrez'</span><span class="br0">&#41;</span><span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> <span class="nu0">3</span> rows affected <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span><br />
Records: <span class="nu0">3</span> &nbsp;Duplicates: <span class="nu0">0</span> &nbsp;<a href="http://search.mysql.com/search?site=refman-51&amp;q=WARNINGS&amp;lr=lang_en"><span class="kw1">Warnings</span></a>: <span class="nu0">0</span></div></div>
<p>Nuestra tabla users quedó entonces</p>
<div class="codecolorer-container mysql " style="overflow:auto;white-space:nowrap;width:435px"><div class="mysql codecolorer" style="font-family:Monaco,Lucida Console,monospace">mysql<span class="sy1">&gt;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=SELECT&amp;lr=lang_en"><span class="kw1">SELECT</span></a> <span class="sy1">*</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=FROM&amp;lr=lang_en"><span class="kw1">FROM</span></a> users<span class="sy2">;</span><br />
<span class="sy1">+----+-----------+-----------+</span><br />
<span class="sy1">|</span> id <span class="sy1">|</span> name &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> lastname &nbsp;<span class="sy1">|</span><br />
<span class="sy1">+----+-----------+-----------+</span><br />
<span class="sy1">|</span> &nbsp;<span class="nu0">1</span> <span class="sy1">|</span> Juan &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> Perez &nbsp; &nbsp; <span class="sy1">|</span> <br />
<span class="sy1">|</span> &nbsp;<span class="nu0">2</span> <span class="sy1">|</span> Ana Maria <span class="sy1">|</span> Lopez &nbsp; &nbsp; <span class="sy1">|</span> <br />
<span class="sy1">|</span> &nbsp;<span class="nu0">3</span> <span class="sy1">|</span> Carlos L. <span class="sy1">|</span> Gutierrez <span class="sy1">|</span> <br />
<span class="sy1">+----+-----------+-----------+</span><br />
<span class="nu0">3</span> rows <a href="http://search.mysql.com/search?site=refman-51&amp;q=IN&amp;lr=lang_en"><span class="kw2">in</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=SET&amp;lr=lang_en"><span class="kw1">set</span></a> <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span></div></div>
<h3>Creación del script mysqldb.py</h3>
<p>Creamos el siguiente script que se conectará a la base de datos test y traerá todos los datos de los usuarios cargados en la tabla users. En el script es necesario reemplazar &lt;user&gt; y &lt;pass&gt; por los datos requeridos para acceder a tu DB.</p>
<div class="codecolorer-container python " style="overflow:auto;white-space:nowrap;width:435px;height:300px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="python codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co1">#!/usr/bin/python</span><br />
<span class="kw1">import</span> MySQLdb<br />
<br />
<span class="co1"># Conexion a la base de datos</span><br />
conn = MySQLdb.<span class="me1">connect</span> <span class="br0">&#40;</span>host=<span class="st0">&quot;localhost&quot;</span>,<br />
&nbsp; &nbsp; <span class="kw3">user</span>=<span class="st0">&quot;&lt;user&gt;&quot;</span>, passwd=<span class="st0">&quot;&lt;pass&gt;&quot;</span>, db=<span class="st0">&quot;test&quot;</span><span class="br0">&#41;</span><br />
<br />
<span class="co1"># Creacion cursor</span><br />
cursor = conn.<span class="me1">cursor</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<br />
<span class="co1"># Ejecucion query</span><br />
cursor.<span class="me1">execute</span><span class="br0">&#40;</span><span class="st0">&quot;SELECT * FROM users&quot;</span><span class="br0">&#41;</span><br />
<br />
<span class="co1"># Manejo de datos devueltos por la consulta</span><br />
<span class="kw1">while</span> <span class="kw2">True</span>:<br />
&nbsp; &nbsp; row = cursor.<span class="me1">fetchone</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> row <span class="kw1">is</span> <span class="kw2">None</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;id: %s<span class="es0">\t</span>name: %s %s&quot;</span> <span class="sy0">%</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>row<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, row<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, row<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<br />
<span class="co1"># Finalizado cursor y objeto conexion</span><br />
cursor.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
conn.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></td></tr></tbody></table></div>
<p>La salida debería ser</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:435px"><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">id: 1 &nbsp; name: Juan Perez<br />
id: 2 &nbsp; name: Ana Maria Lopez<br />
id: 3 &nbsp; name: Carlos L. Gutierrez</div></div>
<h4>Links recomendados para ampliar conocimientos</h4>
<ul>
<li><a href="http://mysql-python.sourceforge.net/MySQLdb.html" class="external">MySQLdb User&#8217;s Guide</a></li>
<li><a href="http://www.kitebird.com/articles/pydbapi.html" class="external">Writing MySQL Scripts with Python DB-API</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.calcifer.com.ar/2009/03/accediendo-a-mysql-con-python-y-mysqldb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
