2013.04.21 14:35

Over the last month I’ve experienced a small explosion in email traffic about CAC on Linux, especially Ubuntu derivatives — most of it bad. It seems like some version of Firefox has a nasty bug where Firefox crashes hard as soon as you stick your CAC in the pooter, and then can’t get up again for as long as your thing is in there.

There are a few other issues, but this is the worst one affecting the largest number of users. There are three problems I’ve got resolving this:

The error reports I get in email are vague. Everything I know is written above. I don’t know what version, what derivative of Ubuntu (one guy said “Ubuntu” another said “Xubuntu”, another said “Kubuntu, I think”), what version of Firefox, what version of pcsc-tools, coolkey, etc. Nothing. Some of the reports may even be about CAC on SL6 for all I know, because nobody has told me anything.

I no longer have a CAC nor any involvement in CAC tool development. I’m out of the Army, nobody is going to pay me to deal with this (I’d love to, but I’ve gotta eat), and I’ve got no way to register for a CAC and all the different portal sites again to test it even if I had one.

I can’t update the instructionals for the current versions of the Fedora or Debian families because I can’t test anything without actually having a CAC and a place to use it (DTS, AKO, DKO, labs, etc.)… which sucks. I’m considering opening a wiki so the community can help itself maintain a current list of tutorials/versions. But I need help gardening it, and no volunteers have stepped forward.

The second problem is, actually, the smaller of the two. If I know a bit more about the distros, packages and versions installed I can get a pretty good lock on where the problem is and raise the attention of people who are getting paid to maintain CAC tools and squish Firefox bugs.

If you know anything about this please leave a note below with more detailed information so we can start getting some direction on a fix.

2013.04.20 20:12

Comparing and sorting version strings in Python scripts has come up a few times lately. Here are some simple approaches. These examples assume that the version strings will be numeric representations and not include elements like “rc-1” or “alpha” or whatever. If your problem includes these kinds of elements, don’t worry — they are solvable by applying a touch of regex-fu to the processes below.

First, sorting a bunch of version number strings. The problem is that many version strings reported by various packages are just that: strings. Usually the only way to get version information is to ask for it (“[prog] –version” in a shell script, or “SELECT version();” from a database, or whatever) and interpret whatever gets sent to stdout. Those strings don’t mean the same thing to comparison operators that they mean to us so long as they remain strings. For example, the string ‘3.5.10’ is greater alphabetically than ‘3.15.1’ but is a higher version. So we need to convert them to tuples of integers to make comparison of them natural (again, all these examples assume integer-only version strings, but minor changes to the process can allow you to compare anything — and assigning a custom collation order can allow you to sort against any arbitrary order of arbitrary symbols, but that’s beyond the scope of the basic nature of the problem I’m addressing here):

The list comprehension (actually, two nested list comprehensions) assignment to s_vers is the important part of this. Once that is done you can compare whatever you want. If the version number is buried as an element in a dict or larger list (likely) you can do this conversion in place by adding a new element to the contained structures and then sort the greater list based on that element:

We started out with a list of dictionaries, each containing a package name and a version string. The first loop updates each dictionary to include a version tuple, and the next orders the dictionaries within the list by the tuple values. Viola! We have a list of dictionaries sorted by version number. Of course, if there are more than one package name involved you will want to sort on the package name first, then the version tuple as a secondary criteria (so you don’t compare versions of package ‘foo’ against versions of package ‘bar’, or sort glibc against firefox, for example).

If lambdas are unfamiliar to you, don’t be scared off by the package.sort() line up there — lambdas are perfectly safe, reliable and quite concise once you understand the way they are used.

From here writing a sort function for lists of version strings should be pretty obvious. And… that means that writing a comparison function for two individual elements that works the same way the built-in cmp() function works is trivial:

Now I can’t figure out why comparison functions I’ve seen floating around occupy so much space and are hard to follow — full of class declarations and exec loops within exec loops (!!!) and other nonsense. At the most you will need to add some regular expression matching to extract/split on the correct substrings from the version string. That means you would have to import the re module and the list comprehension will grow by a few (maybe 10) characters.

From time to time I get asked how to use the date command to generate a timestamp. Here is an idiot-friendly script you can post for reference in your team’s bin/ if you get interrupted about timestamp questions or have an aversion to typing phrases like “man date” (with or without a space).

All but the first one and last three produce filename-friendly strings.

A big thanks to the following folks for pointing out mistakes and suggesting useful format inclusions:

2013-05: Rich for the reminder to include UTC and timezoned stamps.

2017-10: “Hamilton and Meg” (haha!) for pointing out I had my 4 year example formats messed up and for prodding me to include a 2-year example.

2018-01: Autumn Gray for suggesting that I add examples of including short and long days of the week.