On a nice Monday evening, I had the idea of checking out who actually releases the most packages for Mandriva, tooking cooker repository as the base. So I did a simples script which grabbed the latest 50.000 commits to Mandriva packages subversion repository, and did some graphs out of it. Note that this only counts the commits into the packages repo – and this number can very loosely be mapped into the number of package releases. Of course, it is not a definitive metric, because most committers do multiple commits before releasing a package, and some use only the ‘mdvsys update’ command, so it is not a quite fair comparison between them. But I thought that it is better to have some metrics than no metrics at all :) .

So, in April, Funda Wang managed an impressive number of 600+ commits. He was followed by jquelin and goetz, with almost 200 commits each, then neoclust and cfergeau (I’ll mark Mandriva current/former employees with bold marks for the sake of clarity) with a bit more than 100 commits, and then by many others.

Committers for April 2010

In May, neoclust got his revenge and ranked at number 1 with almost 300 commits. Funda came second with approximately 150 commits, and then we had thomas, tpg, fcrozat and guillomovitch.

Commits history for May/2010

In June, fcrozat beat the competition with his almost 100 commits. Thomas, goetz, ahmadsamir, neoclust, fwang, oden and me were the ones to do more than 20 package commits. Note that during this month cooker was frozen, so only the approved and highly-trusted fixes were accepted into it.

Commits for June/2010

July was the month of jquelin to be the king of the hill, he did an insane number of 800+ package rebuilds for perl. Funda came second with 500+ updates, then goetz, tpg and kharec.

Commits for July/2010

Funda regain the leadership in August, handling over 600 packages. Goetz got the second place with 400+, and jquelin – still on the perl rampage – did another 200+ packages. Neoclust was forth, with a bit more than 100 packages.

Commits history for August/2010

Goetz was the master-packager in September, delivering over 400 commits. Funda Wang got the silver medal with 300+ packages, and peroyvind delivered more than 100 packages as well. Jquelin, tpg, neoclust and oden were not far behind either.

September/2010 commits

And finally, now, in the first few days of October, Funda already managed to leave all the competition way behind, already being responsible for almost 200 commits. He is being followed by tv with about 60 packages, the thomas and goetz who almost got to 50 packages each, and peroyvind and oden, with about 40 and 30 packages each one.

October/2010 commits

So, considering the period from March 30rd to October 11th, the top-10 commiters in Mandriva Linux community are:

  • fwang: 2492
  • goetz: 1511
  • jquelin: 1375
  • neoclust: 739
  • tpg: 416
  • guillomovitch: 414
  • thomas: 374
  • peroyvind: 363
  • ahmadsamir: 339
  • oden: 320

In this list, Oden is working at Mandriva, and Neoclust was working on kde packages until the last month. But besides them, I guess it can be safely assumed that Mandriva community contribution to the distribution is far from inexistent :) .

Every time I try to switch to a different desktop environment/window manager, there is just one simple feature which always make me go back to xfce – the possibility to quickly switch back to previous virtual desktop. A simple but extremely addictive feature, which only xfwm4 was offering…

…until yesterday! I became tired on metacity not offering this feature, so I just went ahead and implemented it overnight (learning a lot about gnome development during the process).

So, if anyone out there was missing this feature – feel free to grab this patch and apply it to the metacity source. Basically, it will add one new gconf entry (switch_to_previous_workspace), and will make metacity remember the last workspace. So you can press ctrl-f2 to switch to from workspace 1 workspace 2, and when you press ctrl-f2 again metacity will recognize that you want switch back, to whatever workspace you were before, and will do it.

Once again, this is the beauty of the open source. If there is something you need, but nobody implemented it, you always have the possibility of just doing it yourself. At least, sometimes :) .

diff -p -up metacity-2.30.1/src/core/prefs.c.switch metacity-2.30.1/src/core/prefs.c
--- metacity-2.30.1/src/core/prefs.c.switch 2010-03-30 11:35:40.000000000 -0300
+++ metacity-2.30.1/src/core/prefs.c    2010-05-06 17:47:14.000000000 -0300
@@ -97,6 +97,7 @@ static char *cursor_theme = NULL;
 static int   cursor_size = 24;
 static gboolean compositing_manager = FALSE;
 static gboolean resize_with_right_button = FALSE;
+static gboolean switch_to_previous_workspace = TRUE;
 static gboolean force_fullscreen = TRUE;

 static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
@@ -412,6 +413,11 @@ static MetaBoolPreference preferences_bo
       &resize_with_right_button,
       FALSE,
     },
+    { "/apps/metacity/general/switch_to_previous_workspace",
+      META_PREF_SWITCH_TO_PREVIOUS_WORKSPACE,
+      &switch_to_previous_workspace,
+      FALSE,
+    },
     { NULL, 0, NULL, FALSE },
   };

@@ -1757,6 +1763,9 @@ meta_preference_to_string (MetaPreferenc

     case META_PREF_FORCE_FULLSCREEN:
       return "FORCE_FULLSCREEN";
+
+    case META_PREF_SWITCH_TO_PREVIOUS_WORKSPACE:
+      return "SWITCH_TO_PREVIOUS_WORKSPACE";
     }

   return "(unknown)";
@@ -2719,6 +2728,12 @@ meta_prefs_get_mouse_button_menu (void)
   return resize_with_right_button ? 2: 3;
 }

+guint
+meta_prefs_switch_to_previous_workspace (void)
+{
+  return switch_to_previous_workspace;
+}
+
 gboolean
 meta_prefs_get_force_fullscreen (void)
 {
diff -p -up metacity-2.30.1/src/core/screen-private.h.switch metacity-2.30.1/src/core/screen-private.h
--- metacity-2.30.1/src/core/screen-private.h.switch    2010-01-14 22:31:32.000000000 -0200
+++ metacity-2.30.1/src/core/screen-private.h   2010-05-06 17:47:14.000000000 -0300
@@ -80,7 +80,7 @@ struct _MetaScreen
   MetaUI *ui;
   MetaTabPopup *tab_popup;

-  MetaWorkspace *active_workspace;
+  MetaWorkspace *active_workspace, *last_workspace;

   /* This window holds the focus when we don't want to focus
    * any actual clients
diff -p -up metacity-2.30.1/src/core/workspace.c.switch metacity-2.30.1/src/core/workspace.c
--- metacity-2.30.1/src/core/workspace.c.switch 2010-01-14 22:31:32.000000000 -0200
+++ metacity-2.30.1/src/core/workspace.c    2010-05-06 18:00:39.000000000 -0300
@@ -377,7 +377,31 @@ meta_workspace_activate_with_focus (Meta
                 meta_workspace_index (workspace));

   if (workspace->screen->active_workspace == workspace)
-    return;
+  {
+      meta_verbose("Switching to same workspace detected, going back to previous one!!\n");
+      if (meta_prefs_switch_to_previous_workspace()) {
+          if (workspace->screen->last_workspace) {
+              meta_verbose("Going to desktop %d\n", meta_workspace_index(workspace));
+              meta_workspace_activate_with_focus(workspace->screen->last_workspace,
+                      NULL, timestamp);
+              return;
+          } else {
+              meta_verbose("No old workspace..\n");
+              return;
+          }
+      } else {
+          meta_verbose("Last workspace switching disabled..\n");
+          return;
+      }
+  }
+  else
+  {
+      if (workspace->screen->active_workspace)
+          meta_verbose("Updating last workspace.. current: %d, new: %d\n",
+                  meta_workspace_index(workspace->screen->active_workspace),
+                  meta_workspace_index(workspace));
+      workspace->screen->last_workspace = workspace->screen->active_workspace;
+  }

   if (workspace->screen->active_workspace)
     workspace_switch_sound(workspace->screen->active_workspace, workspace);
diff -p -up metacity-2.30.1/src/include/prefs.h.switch metacity-2.30.1/src/include/prefs.h
--- metacity-2.30.1/src/include/prefs.h.switch  2010-01-14 22:31:32.000000000 -0200
+++ metacity-2.30.1/src/include/prefs.h 2010-05-06 17:47:14.000000000 -0300
@@ -60,7 +60,8 @@ typedef enum
   META_PREF_CURSOR_SIZE,
   META_PREF_COMPOSITING_MANAGER,
   META_PREF_RESIZE_WITH_RIGHT_BUTTON,
-  META_PREF_FORCE_FULLSCREEN
+  META_PREF_FORCE_FULLSCREEN,
+  META_PREF_SWITCH_TO_PREVIOUS_WORKSPACE
 } MetaPreference;

 typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
diff -p -up metacity-2.30.1/src/metacity.schemas.in.in.switch metacity-2.30.1/src/metacity.schemas.in.in
--- metacity-2.30.1/src/metacity.schemas.in.in.switch   2010-05-06 17:47:14.000000000 -0300
+++ metacity-2.30.1/src/metacity.schemas.in.in  2010-05-06 18:01:16.000000000 -0300
@@ -4,6 +4,24 @@
     <!-- General preferences -->        

     <schema>
+      <key>/schemas/apps/metacity/general/switch_to_previous_workspace</key>
+      <applyto>/apps/metacity/general/switch_to_previous_workspace</applyto>
+      <owner>metacity</owner>
+      <type>bool</type>
+      <default>false</default>
+      <locale name="C">
+         <short>Remember and recall previous workspace when switching via keyboard shortcuts</short>
+         <long>
+           Set this to true to allow to switch to previous workspace when
+           using the current workspace keybinding. For example, if you switched
+           from workspace 2 to workspace 1 by pressing keyboard shortcut for
+           workspace 1, pressing the same shortcut again while on workspace 1
+           will switch to workspace 2.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/metacity/general/mouse_button_modifier</key>
       <applyto>/apps/metacity/general/mouse_button_modifier</applyto>
       <owner>metacity</owner>
diff -p -up metacity-2.30.1/src/metacity.schemas.in.switch metacity-2.30.1/src/metacity.schemas.in
--- metacity-2.30.1/src/metacity.schemas.in.switch  2010-04-06 07:10:38.000000000 -0300
+++ metacity-2.30.1/src/metacity.schemas.in 2010-05-06 18:01:06.000000000 -0300
@@ -4,6 +4,24 @@
     <!-- General preferences -->        

     <schema>
+      <key>/schemas/apps/metacity/general/switch_to_previous_workspace</key>
+      <applyto>/apps/metacity/general/switch_to_previous_workspace</applyto>
+      <owner>metacity</owner>
+      <type>bool</type>
+      <default>false</default>
+      <locale name="C">
+         <short>Remember and recall previous workspace when switching via keyboard shortcuts</short>
+         <long>
+           Set this to true to allow to switch to previous workspace when
+           using the current workspace keybinding. For example, if you switched
+           from workspace 2 to workspace 1 by pressing keyboard shortcut for
+           workspace 1, pressing the same shortcut again while on workspace 1
+           will switch to workspace 2.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/metacity/general/mouse_button_modifier</key>
       <applyto>/apps/metacity/general/mouse_button_modifier</applyto>
       <owner>metacity</owner>
@@ -247,7 +265,7 @@
       <applyto>/apps/metacity/general/theme</applyto>
       <owner>metacity</owner>
       <type>string</type>
-      <default>Clearlooks</default>
+      <default>Ia Ora Steel</default>
       <locale name="C">
          <short>Current theme</short>
          <long>

Working on Mandriva network tools, I looked on one of the most essential ones the network monitor (net_monitor). It was introduced a couple of releases before, and was mostly doing its job. However, it has a number of flaws and lack of features that motivated us to look closer at it.

Our old friend net_monitor, present in your favorite Mandriva distro!

Our old friend net_monitor, present in your favorite Mandriva distro!

The net_monitor currently used in all Mandriva versions is written in perl, is using internal drakx-net api (and is, therefore, only usable on Mandriva), and also have some issues such as memory leaks and non-usual interface. After a few thoughts and discussions we came to conclusion that it would be more adequate to project and rewrite it from scratch, turning it more modular, expansible and focused on common use cases.

Initially, I thought on using perl to write it, so it would still be part of drakx-net suite. However, after thinking on the code and the way it should work I felt that my brain was going to melt down :) (perl is a nice language, but it is certainly not that compatible with me). So I ended up with python, which is my language of choice (together with C). Also, I’ve received many comments saying that the net_monitor is no more relevant, as every desktop environment provides its own network monitoring tool, and it should be dropped from drakx-net. By combining those issues, we came to decision that it would be more proper to separate net_monitor into a different package – this way, it won’t depend on any drakx-net internal functionalities, and user could uninstall it if required and use his own network monitoring tool if he wants to. And, at the same time, users would still have a cute little network monitoring application on their machines.

So, as a picture says more than a thousand words, I guess I’ll just add some pictures here than additional KBs of text :) (EDIT: please note that the look and features of net_monitor have changed significantly in Mandriva since this post):

net_monitor monitoring a wireless connection

net_monitor monitoring a wireless connection

net_monitor monitoring a connection for which network accounting was not enabled

net_monitor monitoring a connection for which network accounting was not enabled

net_monitor displaying some statistics about your network usage (provided by vnstat)

net_monitor displaying some statistics about your network usage (provided by vnstat)

looking at daily traffic statistics on my notebook for the past month

looking at daily traffic statistics on my notebook for the past month

...and hourly statistics...

...and hourly statistics...

...and finding our when I killed my bandwidth..

...and finding our when I killed my bandwidth..

Surely, this is just an early and preliminary version, with many missing features and such. If you want to give it a try, just install net_monitor package, and it will create /usr/bin/net_monitor executable for you. It won’t conflict with existent net_monitor from drakx-net which is installed in /usr/sbin, so both of them may coexist on your system. If you look at /usr/share/doc/net_monitor/TODO, you’ll see some of the ideas that I intend to add to it, but the idea is to keep it simple and not transform it into an emacs of network monitoring :) . And, of course, feel free to add your comments and suggestions (and bug reports) here!

P.S.: Just to prevent comments like ‘you should focus on fixing bugs instead of wasting time writing new things’. Net_monitor is present in Mandriva for years now, and if you look at bugzilla list it has a number of bugs and issues. So I am not creating a new app – I am bringing back from the land of the dead an old one :) .

P.P.S.: Answering in advance to another question – yes, it would work on any Linux distro which has python and pygtk. You’ll just have to add some tricks into your network startup scripts to enable vnstat integration, but it will work just fine even without that.

Time has come for the first msec release since Mandriva 2009.1!

This time we have several improvements, such as:

  • support for audit plugins
  • more msec auditing checks
  • improved auditing logging
  • and, of course, bugfixes.

So let me introduce some details about each one of them.

Support for audit plugins

You may remember that msec shipped with Mandriva 2009.1 introduced support for plugins infrastructure (take a look at your /usr/share/msec/plugins/ directory to see some examples). This new msec, which will be shipped with Mandriva 2010, also introduces auditing plugins.

Well, you might be asking what the ..? what is the difference between those plugins?, so let me clarify it a bit.

Msec has two main functionalities:

  • Security configuration
  • Security auditing

The security configuration is what you configure using msecgui or using security levels – basically, you say what settings should be used on your machine for ssh, user logins, and all kind of system configuration. The security auditing are those background checks that run daily on your machine, to determine what has changed since the last run and let you know about that.

In old msec, this security auditing was performed by security.sh, security_check.sh and diff_check.sh, so we had just three large and complex files with a lot of duplicated code. With new msec version, everything was split to reduce code duplication, improve readability and simplify plugins creation.

Let me show you a sample plugin which checks for changes in system users:

    #!/bin/bash
    # msec: check for changes in local users

    # check if we are run from main script
    if [ -z "$MSEC_TMP" -o -z "$INFOS" -o -z "$SECURITY" -o -z "$DIFF" ]; then
            # variables are set in security.sh and propagated to the subscripts
            echo "Error: this check should be run by the main msec security check!"
            echo "       do not run it directly unless you know what you are doing."
            return 1
    fi

    # files to log the list of today's and yesterday's, and difference between them
    USERS_LIST_TODAY="/var/log/security/users_list.today"
    USERS_LIST_YESTERDAY="/var/log/security/users_list.yesterday"
    USERS_LIST_DIFF="/var/log/security/users_list.diff"

    # update yesterday's list
    if [[ -f ${USERS_LIST_TODAY} ]]; then
        mv ${USERS_LIST_TODAY} ${USERS_LIST_YESTERDAY};
    fi

    # check for changes in users
    if [[ ${CHECK_USERS} == yes ]]; then
        getent passwd | cut -f 1 -d : | sort > ${USERS_LIST_TODAY}
        Diffcheck ${USERS_LIST_TODAY} ${USERS_LIST_YESTERDAY} ${USERS_LIST_DIFF} "local users"
    fi

that’s it. You just drop this file into /usr/share/msec/scripts/01_check_for_users.sh and this check will be executed every time msec security checks are run. The security log will be updated, the diff check mail will be created and mailed (along with all other checks), and it will be working automatically from now on.

More msec auditing checks

A few additional msec auditing checks were added:

  • CHECK_FIREWALL — checks for changes in iptables configuration
  • CHECK_USERS — checks for changes in local users (most of its code was shown above actually)
  • CHECK_GROUPS — checks for changes in local groups
  • FIX_OWNER — if unowned files are found on the system, this check gives the opportunity to change their ownership to nobody/nogroup, instead of blindly doing it automatically
  • CHECK_RPM_PACKAGES — checks for changes in installed RPM packages
  • CHECK_RPM_INTEGRITY — checks all the installed packages for changed files. Both those checks were run before under the CHECK_RPM check, but, as they are quite expensive, these two new checks were introduced instead

If you are using cooker or 2010 alpha, these options will not be added automatically to your /etc/security/msec/security.conf configuration file. The best way to experiment with them is by using msecgui, or running msec -f standard or msec -f secure to install default configuration for standard and secure levels.

Besides those items, I was thinking on an option to check for changes in PAM authentication, check for failed login attempts and support for rkhunter. And, as always, if you have any idea on some other functionality that should be interesting to have in msec, feel free to comment!

Improved auditing logging

The logging format of /var/log/security.log was changed to be compatible with syslog-based logging. This should make it easier for system applications to parse it, and for administrator to examine its contents. Now it is way easier to find information by date, kind of message and check type.

Other ideas

Among other ideas for msec I thought on the following:

  • msec supports an arbitrary number of custom security levels, but msecgui only supports two basic ones (standard and secure). It could be nice to have a combobox to select a custom profile..
  • gui for TOMOYO security framework, since the AppArmor project looks quite stone-cold dead. This is already a work in progress, so probably I’ll post some update on this later.
  • Support for administrator-supplied rules for security and diff checks. For example, to exclude everything matching ‘/var/tmp’ from any kind of checks and reports, or excluding network ports from 3000 to 5000 from open port checks.

Besides that, there is a number of bugfixes (which are going to be backported to 2009.1 shortly).

So msec is definitely is alive and getting better and better. Stay tuned for more news! :)

I wondered why my .git directory of drakx-net was using about 70MB of disk space (I am accessing the SVN repository using git svn). Of course, I have read that periodic git repository clean could drastically save space and speed, but – what the heck – it is just a bunch of text files. So I never bothered with it.

However, after running git gc on top of drakx-net directory, the .git directory size went from 70MB down to 4MB. A 17.5x improvement! Unbelievable!

So I did the same to msec repository, with quite similar results — from 21MB down to 3MB!

So a mental note to myself – run git gc always. It rocks.

Trabalhando com mandriva, vira e mexe encontro gente falando em francês. Como já faz quase 14 que não falo essa língua ;) , decidi apelar pro meu querido python e google translator.

Nada como uns 10 minutos de programação voltada a gambiarras :) .

#!/usr/bin/python
#
# quick and dirty french2english translator
#

import urllib
import urllib2
from subprocess import Popen, PIPE

URL='http://translate.google.com/translate_t#fr|en|'

print "Paste your message"
msg = []
while 1:
    try:
        line = raw_input('>> ')
        msg.append(line)
    except:
        break

s = ">>" + "\n>>".join(msg)

data = "http://translate.google.com/translate_a/t?client=t&%s&fr&tl=en" % urllib.urlencode({'text':s})
req = urllib2.Request('http://translate.google.com/translate_t', data, {'User-Agent':'Mozilla/5.0'})
resp = urllib2.urlopen(req).read()
p = Popen("lynx -dump -stdin | grep -- '>>'", shell=True, stdin=PIPE, stdout=PIPE)
p.stdin.write(resp)
p.stdin.close()
trans = p.stdout.read()
print trans

Agora é só dar ctrl-c no texto, depois rodar o programinha e dar ctrl-v seguido por ctrl-d :) .

Perl would be Voodoo – An incomprehensible series of arcane incantations that involve the blood of goats and permanently corrupt your soul. Often used when your boss requires you to do an urgent task at 21:00 on friday night.

huauhahahahaha

via Aegisub: If programming languages were religions….

Ultimamente eu uso bastante programação funcional em python para tudo. Entretanto, fiquei brincando hoje e descobri que nem sempre ela oferece os melhores resultados.

Por exemplo, vamos imaginar a função que vai fazer todas as combinações entre os elementos de uma lista. Ela pode ser escrita de forma funcional:

# permutate-func
def permutate(l):
    '''Returns all possible combinations of list values'''
    return reduce(lambda x, y: y + x, [ [(x, y) for y in l if x != y] for x in l ])

ou de forma iterativa:

# permutate-iter
def permutate(l):
    '''Returns all possible combinations of list values'''
    res = []
    for x in l:
        for y in l:
            if x != y:
                res.append((x, y))
    return res

Para listas pequenas não temos muita diferença de desempenho. Agora para listas maiores (por exemplo, com 1000 strings):

dups=['string%d' % x for x in range(1000)]
permutate(dups)

temos os seguintes resultados para programação funcional:

# time permutate-func
real    0m24.494s
user    0m20.763s
sys 0m1.698s

e os seguintes para o algoritmo iterativo:

# time permutate-iter
real    0m1.191s
user    0m1.150s
sys 0m0.036s

O tempo de 24 segundos caiu para apenas 1 segundo!

Qual conclusão tiramos disso? Embora programação funcional é extremamente poderosa, em alguns casos é melhor usar outras soluções para o problema :) .

Mais um exemplo do poder de python + gtk. Para tirar um screenshot da tela, salvando-o em formato JPEG, o seguinte código é suficiente:

from gtk.gdk import *
screenshot = Pixbuf(COLORSPACE_RGB, False, 8, screen_width(), screen_height())
screenshot.get_from_drawable(get_default_root_window(), colormap_get_system(), \
    0, 0, 0, 0, screen_width(), screen_height())
screenshot.save("tela.jpg", "jpeg", {"quality": "75"})

(Tá certo, dividi em 5 linhas para melhorar a legibilidade, mas no fundo são só 4 linhas mesmo).

Uma das maiores vantagens do python para mim é a legibilidade do código, facilidade de programação, e eficiência. Com quantas linhas de código seria possível fazer esse exemplo em qualquer outra linguagem? (Não vale apelar para import -window root tela.jpg porque aí é ImageMagick que faz toda a mágica!) :)

Cada vez mais e mais eu gosto dos recursos de programação funcional em python. E, como eu uso essa linguagem para resolver tarefas mais variáveis, não dá para não perceber que a velocidade de desenvolvimento e eficiência do código tornam-se cada vez melhores, por simplesmente aplicar técnicas de programação funcional.

Por exemplo, sem a programação funcional, eu usava o seguinte código antes para ler um arquivo com uma série de números, e determinar a média dos valores:

fd = open("data.log")
data = fd.readlines()
valores = []

le os dados

for line in data: line_val = float(line.strip()) valores.append(line_val)

calcula a media

media = 0 for item in valores: media += item media /= len(media)

Re-escrevendo isso com técnicas de programação funcional, temos o seguinte:

le os valores do arquivo, transformando-os para floats, e ignorando strings vazias

valores = [float(val) for val in open("data.log").readlines() if len(val) > 1]

calcula a media, somando todos os valores e dividindo pelo número de elementos no vetor

media = reduce(lambda x, y: x+y, valores) / len(valores)

(É óbvio que é só um exemplo rápido, não estou tratando as excessões aqui, mas para resolver problemas simples do dia-a-dia é mais de que suficiente!)

O essencial são as funções lambda, map, reduce e filter. Todos os detalhes interessantes sobre esse estilo de programação eu achei aqui, e recomendo essa apresentação para todos!

© 2012 Eugeni's blog Suffusion theme by Sayontan Sinha