Enrico's pages/ tags/ sw

Software

How to generate bootable USB keys with simple-cdd

How to generate bootable USB keys with simple-cdd

simple-cdd is a lovely piece of software that builds a custom D-I image with the package selection and preseeding of your choice.

Today I was asked to build a bootable USB key with the simple-cdd image. Here is how; the general case is described in the d-i manual:

General USB key preparation:

  1. download vmlinuz and initrd.img from hd-media
  2. apt-get install syslinux mtools mbr
  3. Partition the USB key as needed (from now on, I'll assume the usb key is in the device /dev/sdb1)
  4. Format it as FAT: mkdosfs /dev/sdb1
  5. Put the boot loader in it: syslinux /dev/sdb1
  6. Put the MBR in it: install-mbr /dev/sdb
  7. Mount it: mount /dev/sdb1 /mnt
  8. Copy kernel and initrd: cp vmlinuz initrd.img /mnt/

simple-cdd specific part:

  1. Run build-simple-cdd as usual
  2. Copy the ISO file generated by build-simple-cdd in the USB key. Any name will do, as long as it ends in .iso the installer will find it
  3. Configure the boot loader, fetching the kernel command line out of the cdrom boot loader generated by simple-cdd:
    • echo default vmlinuz > /mnt/syslinux.cfg
    • grep append tmp/cd-build/etch/boot1/isolinux/isolinux.cfg | head -1 | sed -e 's/^\t//' -e 's/ initrd=[^ ]*/ initrd=initrd.gz/' >> /mnt/syslinux.cfg

This is it, it works nicely, perfectly scriptable, tested today.

Posted Wed 14 May 2008 00:40:06 CEST Tags: sw
Setting environment variables at X login

Setting environment variables at X login

I've been asked how to set a variable after gdm has done login. ~/.bashrc is not an option, as it's only run by shells, but we want the variable to be set in every X application that is started.

The answer is:

Forget about ~/.xinitrc. ~/.xsession and ~/.Xsession: at least in gnome-session, they do not work.

Update: * On IRC, I've been told that ~/.xsessionrc should be used since xorg 1:7.3+9

Posted Wed 14 May 2008 00:22:17 CEST Tags: sw
How to not start a service by default

How to not start a service by default

Use case: in my laptop, I sometimes need MySQL, PostgreSQL or Apache in order to test some software that I'm developing, but I do not want them on all the time.

The solution is: rm /etc/rc*.d/S*mysql* (thanks to Wouter)

update-rc.d will not touch your symlinks as long as there is at least one still around for a package. Also, this leaves the stop symlinks around, so that when I start one of these services for development, it will still be properly stopped on shutdown.

Posted Thu 24 Apr 2008 17:40:19 CEST Tags: sw
OpenStreetMap party at Kaohsiung, Taiwan

OpenStreetMap party at Kaohsiung, Taiwan

Apparently, yesterday we had the first OpenStreetMap event in Taiwan!

We met in a café/restaurant equipped with power plug, wireless network and overhead projector and we had a bit of an introduction, chat and lunch.

Then we split in groups and exploited the fact that the newly built underground (KMRT) system is still free of charge, to spread around and map around the stations.

Finally, we reconvened at someone's house to see how to put the data together, draw roads, tag and upload.

Highlights of the day:

Technical bits:

Issues to address:

Posted Sun 30 Mar 2008 07:10:59 CEST Tags: osm sw
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: sw
Fields used by an LDAP Unix user database

Fields used by an LDAP Unix user database

Some notes about LDAP for Unix user management:

Meaning of fields for objectClass posixAccount:

Meaning of fields for objectClass posixGroup:

For objectClass inetOrgPerson: what you put there can be used as if it were a vCard by mail programs and contact lists.

Now, the name of people could potentially be split in cn,givenName,sn,gecos and displayName (possibly more): how would normal user tools deal with the redundancy? To show a gecos field, pam_ldap will search for a gecos field first, then automatically fallback on building a gecos field out of the other suitable info it finds. To show a name, sane programs try displayName first and if it's not present they guess using the rest.

Then there is the issue of how to chose the dn to identify users, groups and so on. Users usually go in uid=$USERNAME,ou=People,$SUFFIX, while groups would usually go in cn=$GROUPNAME,ou=Groups,$SUFFIX.

Should you need to create the People and Groups organizational units, this could be the proper bit of LDIF:

dn: ou=$NAME,$SUFFIX
ou: $NAME
objectClass: organizationalUnit

To add fields that are not already part of a schema, one needs to create their own schema. To do that, one needs to first obtain (free of charge) a Private Enterprise Number that is used in various places in the schema definition. Making up your own one means risking conflicts if you eventually grow larger. But it is rarely needed, because for most things there are already schemas available.

Many thanks to Wouter and noshadow for allowing me to crudely extract all this content from their brains.

Posted Sun 09 Mar 2008 17:05:55 CET Tags: sw
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: sw
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: sw
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: sw
Happy new year

Happy new year

A year ago we got in touch with various Taiwanese aboriginal tribes to try to start localisation efforts.

Thanks to the research the Taroko people did during 2007 and the prototype work of tonight, the Taroko people in Taiwan can see the computer calendar of the new year in their own language:

trv_TZW Gnome calendar

Posted Mon 31 Dec 2007 16:58:30 CET Tags: sw