Enrico's pages/ tags/ rant

Rants, kept to a bare minimum and strictly with a useful component.

How to autologin X without a display manager

How to autologin X without a display manager

Problem: configure a custom Debian box used to drive some industrial machinery. The system should boot directly into the GUI control application, that runs full screen, with root privileges. Everything should respawn if X is killed or the control application dies.

In theory, you'd run an X display manager with autologin, then run matchbox-window-manager and the control application as the X session. You wish. At the end of the post is an explanation of why this way failed.

So, here is how to get the whole thing to work, without a display manager.

Use init to drive the whole thing:

6:23:respawn:/sbin/getty -L -n -l /usr/local/sbin/autologin

This will respawn everything if it dies, stop respawning if it dies all the time, avoid starting it in single user mode, and not ask for a username.

/usr/local/sbin/autologin contains:

#!/bin/sh
/bin/login -f root MAINAPP=true

This will autologin as root, setting an extra env variable.

Then comes root's ~/.bash_profile, that just starts X if we are doing autologin:

if [ "$MAINAPP" = "true" ]
then
    startx
    logout
fi

If the application was running as a special user, we could have made things simpler and just used startx as the shell for that user; however, we still want root to have bash as the shell, and the above hack does it.

Finally, root's ~/.xsession:

#!/bin/sh

matchbox-window-manager &

# If the touch screen is not calibrated, run the calibration
while [ ! -f /etc/touchscreen-calibration ]
do
        calibrate-touchscreen
done

# Run the main application: if it ends, the session ends
main-application

And there we go, no dependencies at all.

Why not using a display manager

gdm and kdm seem to do autologin, but their dependency list is not acceptable for something that should just respawn an X server in an industrial system that must be kept simple.

xdm on the other hand has a small set of dependencies, but its developers seem to have decided that autologin is a ""glitz", and there is no need for it in such a bare-bones display manager".

Dict for "glitz" gives "tasteless showiness". What one has to bear...

wdm seems however even more disconcerting, as it "doesn't actually support autologin but you can set the default user and default password in /etc/X11/wdm/wdm-config. Now, [...] you only need to press Enter twice [...] to login".

Figure how this would look in the manual: "After powering up the unit, attach a USB keyboard and press enter twice to start the system".

And this is why we are not using a display manager.

Posted Fri 13 Jun 2008 03:16:01 CEST Tags: rant
LDAP user database errors

LDAP user database errors

In case your machine uses an external LDAP server for the user database, and you see this error:

id: ldap-nss.c:1376: do_init: Assertion `cfg->ldc_uris[__session.ls_current_uri] != ((void *)0)' failed.

The solution is to check that you have no passwords in /etc/libnss-ldap.conf and make it world readable, because software needs to access it in order to access the user database.

This is apparently "normal" folk knowledge. Already in the BTS.

Now, why is /etc/libnss-ldap.conf not world readable by default? Because a debconf question offers it to be that way. Why does it do so? I have no idea, since passwords should go in the not world readable /etc/libnss-ldap.secret anyway.

Why do we get that assertion instead of something like cannot read /etc/libnss-ldap.conf?

These sort of obscure errors or behaviours happen so often that I start to believe it's an intentional coding style. Maybe LDAP needs to be something for élite sysadmins with a painful initiation path, so that only the Worth and Pure of Spirit can use the only sane way to have a central user database in Linux.

I almost feel like if I disclose these tricky bits one day I will be tied to a rock with an eagle eating my liver.

Posted Sun 25 May 2008 22:24:34 CEST Tags: rant
How to view the fingerprint of the ssh host key

How to view the fingerprint of the ssh host key

This way, ready to copy and paste:

ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key

Background:

It already takes a lot of resources to recall that to see the host key fingerprint you need to run something called 'keygen'. Then ssh-keygen doesn't support --help: it will try to generate a new key instead. We're in 2008. There should be a law against this sort of behaviour.

To figure out how to see the host key, you need to dig through a long manpage with no examples section. ssh-keygen does have commandline help, but does not implement any switch to invoke it (check the getopt invocation in the source code if you don't believe me). It will however show commandline help when given an unrecognised option, so it will mutter but at least give you love if you ask for it:

$ ssh-keygen -♥
ssh-keygen: illegal option -- 
Usage: ssh-keygen [options]
Options:
  [...]

After figuring out that it's -l -f, you still have to go and fish the file wherever it is. And luckily we had the recent Debian openssh problems, so now I can get the fingerprint of the RSA file only and be done with it.

But thanks to this blog entry, no more of that, at last.

Posted Sat 17 May 2008 14:38:13 CEST Tags: rant
Meet the Italian income agency

Meet the Italian income agency

The Italian income agency decided to publish online all the income levels for each and every single citizen and company in the country.

I did not manage to see the actual data, because the entire income agency website was swamped with request and timing out all the time. You should have heard the comments of my accountant, who every day needs to access other parts of the website for work.

That service is supposed to have been taken offline now, after the Italian privacy watchdog issued a polite What The Fuck! Why Didn't You Tell Us Anything About This? sort of note. The minister defended himself by saying "I can't see what is the problem, it's the same in all the world: if you want proof just watch any American TV series". What a wise man. I should watch some of The Greatest American Hero again.

Since I could not see the actual data, I could not verify if what people were saying was actually true, that is that income information were published together with the full home address, providing a nice shopping list for house robbers, kidnappers and the other kind of professionals that would politely wait next to your door for you to come home late in the night.

But fear not, the website was protected from bots: it used a captcha.

Not only that: in order to comply with standard accessibility rules, the website used a perfectly accessible captcha:

Screenshot of full text captcha

You can't get more accessible than that: the captcha is displayed in plain text, so any accessibility technology will be able to read it. Plus, anyone can easily copy and paste it into the text box. And if someone needs to do it often, it's even trivial to write a script that does it for you!

But it's unfair to say that it was just plain text: it was cleverly encrypted:

<div class="educaptcha"><label for="educaptcha">I<!-- id9113507 -->nser<span>ire </span><span>nel c</span><span>ampo</span> di <!-- id5058508 -->v<span>erific</span><span>a suc</span><!-- id2643358 -->ces<span>sivo i</span><!-- id2500023 -->l valore <span>695</span><span>8571</span>4<!-- id3588853 -->:</label>
<input id="educaptcha" type="text" name="ucaptcha" value="" maxlength="10" size="20" /></div>

For your convenience, here is the version cracked with a malicious :%s/<[^>]\+>//g in vim. If you do not speak Italian, you can still look for this phrase in the screenshot above:

Inserire nel campo di verifica successivo il valore 69585714:

The meaning is of course:

Insert the value 69585714 in the following verification field:

It's been a fun day for Italians online.

Posted Wed 30 Apr 2008 23:11:55 CEST Tags: rant
Italian National Anthem

Italian National Anthem

Christian mentions that he likes the Italian National Anthem, although not the words.

No Italian in their right mind likes the words; luckily we are generally not forced to learn them, so we can allow ourselves to not give a damn about it. Which is our general strategy to deal with all the insanity we get every day.

What's the point of a nationalist anthem anyway, when the people who care most about the country are wishing for the Germans to invade us?

Anyway, here's my attempt at national anthem lyrics that suck less, for the benefit of those, like Christian, who like the music but not the words.

Fratelli d'Italia
L'Italia s'è desta,
Chi cazzo è sto Scipio
Che ci han messo in testa.
Non c'è la Vittoria
che porge la chioma,
Siam schiavi di Roma
E del Vatican.
Scongiuri alla sorte
Si rischia la morte
Si spera di no.

Noi siamo da secoli
Calpesti, derisi,
Perché siam mafiosi
ladroni e collusi.
Si rischia di nuovo
di aver Berluscone
Dell'emigrazione
Già l'ora suonò.
Scongiuri alla sorte
Si rischia la morte
Si spera di no.

Uniamoci, amiamoci,
l'unione, e l'amore
Ridanno alla gente
Il suo buonumore;
Giuriamo far sesso
sul suolo natío:
Chiaviamo, perdío,
Chi dice di no?
Scongiuri alla sorte
Si rischia la morte
Si spera di no.

Dall'Alpi a Sicilia
Noi ti condoniamo,
Ogn'uom di Bettino
Ha il core, ha la mano,
I bimbi d'Italia
Fan calcio balilla,
Bastardo chi frulla
Gancin non si può.
Scongiuri alla sorte
Si rischia la morte
Si spera di no.

I nostri politici
Son tutti venduti:
Si sente dall'Austria
L'odor dei rifiuti.
Lavora in Italia,
Il nero, il Polacco,
In nero, perbacco,
Io lo pagherò.

Scongiuri alla sorte
Si rischia la morte
Si spera di no.

Posted Sun 23 Mar 2008 14:32:19 CET Tags: rant
make distcheck and LaTeX

make distcheck and LaTeX

When building LaTeX documentation on a VPATH build, if your .tex file includes other files in the same directory, LaTeX will complain that it cannot find them. The reason is because in a VPATH build, latex is invoked like this:

latex ../../doc/manual.tex

What we need here is an equivalent to cc's -Idir for latex.

latex --help doesn't mention of such an option, nor of useful environment variables.

Googling a bit seems to suggest --include-directory=dir, but that gives me: unrecognized option '--include-directory=../../doc'

The manpage doesn't list commandline options. It however says:

The complete documentation for this version of TeX can be found in the info file or manual Web2C: A TeX implementation.

Without saying where that manual is, if it's installed and where, or what package installs it, or if instead should I look it up on the web.

info latex gives the manpage itself, of course.

Googling the title of that manual finds it, and it's a long one. Reading through, it points at the kpathsea manual, which then mentions you can set TEXINPUTS_latex, which however doesn't add but overrides, so your document will find the includes maybe, but not the LaTeX styles and other stuff.

But then later on it mentions that in the env variable you can use "default expansion", and it's another page of manual to read which tells you to put an extra colon in the end of the env var.

After half an hour of googling and trying things and cursing loud, here is the solution, which I hope will save others from this ugly search.

%.aux: %.tex
    TEXINPUTS="$(srcdir):" latex $<

# Oh, yes, and bibtex requires BIBINPUTS instead
%.bbl: %.aux
    BIBINPUTS="$(srcdir):" bibtex `basename $< .aux`

Posted Tue 18 Mar 2008 13:51:58 CET Tags: rant
Uploading gpsdrive tracks to openstreetmap

Uploading gpsdrive tracks to openstreetmap

I've got some gpsdrive tracks and my area is blank on openstreetmap.

People pointed me at gpsbabel, and it took me a while to figure how it works. For the record, don't do any of this:

gpsbabel -i gpsdrive -o gpx -f track0000.sav -F track0000.gpx
gpsbabel -i gpsdrive -o gpx track0000.sav track0000.gpx

What you would have to do is this:

gpsbabel -i gpsdrive -f track0000.sav -o gpx -F track0000.gpx

However, it would choke on gpsdrive's "missing" points with all values set to 1001. You can grep them out, then gpsbabel would work, but openstreetmap would reject the data because the points have no timestamp: gpsbabel won't carry that on from the gpsdrive tracks to the GPX tracks.

The way to go is here, which contains a link to a tiny little perl script that will do the proper conversion for you:

./gpsdrive2gpx.pl track0000.sav > track0000.gpx

Those you can upload them to openstreetmap, at last.

Posted Sat 08 Mar 2008 17:12:45 CET Tags: rant
Formatting numbers with iostream

Formatting numbers with iostream

What is the output of this C++ program?

#include <stdio.h>
#include <iostream>
#include <iomanip>

using namespace std;

main()
{
    printf("%05d\n", -3);
    cout << setw(5) << setfill('0') << -3 << endl;
}

It turns out that it is:

-0003
000-3

To get the numbers where you'd like them to be, you do it this way:

printf("%05d\n", -3);
cout << setw(5) << setfill('0') << internal -3 << endl;

Compare with C to see why C++ iostream is not really that much used. Also, setfill and internal are persistently changing the state of the stream, contributing fancy and interesting side effects:

cout << setw(5) << setfill('0') << internal << -3 << endl;
cout << setw(10) << "ciao" << endl;

this prints:

-0003
000000ciao

and I didn't see any sort of RAII save and restore of the stream state, nor a particularly obvious way to reset the stream to factory settings. Suppose that the function foo throws an exception here:

try {
    cout << setfill('=');
    cout << setw(10) << foo() << endl;
    cout << setfill(' ');
} catch (MyException& e) {
    // Catch this hypotetical exception
    cerr << setw(3) << e.errCode() << ": " << e.msg() << endl;
}

Then the state of the stream never gets reset, and the error code ends up being padded with equals instead of the default space. What would the alternative be, reset the stream state after each function call in the code? Or am I missing something?

Update: here are some suggested, but still not optimal, ways of dealing with it:

From Simon Richter:

std::cout << (std::stringstream() << "foo" << std::setw(8) << "bar").rdbuf() << std::endl;

From Peter De Wachter:

fstream tmp;
tmp.copyfmt(cout);
cout << setw(5) << setfill('0') << internal << -3 << endl;
cout.copyfmt(tmp);
cout << setw(10) << "ciao" << endl;

This is a possible RAII class to save the stream state (based on Peter De Watcher's approach), but I suspect that creating a fstream for every block that uses iomanip operators is rather heavyweight:

    struct SaveIOState
    {
            fstream tmp;
            ostream& s;
            SaveIOState(ostream& s) : s(s)
            {
                    tmp.copyfmt(s);
            }
            ~SaveIOState()
            {
                    s.copyfmt(tmp);
            }
    };

And this is a lightweight version, again thanks to Sylvain Sauvage:

class SaveIOState
{
    ios_base& s;
    ios_base::fmtflags f;
public:
    SaveIOState(ios_base& s) : s(s), f(s.flags())
    {}
    ~SaveIOState()
    {
        s.flags(f);
    }
};

Posted Thu 06 Mar 2008 16:26:16 CET Tags: rant
How to work with python-m2crypto

How to work with python-m2crypto

This is a little howto on how to understand the m2crypto Python module, beyond the examples provided:

  1. Build the documentation as explained here
  2. Look at the documentation, which does not contain a single comment
  3. Click the links that show the source (for example, of M2Crypto.SMIME.SMIME.verify)
  4. Look what openssl function gets called by the function you are interested in (for example, pkcs7_verifysomething))
  5. Google the name of that openssl function, trying a few variations, until you find the openssl manpage that tells you what it does, in detail (for example, pcks_verify)
  6. Understand what it does, and backport the understanding to the thin convenience layer that m2crypto adds on top of it
  7. Realise that now you also understand the corresponding openssl smime -verify commandline invocation, and that next time instead of reading the openssl manpage you should look at the openssl api docs instead.
Posted Fri 08 Feb 2008 16:45:50 CET Tags: rant
Servizio Abuse Tiscali

Servizio Abuse Tiscali

Ricevo spam spedito tramite Tiscali e lo forwardo al loro servizio di abuse:

From: Enrico Zini <...>
To: Servizio Abuse Tiscali <...>
Subject: Spam da un vostro utente

Buon giorno,

ve la giro cosí come mi è arrivata.

Cordiali saluti,

Enrico

Brillante la risposta (top-quoting, X-Mailer: Microsoft Outlook Express, e contenuto inutile su almeno due livelli: cosa chiedere di piú?):

Gentile Cliente,
le posso consigliare, per bloccare l'arrivo di ogni mail dai mittenti
indesiderati, di utilizzare le apposite funzioni del nuovo tiscali mail. Più
precisamente, dopo aver avuto accesso al tiscali mail dalla pagina
http://mail.tiscali.it/cp/sso/Login.jsp , dovrà inserire il flag sul
messaggio indesiderato e cliccare sulla voce "Blocca"
Tutta la posta in arrivo da tali indirizzi verrà inserita nella cartella
spam.

Posted Thu 26 Jul 2007 00:43:17 CEST Tags: rant