Parasite, wake up!

Hi there!

In the last weeks I’ve been working on GTK+ themes, customizing some apps, and I missed the tools we have on the web world that allow us to to some live editing on CSS.

I remembered we had Parasite, a tool similar to Firebug, but for GTK+ apps. Unfortunately it didn’t support CSS tweaking. But it does now! I’ve made some improvements on it mainly to allow live editing of CSS, but not limited to that.

Some changes so far:

  • Live editing of CSS, for the whole application, or only for the selected widget
  • Ability to add/remove a CSS class for a specific widget. (Editing of pseudo-classes like :hover is planned)
  • In the Property inspector, if a property itself is another Object, we can also inspect it. (For example, you can inspect a Buffer inside a TextView)
  • A bit of UI change

I have made a small video showing the improvements:


Link to the video

The code is on the usual place, github: https://github.com/chipx86/gtkparasite

Please, test it and file bugs/wishes/pull requests. /me is now wearing the maintainer hat :)

Note: it requires GTK+ 3.10 (and optionally python+gobject introspection for the python shell)

Joining Intel

Today is my last day at Oi WiFi.

It has been 1 year and a half since I moved from my small city (Maceió) to the biggest, craziest Brazilian city, São Paulo. I don’t regret!

I’m lucky to have joined a great company (Vex at the time. Oi WiFi nowadays), with great people where I learnt a lot. I’m glad for the things I helped to improve, I’m sure we have better products than before and I’m proud to be part of that progress. I leave as legacy the spirit of the Free Software, where we can (and should) contribute back to projects we use and improve internally. Every improvement we made here we submitted back to projects like Openwrt, busybox, glib, etc.
However things and priorities in the company have changed a bit in the last few months. Time to look for a new challenge in my career.

What a challenge!

At Intel I’ll join the OTC – Intel Open Source Technology Center, and will work on Open Source projects such as Tizen, EFL, Webkit and hopefully GTK+ :)
The team I’ll work with is formed by the former Profusion company, acquired by Intel in the beginning of the year. Profusion was a company that I admired even before it was acquired by Intel :)

I’m very excited to join Intel. It’s a great opportunity in a great company and I don’t want to disappoint them!

I hope to publish here very soon the things I’m working on under the Intel umbrella. See you!

Shell script that updates itself

Recently I needed to write a shell script that updates itself, and, surprising, I found it an easy job to do. I will share the recipe here.

In my use case, I’m developing a kind of software updater and, before updating the system packages, I need to check if there is a new version of this software updater. If there is, then I update myself and run my new copy on-the-fly.

Enough talk, show me the code. I’ll paste here a simple shell script that talks by itself:

#!/bin/sh

SCRIPT_NAME="$0"
ARGS="$@"
NEW_FILE="/tmp/blog.sh"
VERSION="1.0"

check_upgrade () {

  # check if there is a new version of this file
  # here, hypothetically we check if a file exists in the disk.
  # it could be an apt/yum check or whatever...
  [ -f "$NEW_FILE" ] && {

    # install a new version of this file or package
    # again, in this example, this is done by just copying the new file
    echo "Found a new version of me, updating myself..."
    cp "$NEW_FILE" "$SCRIPT_NAME"
    rm -f "$NEW_FILE"

    # note that at this point this file was overwritten in the disk
    # now run this very own file, in its new version!
    echo "Running the new version..."
    $SCRIPT_NAME $ARGS

    # now exit this old instance
    exit 0
  }

  echo "I'm VERSION $VERSION, already the latest version."
}

main () {
  # main script stuff
  echo "Hello World! I'm the version $VERSION of the script"
}

check_upgrade
main

To try this script:
1) save it somewhere
2) save a copy of it at /tmp/blog.sh (as pointed at line 5)
3) modify the variable “VERSION” (line 6) of that copy, to, say, “2.0″.
4) run the original script (not the one at /tmp)

You will see that the script updated itself and ran the “new” 2.0 version.

Try running again the original script (step 4 above). See the difference? It doesn’t update itself anymore, because it is the “latest” version.

A small thing you might notice: at line 19, I deleted the “new file”. That’s merely for this educational example, that we check if there’s a new version of the script by just checking if a file exists in the disk. On real life (with apt/yum or any smarter process) this is not needed as our check for a new version (line 13) will naturally fail.

This was tested with bash, dash and busybox’s ash. Worked fine.

I hope it’s useful to someone. Comments are welcome!

g_list_copy_deep and g_slist_copy_deep in GLib

If you have in your code things like that:

copy = g_slist_copy (list);
g_slist_foreach (copy, g_object_ref, NULL);

In GLib 2.34 (to be released soon) you can do:

copy = g_slist_copy_deep (list, g_object_ref, NULL);

Thus eliminating another loop in the list (one loop is done when copying the list).

In other words, there’s now a function to do a deep (full) copy of a GList and GSList. It accepts, besides the list to be cloned, a function as a second argument, and a user data as the third argument. That function will be called for each element in the list.

To free the new list, use g_list_free_full().

Programmatically managing iptables rules in C: IPTC

Sometimes we need to manage iptables rules from inside our own programs. The recommended solution given by iptables developers is to spawn the iptables command with execl() or system(). It’s explicitly stated that there’s no stable/public API to do that: http://www.netfilter.org/documentation/FAQ/netfilter-faq-4.html#ss4.5

However, if you have control of your box, including kernel, iptables, and all related packages, it’s safe to use IPTC to programmatically manage iptables rules.

IPTC is an internal iptables library that actually inserts/removes the rules. It’s used by the iptables (xtables-multi, iptables-save, iptables-restore) binaries. Depending on how iptables was compiled, there might be a shared libiptc.so object and/or a static libiptc.a object.

You should check that in order to correctly build your application. In Debian/Ubuntu, which this post is based, it’s enough to install the iptables-dev package. It will install the shared libraries, the header files and the pkg-config facility.

So, let’s take a look at a complete function that adds a rule to iptables:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <libiptc/libiptc.h>

static int
insert_rule (const char *table,
             const char *chain, 
             unsigned int src,
             int inverted_src,
             unsigned int dest,
             int inverted_dst,
             const char *target)
{
  struct
    {
      struct ipt_entry entry;
      struct xt_standard_target target;
    } entry;
  struct xtc_handle *h;
  int ret = 1;

  h = iptc_init (table);
  if (!h)
    {
      fprintf (stderr, "Could not init IPTC library: %s\n", iptc_strerror (errno));
      goto out;
    }

  memset (&entry, 0, sizeof (entry));

  /* target */
  entry.target.target.u.user.target_size = XT_ALIGN (sizeof (struct xt_standard_target));
  strncpy (entry.target.target.u.user.name, target, sizeof (entry.target.target.u.user.name));

  /* entry */
  entry.entry.target_offset = sizeof (struct ipt_entry);
  entry.entry.next_offset = entry.entry.target_offset + entry.target.target.u.user.target_size;
  
  if (src)
    {
      entry.entry.ip.src.s_addr  = src;
      entry.entry.ip.smsk.s_addr = 0xFFFFFFFF;
      if (inverted_src)
        entry.entry.ip.invflags |= IPT_INV_SRCIP;
    }

  if (dest)
    {
      entry.entry.ip.dst.s_addr  = dest;
      entry.entry.ip.dmsk.s_addr = 0xFFFFFFFF;
      if (inverted_dst)
        entry.entry.ip.invflags |= IPT_INV_DSTIP;
    }

  if (!iptc_append_entry (chain, (struct ipt_entry *) &entry, h))
    {
      fprintf (stderr, "Could not insert a rule in iptables (table %s): %s\n", table, iptc_strerror (errno));
      goto out;
    }

  if (!iptc_commit (h))
    {
      fprintf (stderr, "Could not commit changes in iptables (table %s): %s\n", table, iptc_strerror (errno));
      goto out;
    }

  ret = 0;
out:
  if (h)
    iptc_free (h);

  return ret;
}

int main (int argc, char **argv)
{
  unsigned int a, b;

  inet_pton (AF_INET, "1.2.3.4", &a);
  inet_pton (AF_INET, "4.3.2.1", &b);

  insert_rule ("filter",
               "INPUT",
               a,
               0,
               b,
               1,
               "DROP");
  return 0;
}

Note: The code above was compiled and tested against the 1.4.13 version of iptables.
To compile:

cc `pkg-config –cflags –libs libiptc` source-file.c -o test-iptc

So, the code in main() above does the equivalent of:

iptables -t filter -A INPUT -s 1.2.3.4/32 ! -d 4.3.2.1/32 -j DROP

The main functions used were iptc_init, iptc_append_entry and iptc_commit. There are functions to remove a rule (iptc_delete_num_entry), to iterate over all the rules (iptc_first_rule, iptc_next_rule) and to clear all rules (iptc_flush_entries).

You can check the header file libiptc/libiptc.h to see all available functions and their descriptions. I can post some more examples here in the future if there’s demand to it.

Again, remember that there’s no API stability in IPTC, so, it can change in each new version of iptables.

Hope it’s useful to someone. Feel free to ask anything or to report any issues you have. See you!

Linux firewall: Mac filtering – iptables and arptables

[english]

It’s common: you don’t want just filter the access by IP address, but also by the MAC address. The solution can be quite simple: use the MAC module of iptables:

iptables -A INPUT -s 1.2.3.4 -m mac ! –mac-source aa:bb:cc:dd:ee:ff -j DROP


The command above says: Drop every packet with source ip address 1.2.3.4 and its MAC address is NOT aa:bb:cc:dd:ee:ff. Thus you’re forcing the origin of the packet to be the desired one.


However there is a minor issue with that approach: iptables manages packets at the network (IP) layer, which is above the link (MAC) layer. What does that mean? Simple: Once the packet arrives at the network interface, it’s handled by the MAC layer and then it’s forwarded to the IP layer. That’s where iptables filter it. Again, what’s the problem? At this pointer, the ARP table of the kernel was touched, meaning that (using the example above), if a packet with source IP 1.2.3.4 and source MAC 00:00:00:00:00:01 arrives, it will change the ARP entry in the kernel table to point the IP 1.2.3.4 to that wrong MAC address. After that, the packet is forwarded to the above layer, which is then dropped by iptables from go on over the network. Even if the packet is dropped, which is what you want, your ARP table is messed up right now.


That’s where arptables command comes in. It works just like iptables, but it filters packets at MAC layer, preventing the kernel ARP table being touched by wrong packets. Its syntax is very similar to iptables (in fact, it’s a copy of iptables adapted to work in the lower level). The same command (iptables) above could be better implemented with arptables:

arptables -A IN -s 1.2.3.4 ! –source-hw aa:bb:cc:dd:ee:ff -j DROP


You just need this rule, it’s not necessary to have the iptables rules anymore. arptables needs a kernel with support built in, which I guess most distros do, just like they do with iptables.


Take a look at the arptables man page, it has some examples. Its similarity with iptables facilitates our lives.

[português]

É uma situação comum: você não quer apenas filtrar o acesso por endereço IP, mas também pelo endereço MAC. A solução pode ser bastante simples: usar o módulo MAC do iptables:

iptables -A INPUT -s 1.2.3.4 -m mac ! –mac-source aa:bb:cc:dd:ee:ff -j DROP


O comando acima diz: Descarte todos os pacotes com o endereço IP de origem 1.2.3.4 e cujo endereço MAC não é aa:bb:cc:dd:ee:ff. Assim, você está forçando a origem do pacote a ser a desejada.


No entanto, há um pequeno problema com essa abordagem: o iptables gerencia pacotes na camada de rede (IP), que é acima da camada de enlace (MAC). O que significa isso? Simples: Quando o pacote chega na interface da rede, ele é tratado pela camada MAC e depois é encaminhado para a camada IP. É onde iptables o filtra. Novamente, qual é o problema? Neste ponto, a tabela ARP do kernel foi alterada, o que significa que (usando o exemplo acima), se um pacote com o IP origem 1.2.3.4 e MAC 00:00:00:00:00:01 chega, ele vai mudar a entrada na tabela ARP do kernel para apontar o IP 1.2.3.4 para o endereço MAC errado. Depois disso, o pacote é encaminhado para a camada superior, que é então descartado pelo iptables de continuar na rede. Mesmo o pacote sendo descartado, que é o que você deseja, sua tabela ARP está uma bagunça agora.


É aí que o comando arptables entra. Ele funciona exatamente como o iptables, mas filtra os pacotes na camada MAC, evitando que a tabela ARP do kernel seja alterada por pacotes errados. Sua sintaxe é muito semelhante ao iptables (na verdade, é uma cópia do iptables adaptado para trabalhar num nível mais baixo). O mesmo comando (iptables) acima poderia ser melhor implementado com arptables:

arptables -A IN -s 1.2.3.4 ! –source-hw aa:bb:cc:dd:ee:ff -j DROP


Você só precisa dessa regra, não é necessário ter as regras de iptables mais. o arptables precisa que o kernel tenha suporte, o que eu acho que a maioria das distribuições já fazem, assim como eles fazem com o iptables.


Dê uma olhada no man do arptables, lá tem alguns exemplos. Sua semelhança com o iptables facilita nossas vidas.

free() inconsistencies


Hi, folks!


Last week I was porting a program from uClibc to glibc. Everything went fine, until I found a crash to always happen in a certain part of it. The failure was in a call to the free() function. First thing that came in my head: Why the hell is it crashing now, while it used to run fine on uClibc? I made a simple program that simulates the problem:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

typedef struct {
  char *field1;
} s_test;

s_test test = {
  .field1 = NULL
};

int main (int argc, char **argv) {
  s_test *t;

  t = &amp;test;
  free (t);
  t = &amp;test;
  t-&gt;field1 = "bug";
  printf ("%s\n", t-&gt;field1);

  return 0;
}


Look at line 16. I’m executing a free() in a pointer to a static variable, instead of a pointer in the heap (previously allocated with malloc() or similar). It’s expected a crash here, right? Maybe! Yes, if you’re using glibc. No if you’re using uClibc. The above code works like [not] expected. Weird! Everything we learned at the programming school is ruined now :D !


So, we have a similar code here that have been worked for a long time, exactly because it was compiled and run on top of uClibc. I’ve seen this and other behavior differences between uClibc and glibc. The solution? Change the code to make it portable, not only to make it compile, but also so that it have the same behavior on every platform.


I thought it was a bug in uClibc, but I was told it doesn’t break the standards. In fact, standards say, in that case, the behavior is “undefined”. Ah, standards :) … So, in order to avoid surprises like that, here is what I learned: Always code in the right way, even if it comes with a harder job. Don’t say: “hey, it’s working, let’s deploy it!”.


See you!

New challenges

[english]


Hi, folks!


This is a small post, just to share the news with you: I moved to São Paulo (the biggest Brazilian city) to work with what I like the most: linux development! It’s indeed a big step in my career, I’m too excited about my new job: embedded linux developer!


I hope to learn a lot in this new job, and, at the right time, I want to contribute back to FLOSS community, since we use a lot of free software here.


See you!


Software livre, ajude a fazer

Este post é direcionado a programadores. Repasse-o pra todos os programadores que você conhece. O software livre agradece!

Oi gente, esse é um assunto que sempre menciono nos eventos que vou, e que me incomoda bastante. Por estes dias tava com vontade de fazer um post simples e prático sobre o assunto. Felizmente aconteceram 3 coisas que me motivaram a escrevê-lo:

  1. Depois de ter aberto um bug no ano passado, ainda sem solução, resolvi escrever um pequeno patch que foi aceito, com modificações;
  2. Li isso: http://www.dicas-l.com.br/arquivo/yad_yet_another_dialog.php;
  3. Jomar escreveu um ótimo artigo exatamente sobre esse tema: http://www.trezentos.blog.br/?p=5907

Por que as pessoas se referem ao software livre sempre na terceira pessoa: “Eles”? É comum a gente ouvir:

- Quando o software X implementar a feature Y eu migro.
- Software X? Ah, ele tem muitos bugs, prefiro esperar ficar redondo.
- Não gostei da versão nova do software X. Vou ficar na atual ou testar uma alternativa.
- O pessoal do projeto X é devagar demais.

Gente, quando é que vai cair a ficha que o software é livre e que nós podemos mudá-lo? Vocês já pararam pra pensar que podem tornar o software X um software melhor? Não tô entrando aqui no mérito da liberdade de escolha, você é livre pra usar o software que quiser. O recado aqui é para programadores, que querem ao mesmo tempo ganhar experiência e contribuir para um mundo melhor.

Contribuir com código não é um bicho de 7 cabeças. Software é software em todo lugar do mundo, e software livre é a melhor forma de espalhar e receber conhecimento. Vejam aqui um exemplo muito simples, porém prático de como você pode fazer a coisa acontecer, ao invés de simplesmente esperar “eles” resolverem o bug (explicação do item 1 lá de cima):

  • Ano: 2008. Senti a falta de um conversor de moedas no GNOME. Reportei meu desejo no bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=533690. Pouco mais de 1 ano depois esse recurso foi implementado.
  • Ano: 2010. Usando o recurso acima, senti a falta de um botão pra trocar de moedas. Da mesma forma, reportei meu desejo: https://bugzilla.gnome.org/show_bug.cgi?id=633193.
  • Ano: 2011. 7 meses depois, usando muito o recurso e sentindo realmente falta do tal botão, resolvi dar uma olhada no fonte e ver se seria fácil sua implementação. E foi. Submeti um patch, que no mesmo dia foi aceito, com algumas modificações feitas pelo mantenedor. Na próxima versão, a calculadora do GNOME virá com esse recurso.

O que quero mostrar com isso? Que o software livre basicamente é movido por empresas e voluntários. Se uma empresa não tem interesse em determinado recurso (a ponto de alocar um funcionário para implementá-lo), o recurso tem que ser implementado por algum voluntário. Então, ao invés de ficar dizendo “Eles não ligam pra minha opinião, reportei o bug há mais de um ano e nada até agora…”, simplesmente tente resolver você mesmo! Algumas considerações:

  • Mesmo que o seu patch não esteja correto, não tenha medo de enviá-lo. Dependendo do grau de complexidade, o desenvolvedor pode sugerir algumas modificações, explicar porque tá errado, onde tá errado e tal e pedir pra você corrigir e reenviar… ou ele pode simplesmente modificar e seu patch e aplicá-lo diretamente (foi o que aconteceu comigo acima).
  • Há sempre a possibilidade de entrar em contato direto com o desenvolvedor/mantenedor, via email, irc, jabber, etc. Assim, você pode tirar dúvidas, pedir um direcionamento, e coisas do tipo, antes de efetivamente enviar seu patch para avaliação.

Quanto ao item 2 lá em cima, até mencionei minha “indignação” nos microblogs, e algumas pessoas me perguntaram o por quê. Deixa eu explicar: Minha indignação, neste caso, não é com a pessoa do Júlio. Não quero nem discutir isso. É que tô cansado de ver empresas e pessoas que ganham a vida com software livre, seja usando em seu trabalho, seja escrevendo livros, seja dando aulas, enfim, você captou a ideia, e que são aptas a escrever (ou pagar alguém que escreva) código livre mas não o fazem. Neste caso específico, o Júlio citou no post:

“Sempre esperei que a qualquer momento o gnome lançaria uma nova versão deste software [...] Estava enganado, acompanhei o lançamento de diversas revisões do software mas elas simplesmente tratavam bugs e apresentação. Infelizmente nada de inovação. Porém um dia descobri o YAD.”

Veja que o gnome está sendo tratado na terceira pessoa. “Eles”. Segue o mesmo raciocínio que usei acima. Tanto para o Júlio como para os criadores do YAD. Se o zenity não tava atendendo as expectativas, por que não ajuda-lo? Por que não implementar os recursos tão desejados?

Quanto ao item 3 lá de cima, não tenho muito o que falar. Leiam o texto do Jomar, é muito bom!

Enfim, esse “desabafo” é uma forma de mostrar pra vocês que o software livre é nosso! Vamos colaborar mais (com código). Afinal de contas, já recebemos tanto, de tantos desenvolvedores espalhados pelo mundo, o que custa doar um pouco do nosso tempo e conhecimento como uma forma de retribuição?

Então, esse lance de falar na terceira pessoa (“eles”, “o gnome”, “o pessoal do kde”, etc), deixa para os leigos, meros usuários de software. Na próxima vez que for criticar algum software livre, tome ele para si e pense em uma forma de ajudar, beleza? :)

Looking for new maintainers

Hi, folks. Vino and Vinagre are an one-person projects. Since I hadn’t have been much time to improve them, I decided to look for new blood, new maintainers. Perhaps this will be a hard task, since nobody seems to care much about these two GNOME modules.

Anyway, if you are interested, send me an email.