Search Results: "rul"

3 May 2011

Kai Wasserb ch: Taking over the maintenance of Chronicle

Steve Kemp recently announced his resignation from Debian. That left a few of his packages without a maintainer, one of them was Chronicle. As a Debian Developer using Chronicle, I've adopted this package. The upstream development will still be mostly done by Steve. The packaging is done in a Git repository. The 4.6-1 upload consists of a new upstream version and some housekeeping stuff on the packaging side (like switching to a minimal debian/rules, fixing some Lintian warnings and complying with the latest version of the Debian Policy). I'd like to take this opportunity and thank Steve for all his work for Debian. Hopefully he'll be back to Debian in the future.

30 April 2011

Thomas Girard: ACE+TAO Debian packaging moved to git

We recently converted Debian ACE+TAO package repository from Subversion to git. This was a long and interesting process; I learned a lot on git in the course. I had been using git for a while for other packages: BOUML, dwarves and GNU Smalltalk. But I did not really get it. A preliminary study led by Pau[1] showed that out of the following three tools: the last one was giving results that look better.
The conversion svn-all-fast-export requires physical access to the repo, so the Alioth SVN repo was copied on my machine svn-pkg-ace/ before running the tool:
svn-all-fast-export --identity-map authors.txt --rules pkg-ace.rules svn-pkg-ace
Here's the content of the pkg-ace.rules configuration file that was used:
create repository pkg-ace
end repository
match /trunk/
  repository pkg-ace
  branch master
end match
match /(branches tags)/([^/]+)/
  repository pkg-ace
  branch \2
end match
The author mapping file authors.txt being:
markos = Konstantinos Margaritis <email-hidden>
mbrudka-guest = Marek Brudka <email-hidden>
pgquiles-guest = Pau Garcia i Quiles <email-hidden>
tgg = Thomas Girard <email-hidden>
tgg-guest = Thomas Girard <email-hidden>
The tool sample configuration file merged-branches-tags.rules recommends to post-process tags, which are just a branch in SVN. That's why the configuration file above treats branches as tags. The conversion was indeed fast: less than 1 minute.
Post-conversion observations Invoking gitk --all in the converted repo revealed different kind of issues:
  • svn tags as branches: http://thomas.g.girard.free.fr/ACE/tags-as-branches.png Branches are marked with green rectangles, and tags with yellow arrows. What we have here (expected given our configuration of the tool) are branches (e.g. 5.4.7-5) corresponding to tags, and tags matching the SVN tagging commit (e.g. backups/5.4.7-5@224). We'll review and fix this.

  • merged code that did not appear as such: http://thomas.g.girard.free.fr/ACE/missing-merge-metadata.png Branches that were not merged using svn merge look like they were not merged at all.

  • commits with wrong author: http://thomas.g.girard.free.fr/ACE/wrong-author.png Before being in SVN, the repository was stored in CVS. When it was imported into SVN, no special attention was given to the commit author. Hence I got credited for changes I did not write.

  • obsolete branches: http://thomas.g.girard.free.fr/ACE/obsolete-branches.png The tool leaves all branches, including removed ones (with tag on their end) so that you can decide what to do with them.

  • missing merges: http://thomas.g.girard.free.fr/ACE/missing-merge.png The branch 5.4.7-12 was never merged into the trunk!

Learning git Based on observations above, I realized my limited knowledge won't do to complete the conversion and clean the repository. There are tons of documentation on git out there, and you can find a lot of links from the git documentation page. Here's the one I've used:
The Git Object Model It's described with pictures here. You really need to understand this if you haven't already. Once you do, you understand that git is built bottom-up: the plumbing then the porcelain. If you can't find the tool you need, it's easy to write it.
git fast-import The Migrating to Git chapter explains how you can use the git fast-import tool to manually import anything into git. I've used it to create tags with dates in the past, slightly changing the Custom Importer example in the book:
#!/usr/bin/env ruby
#
# retag.rb
#
# Small script to create an annotated tag, specifying commiter as well as
# date, and tag comment.
#
# Based on Scott Chacon "Custom Importer" example.
#
# Arguments:
#  $1 -- tag name
#  $2 -- sha-1 revision to tag
#  $3 -- committer in the form First Last <email>
#  $4 -- date to use in the form YYYY/MM/DD_HH:MM:SS

def help
  puts "Usage: retag <tag> <sha1sum> <committer> <date> <comment>"
  puts "Creates a annotated tag with name <tag> for commit <sha1sum>, using "
  puts "given <committer>, <date> and <comment>"
  puts "The output should be piped to git fast-import"
end
def to_date(datetime)
  (date, time) = datetime.split('_')
  (year, month, day) = date.split('/')
  (hour, minute, second) = time.split(':')
  return Time.local(year, month, day, hour, minute, second).to_i
end
def generate_tag(tag, sha1hash, committer, date, message)
  puts "tag # tag "
  puts "from # sha1hash "
  puts "tagger # committer  # date  +0000"
  print "data # message.size \n# message "
end
if ARGV.length != 5
  help
  exit 1
else
  (tag, sha1sum, committer, date, message) = ARGV
  generate_tag(tag, sha1sum, committer, to_date(date), message)
end
graft points (graft means greffe in French) Because of missing svn:mergeinfo some changes appear unmerged. To fix this there are graft points: they override git idea of parents of a commit. To create a graft point, assuming 6a6d48814d0746fa4c9f6869bd8d5c3bc3af8242 is the commit you want to change, currently with a single parent 898ad49b61d4d8d5dc4072351037e2c8ade1ab68, but containing changes from commit 11cf74d4aa996ffed7c07157fe0780ec2224c73e:
me@mymachine$ echo 6a6d48814d0746fa4c9f6869bd8d5c3bc3af8242 11cf74d4aa996ffed7c07157fe0780ec2224c73e 898ad49b61d4d8d5dc4072351037e2c8ade1ab68 >> .git/info/grafts
git filter-branch git filter-branch allows you to completely rewrite history of a git branch, changing or dropping commits while traversing the branch. As an additional benefit, this tool use graft points and make them permanent. In other words: after running git filter-branch you can remove .git/info/grafts file. I've used it to rewrite author of a given set of commits, using a hack on top of Chris Johnsen script:
#!/bin/sh

br="HEAD"
TARG_NAME="Raphael Bossek"
TARG_EMAIL="hidden"
export TARG_NAME TARG_EMAIL
filt='
    if test "$GIT_COMMIT" = 546db1966133737930350a098057c4d563b1acdf -o \
            "$GIT_COMMIT" = 23419dde50662852cfbd2edde9468beb29a9ddcc; then
        if test -n "$TARG_EMAIL"; then
            GIT_AUTHOR_EMAIL="$TARG_EMAIL"
            export GIT_AUTHOR_EMAIL
        else
            unset GIT_AUTHOR_EMAIL
        fi
        if test -n "$TARG_NAME"; then
            GIT_AUTHOR_NAME="$TARG_NAME"
            export GIT_AUTHOR_NAME
        else
            unset GIT_AUTHOR_NAME
        fi
    fi
'
git filter-branch $force --tag-name-filter cat --env-filter "$filt" -- $br
(Script edited here; there were much more commits written by Raphael.)

Important

It's important to realize that the whole selected branch history is rewritten, so all objects id will change. You should not do this if you already published your repository.

The --tag-name-filter cat argument ensures our tags are copied during the traversal; otherwise they would be untouched, and hence not available in the new history.

Hint

Once git filter-branch completes you get a new history, as well as a new original ref to ease comparison. It is highly recommended to check the result of the rewrite before removing original. To shrink the repo after this, git clone the rewritten repo with file:// syntax -- git-filter-branch says it all.

Cleaning up the repo To recap, here's how the ACE+TAO git repo was changed after conversion:
  1. Add graft points where needed.

  2. Clean tags and branches. Using git tag -d, git branch -d and the Ruby script above it was possible to recreate tags. During this I was also able to add missing tags, and remove some SVN errors I did -- like committing in a branch created under tags/.

  3. Remove obsolete branches.

  4. Merge missing pieces. There were just two missing debian/changelog entries. I did this before git filter-branch because I did not find a way to use the tool correctly with multiple heads.

  5. Fix commit author where needed. Using the shell script above Raphael is now correctly credited for his work.

That's it. The ACE+TAO git repository for Debian packages is alive at http://git.debian.org/?p=pkg-ace/pkg-ace.git;a=summary.
[1]http://lists.alioth.debian.org/pipermail/pkg-ace-devel/2011-March/002421.html
[2]available in Debian as svn-all-fast-export

28 April 2011

Russell Coker: What is Valid SE Linux Policy?

Guido Trentalancia started an interesting discussion on the SE Linux policy development list about how to manage the evolution of the policy [1]. The Problem The SE Linux policy is the set of rules that determine what access is granted. It assigns types to files and domains to processes and has a set of rules that specify all the permitted interactions between processes and files (among many other things). The policy evolves over time to match the requirements of programs (applications and daemons). As a program evolves the things that it does will change and the SE Linux policy will tend to evolve to permit the set of all operations that were requested by all versions because people only complain when things stop working not when excessive privilege is granted. So we need to periodically remove old allow rules from the policy. One difficulty in this regard is the fact that multiple versions of programs are often available for use at the same time. Debian in particular has a good history of providing separate packages for the old and new versions of programs such as Apache to meet the needs of users who want the tried and tested version and of users who want the newer version with better performance, more features, better documentation, or something else good. There is also a demand to have the same policy work with multiple versions of a distribution without excessive effort. Finally all the distributions that have SE Linux support have different people deciding when the new version of a daemon is ready for inclusion and therefore there is a need to support multiple versions for multiple distributions. So support for older versions of daemons can t be removed easily. One of the things I do to make these things a little easier to manage is to put ifdef( distro_debian', before any Debian specific bits of policy. When policy is conditional and only used in Debian I can freely remove it at any future time if Debian works well without it. Also it doesn t matter if such Debian specific policy allows access that is not needed or desired in other distributions, the only down-side to this is that sometimes other distributions need to repeat work that I did, they determine what access is needed for their configuration and discover that it was already enabled for Debian. What is Valid Policy? We went to only have Valid Policy (as described by Christopher J. PeBenito), so the challenge is determining what is Valid Policy. It seems to me that there are three type of access granted by valid policy (it is debatable whether type #3 is valid):
  1. Access that is needed for an application to perform it s minimal designed task.
  2. Access that is needed for the application to perform all the optional configurations, EG an ftpd running from inetd or as a daemon, and daemons like http server being granted access to ssl keys or not.
  3. Access that is needed to perform all the operations the application requests, but which the application doesn t require or shouldn t require if it worked correctly.
Some common operations that aren t required include opening utmp for write, searching /root, and many other relatively innocuous access attempts which don t affect the program operation if they are denied. There are also many things such as writing temporary files to /root that don t seem unusual if the application developer is not considering SE Linux (but which are often considered bad practice anyway). Some of these things (like using /root for stuff that belongs in /var/lib) have the potential to break things (for the daemon or for other system processes) even if you don t consider SE Linux. How to deal with those types:
  1. In most cases this can be determined without too much effort. For example a web server needs to listen on port 80 and read files and directories that relate to data. When writing policy I can write a lot of the allow rules without even testing the application because I know from the design what it will do. A large part of the other access is obvious in a I can t believe I didn t realise it would need this sense.
  2. The main question here is whether we have booleans (settings which can be tuned at run-time by the sysadmin which determine how the policy works) to specify which optional tasks or whether we allow all access for optional configurations by default. The secondary question is when certain unusual corner cases should be not supported at all such that the people who do such unusual corner cases need to use audit2allow to generate local policy to allow their operations.
  3. Sometimes we have to allow things that we really don t like. Even when we write policy to allow a daemon to do unusual things (such as using /root instead of /var/lib) it s still a lot better than running without SE Linux. Also SE Linux policy to allow such obviously broken things stands out and is a constant reminder that the daemon needs fixing, this is better than allowing symptoms of broken design to be forgotten.
How to Improve the Situation We could have comments in the policy source for everything that is in category 3. If the comments had a fixed format so that a recursive grep could find them all then it would allow us to more easily remove the gross things from the policy at a later date. But it seems to me that the main problem is a lack of people working on this. I am not aware of any people actively testing Debian policy for excessive privilege in regard to such issues.

Russell Coker: Australia Needs it s own Monarch

Tomorrow Prince William will marry Kate Middleton. If we don t change anything he will probably become the King of Australia at some future time, so I think that now is the time to start discussing the options. Walter Block makes some interesting points in favor of longer terms for politicians and for having a monarch to get a long-term view of the national interest [1], he s not the only person to make such points, but he makes them in a better way than most. Of course the problem with this is the long history of kings not doing what s best for their country part of the ownership rights to property is the right to destroy it, so a monarch who owns a country therefore can be considered to have the right to cause the wholesale death of their subjects. There are some examples of President for Life political leaders demonstrating this at the moment. Even with a monarch who is generally a nice person and who has controls to prevent the worst abuses there is the possibility of Control Fraud. In the Constitutional Monarchy system that doesn t happen because a constitutional monarch has little power (no official position of power). But there is still the issue of whether the monarchy is any good. Charles Stross wrote an interesting post about the apparent human need to have a leadership figure [2]. So getting rid of a monarch tends to result in a president getting the trappings of a king, and if things go wrong (as they often do) then they get absolute power until the next revolution. It seems that having one person who is the head of government and the head of state (as done in the US for example) is a bad idea, they can start to think that it s all about them. I don t think that the US is at risk of getting a president for life in the near future and I don t think that Australia will do so if we become a republic, but that doesn t mean that the republican system works well. I think that the Australian system is working better than the US system and I will generally vote against any changes that make Australia more like the US. As long as the House of Windsor provides monarchs who are as sensible as Queen Elizabeth 2 I will vote in favor of the continued rule of the House of Windsor in preference to an Australian republic (if Prince Charles ever becomes king I may support a republic). A Way of Improving Things I want to have an Australian monarch. Someone who will live in Australia for most of the time (as opposed to a distant monarch who visits once a decade if we are lucky). Protocol should dictate that the Prime Minister and cabinet ministers are forced to show ritual respect to the monarch, bowing etc, and no touching. A separation between the person who performs most of the ceremonial functions and the person who actually makes the political decisions should help constrain political egos. When a Prime Minister feels the need to suck up to someone more powerful it would be better to have that person be an Australian monarch than the US president. Tradition has it that monarchs have to be descended from other monarchs (although there are cases of elected monarchs as happened in Danish history). An election for a monarch probably wouldn t work well in a modern political environment, so we need someone with royal ancestry. One possibility is to have a spare descendant of our current Queen become the monarch of Australia, I think it s quite likely that given a choice between remaining a UK prince or princess for the rest of their life and becoming the monarch of Australia there would be someone who would take the latter option and I expect that the Queen would consent to that arrangement if asked (she would have to prefer it to a Republic). Another possibility is the fact that Mary the Crown Princess of Denmark has more children than the Danish monarchy requires [3]. As she was born in Australia it seems likely that her children will have more interest in Australia than most royals and a skim read of some tabloid magazines indicates that her family is quite popular. I expect that if a Danish prince or princess was invited to become the monarch of Australia then this would be acceptable to the Queen of Denmark. In an ideal world there would not be such a thing as a monarchy. But as we don t get to have ideal voters and therefore our politicians are far from ideal it seems to me that the constitutional monarchy is the least bad system of government. Don t think that I am in favor of a monarchy, I just dislike it less than the other options. Finally the Queen is the Supreme Governor of the Church of England. I think that it would be good to have a separation between church and state and therefore anyone who is in a leadership position of any religious organisation should be considered unsuitable to be the monarch.

27 April 2011

Daniel Kahn Gillmor: The bleeding edge: systemd

Curious about these shiny new things i keep hearing about, i set up a test desktop system using using systemd as the init system (yes, that means using systemd-sysv in place of sysvinit -- so i had to remove an essential package for this to work). A system-crippling bug was naturally the result of living on the bleeding edge, but fortunately it was resolved with a trivial patch. In all, i'm pretty happy with some of the things that systemd seems to get right. For example, native supervision of daemon processes, clean process states, elimination of initscript copy-paste-isms, and socket-based service initiation are all obvious, marked improvements over the existing sysvinit legacy cruft. But i'm a bit concerned about other parts. For example, all the above-mentioned features fit really well within a tightly-tuned, well-managed server. But systemd also appears to rely heavily on complex userland systems like dbus and policykit that would be much more at home on a typical desktop machine. I've never seen a well-managed server installation that warranted either policykit or dbus. Also, given the bug i ran into -- when PID 1 aborts due to a silly assertion, your system is well-and-truly horked. Shouldn't a lot more attention to detail be happening? I'd think that a "recover gracefully from failed assertions" approach would be the first thing to target for a would-be PID 1. I'm also concerned about the Linux-centricism of systemd. I understand that features like cgroups and reliance on the spiffiness of inotify are part of the appeal, but i also really don't want to see us stuck with only One Single Kernel as an option. The kFreeBSD folks (and the HURD folks) have done a lot of work to get us close to having some level of choice at this critical layer of infrastructure. It'd be good to see that possibility realized, to help us avoid the creeping monoculture. I worry that systemd's over-reliance on Linux-specific features is heading in the wrong direction. So my question is: why is this all being presented as a package deal? I'd be pretty happy if i could get just the "server-side" features without incurring the dbus/policykit/etc bloat. I already run servers with runit as pid 1 -- they're lean and quite nice, but runit doesn't have systemd's socket-based initiation (or the level of heavyweight backing that systemd seems to have picked up, for that matter). I understand that Lennart is resistant to UNIX's traditional "do one thing; do it well" philosophy. I can understand some of his reasoning, but i think he might be doing his work and his tools a disservice by taking it this far. Wouldn't systemd be better if it was clearer how to take advantage of parts of it without having to subscribe to the entire thing? Of course, i might be missing some nice ways that systemd can be effectively tuned and pared down. But i've read his blog posts about systemd and i haven't seen how to get some of the nice features without the parts i don't want. I'd love to be pointed to some explanations that show me how i'm wrong :)Tags: systemd

26 April 2011

Evgeni Golov: dear qmake

i can haz understanding?I m trying to rebuild a package with gcc-4.6 instead of (default) gcc-4.5. Sounds easy, huh?Not today, not with qmake :(Setting CC=gcc-4.6 CXX=g++-4.6 on the command-line does not help. Neither does exporting these in debian/rules. Let s fire up Google, I think I remember qmake tends to prepend EVERYTHING with QMAKE_ Right, official documentation says it s QMAKE_CC and QMAKE_CXX. Setting those on the command-line does not help. debian/rules? Nope!Okay, let s do it the qmake-way, set it in the main .pro file which basically just calls a bunch of other .pro files (one for each component of the project). Guess what? It does not help. You have to set these in each and every .pro file! Rly? Is this what I have a build-system for?</rant>Now, seriously, what s the proper way to override stuff like this in qmake? Any pointers appreciated.

21 April 2011

Rapha&#235;l Hertzog: People behind Debian: Meike Reichle, member of Debian Women

Meike Reichle is a Debian developer since 2008 but has been involved for longer than that, in particular in Debian Women. She s a great speaker and shared her experience in a Debconf talk. She s also part of the Debian publicity team and managed the live coverage of the last release on identi.ca. Enough introduction, learn more about her by reading the interview. My questions are in bold, the rest is by Meike. Who are you? My name is Meike Reichle, I am a studied information scientist and work as a project manager at Pengutronix, an embedded Linux company probably best known for their ARM kernel work. I live in Germany, more exactly in Lower Saxony, but I was originally born and raised in Swabia. Although I moved here ten years ago I still have a rather strong Swabian cultural identity. (Among other things I pride myself on having introduced a number of fellow DDs to the true promise that are real hand-made Sp tzle ;-) ) I am married to Alexander Reichle-Schmehl, we ll have our third wedding anniversary this summer. Apart from Debian most of my spare time is used for all kinds of crafts and DIY activities. Making things with my hands always gives me a great sense of accomplishment. My Free software history is summed up pretty quickly. Like most women of my age I wasn t introduced to computers until well into my teens. I didn t have a computer of my own until I started studying at the university in 2001. From there on things developed rather quickly: Working on the University s Unix terminals got me hooked on *nixes, so I got me one of those Linuxes everyone talked about. I tried a couple of different distributions, ended up with Debian around 2004, started contributing in 2005, and finally became a full DD what a nice coincidence! exactly this day (Apr 18th) three years ago. You re part of Debian Women. How is the project going? I have the feeling that the number of women involved in Debian has not significantly increased. The amount of women active within Debian is a tricky thing to judge. Here s a quick example why: When the DPL was elected in 2004 there were 911 Debian Developers eligible to vote, 4 of them were female. Shortly after, during DebConf4, debian-women was founded. When the current DPL was reelected last month, there were again 911 Debian Developers eligible to vote, but this time 13 of them were women. You can look at these numbers and say The number of female DDs has more than tripled, what a success! Or you can pull out your calculator and it will tell you that in terms of ratio this puts us from a measly 0.4% to an only slightly less measly 1.4% ratio of female DDs. This still is pardon my language a bloody shame, but sadly also pretty close to the average ratio of women in Free Software. So, while I do think that the debian-women project did already have a significant impact on the Debian project as a whole, I don t think it has achieved its goals yet. Not for a long time. There s still a lot to be done but unfortunately the debian-women project has somewhat run out of steam at the moment. The seven years of its existence divide quite equally into the first half, which was very active and saw great results, and the second half, which was very slow and much more passive. In my impression debian-women is currently undergoing a rather bumpy generational change. On the one hand a lot of the original members, including myself, have reduced their involvement. Speaking for myself this is caused by shift of interests as much as general weariness. On the other hand there are only very few women following up. This development is also reflected quite harshly in DD numbers: If I don t misjudge any first names (and I desperately hope I do!) for the last three years not a single woman has joined Debian as a developer! After the great start debian-women has had, this is a very painful thing to see! That said, things don t look all bad. There is a number of women maintaining packages without being DDs and there s also at least one woman currently in NM, so there s hope this standstill won t last very much longer. But still, the fact remains that debian-women is suffering from a rather serious recruitment problem and I hope that this interview might actually help to spur some new or not yet active members into action. The aim of debian-women is far from achieved and now that its initial members are receding its time for new members to step up and take initiative. What should Debian do to be more attractive to women ? I think the general atmosphere has improved, we re less tolerant with rude behaviour, the usual tone on mailing lists has improved. Yet it doesn t seem to be enough. If there was a female DD for every time I answered that question First of all, I agree, Debian as a community has improved tremendously! Our general tone is much more friendly and cooperative and there is now a much better awareness of the impression we give to outsiders and newcomers. Now on to the difficult part: The question what should be done to get more women into Free Software has been around almost as long as Free Software exists, and it has been answered very well by a lot of people: Twenty years ago Ellen Spertus wrote Why are There so Few Female Computer Scientists? and most of it still holds true. Almost ten years ago Val Henson (now Aurora) wrote HOWTO Encourage Women in Linux and that also is still pretty accurate. In 2006 Floss Pols undertook extensive research to find out why there were so few women in Open Source and Free Software and how that could be changed. They also came up with a very good set of recommendations. All of these texts highlight different aspects of that question and all of them have very good points. I personally have, over the years, arrived at a rather sociological, not to say holistic point of view. In fact I answered the exact same question a few days ago, and the answer I gave then was this: After ~10 years of women in tech advocacy I d say the ultimate and final measure to get more women into Free Software is by finally achieving a truly equal society and at the same time dramatically improving child care support in almost any country. I ve come to the conclusion that what really holds women back in practice is not so much a lack of skill or interest but a simple lack of opportunity. For most of us Free Software is what we do in our spare time and that s something that women, even today, have considerably less of than men. Even in couples where both partners work full-time it is still mostly the woman who does the majority of the housework and child care duties. In most cultures men have a perceived right to their leisure time that does not to the same degree exist for women. That is one major reason, the other is instilled modesty, which has kind of become my personal arch-enemy by now. I ve talked to so many girls and women at all sorts of events about why they won t take up Computer Science studies or join a Free Software project and the answer I hear most often is that they do not consider themselves good enough in one or another aspect. Sometimes they will doubt their technical skills, sometimes their language skills, sometimes their stamina. Needless to say these girls and women were not any less qualified than the people already active in Free Software. So, yes, in the short and medium term making Debian a more welcoming and friendly place is the way to go. As many others pointed out already this will not only benefit prospective contributors but the community as a whole: those new to it as well as those who ve been in it for a long time. In the long term however what we need is empowerment! Women who are just as confident about their skills as men and are not discouraged by uncooperative environments. This is of course something that is culturally deep-rooted and can only happen in a very large time frame. So, for the moment the way to go in my view is accessibility: a cooperative atmosphere, a code of conduct, comprehensive documentation not only of technical aspects but also of structures and processes. The other thing we need to do is to have as many already active women as possible attend as many Linux/Debian/Free Software/Whatever events as possible. In my experience it happens quite often that other women see these women, feel very inspired by them, get to talk to them and then a few days later show up on some mailing list or IRC channel. From what I ve seen personal contact still beats any other kind of recruiting measures. You re a Debian developer but you re also married with a Debian developer (Alexander Reichle-Schmehl). Did you meet because of Debian? If not, who introduced Debian to the other one? :-) We did in fact meet because of Debian. More specifically during our booth shift at the Debian booth at LinuxTag 2005, where I did a talk on the debian-women project and Alex organised the DebianDay. After that our relationship developed pretty much along our Debian activities: After our initial meeting we talked a lot on #debian.de, when Alex went to DebConf5 and I didn t we noticed that we kind of missed each other. The first gift he ever gave me was a Debconf5 shirt and a box Finnish chocolates (I still have one of them today. :) ) Our first secret kiss was at ApacheCon 2005, where we were both staffing the Debian booth (kudos to abe for pretending not to notice). We then became an official couple at Berlinux 2005 where we were both staffing the Debian booth and giving talks on packaging and user motivation. Our first real relationship stress test was when we both joined the DebConf6 orga team. It was a stressful time, but we passed it with flying colours! About a year later we announced our engagement via planet.debian.org. Our wedding was a veritable MiniDebConf, one of the best gifts we got was a Debian cookbook including the favourite recipes of DDs from around the world. By now we ve both finished university and work full-time jobs, so we don t do as many talks and attend as many Debian events as we used to. Instead we now mainly focus on press and publicity work, which is quite practical to work on as a pair. It s actually rather funny that way, Alex and I get confused with each other quite often, since we have almost the same name, often pick up on each other s E-Mail conversations and are most often quoted by our function rather than by name. Because of we have kind of merged into this virtual Debian Press Person in the perception of many of our contacts. You also have another hat : Debian Press Officer. What is this about? What would you suggest to people who would like get involved in that domain? Debian press work is mainly about providing an official and coordinated point of contact to anyone wanting information from or about Debian. The press team answers all sorts of inquiries (the most popular one is is of course always the next release date) and makes sure all important events and developments within Debian receive the attention and recognition they deserve. Debian is a diverse project where every sort of contributor is free to voice his or her opinion in any way. We don t have NDAs or prescribed terminology. That s one of the things I love about Debian but also something that makes us difficult to handle for conventional media. They want official statements, in generally understandable terms, at appointed times. That s what the press team takes care of. Almost all of the press work is done in the publicity team, which coordinates using IRC, Mail and SVN. The publicity team also publishes the Debian Project News, which are very popular among our users and developers. Press work is also an area of work that offers lots of possibilities for non-technical contribution. http://wiki.debian.org/Teams/Publicity lists a number of possibilities for contribution and, like most Debian Teams, we d be more than grateful to get some more helping hands and happy to introduce interested newcomers to our work. What s the biggest problem of Debian? In my view: Overwork. Debian has thousands of contributors but still a lot of the main work rests on very few shoulders. We need more contributors, especially, but not only in the key teams. In order to get more people we need to do some marketing which is very hard for us, since we are very proud of our independence and have a strong focus on purely technical aspects rather than aiming for popularity. However, with the current amount of Open Source and Free Software projects to join we find ourselves not only in a contest on technical excellence but also a sort of popularity contest that is about perception rather than hard facts. This popularity contest is difficult for Debian and currently costs us quite a bunch of very capable people. Do you have wishes for Debian Wheezy? My answer to that is a non-technical one: I think Debian is currently very under-appreciated, we do a lot of great work and maybe even more importantly we do a lot of important work for Software Freedom, sometimes even at the cost of our above-mentioned popularity. I hope people will appreciate that more again in the future. Is there someone in Debian that you admire for their contributions? Over the years I have made a lot of friends within the Debian community, some have even become family. That makes it somewhat hard to single out individual people. I think what I admire most is continuous commitment. I am very impressed by those among us who have kept up a high level of commitment over many years and at the same time managed to bring that in line with a fulfilled personal/family life. That s something that I hope I ll also be able to achieve in the years to come.
Thank you to Meike for the time spent answering my questions. I hope you enjoyed reading her answers as I did. Subscribe to my newsletter to get my monthly summary of the Debian/Ubuntu news and to not miss further interviews. You can also follow along on Identi.ca, Twitter and Facebook.

2 comments Liked this article? Click here. My blog is Flattr-enabled.

20 April 2011

Jeff Licquia: Triumphant Return

When you don t update a blog, it gets stale fast. Tim Bray Of course, I didn t intend to violate this basic rule of blogging. It just happened one thing leads to another, and pretty soon you notice just how little your front page has changed in the past two-and-a-half years. So, I shall begin again. Quite a bit has changed: All of these will get their own posts in the very near future. In the meantime, enjoy the new look. (Especially on mobile!)

11 April 2011

Cyril Brulebois: Debian XSF News #10

This is the tenth Debian XSF News issue. It is basically meant to be a follow-up to DXN#9.
  1. I completed the addition of the Sinhala language, and also dealt with big changes on the xkb-data (a.k.a. xkeyboard-config) side, as explained by Sergey Udaltsov. Protocol:
    • [KiBi] x11proto-core: the upload to experimental was a bit overcautious, so upload again unstable.
    Data: Library:
    • [KiBi] libx11: new upstream release, adding support for Sinhala unstable.
  2. The Graphical Installer started receiving improved portability. There were a few patches floating around adding udebs for generic drivers for non-Linux architectures. I cleaned them up a bit (especially on the vesa side, getting rid of libdrm entirely), got them test-built on a kfreebsd-amd64 box, while Samuel Thibault was doing the same on a hurd-i386 box. I raised the topic on debian-boot@, debian-bsd@, and debian-hurd@, mentioning the remaining steps. Drivers (all accepted by ftpmasters after a tiny trip to the NEW queue):
  3. Here are some other packages which got updated. Applications: Library:
    • [Chris,Julien,KiBi] mesa 7.10.1: long-awaited upload, finally checked, built, and uploaded experimental.
  4. Finally, let s mention migration to testing (from now on I ll use testing instead of wheezy so that it s clear it s about week after week migrations to the testing distribution, rather than our final plans for the next stable release). After a while, and thanks to some hand-holding from our nice release managers (hi, Adam!), linux-2.6, libdrm, mesa, xorg-server, and several dozen drivers migrated to testing. Yay!
  5. As a consequence, some other packages got updated shortly after the successful britney run (because they were prepared right before, just in case). Libraries:
    • [KiBi] libdrm: replace 2.4.23 with 2.4.24 (which was in experimental previously) unstable.
    • [KiBi] mesa: new stable release, 7.10.2 supersedes both 7.10 in unstable and 7.10.1 in experimental (see above) unstable.
    • [KiBi] pixman: new development snapshot, 0.21.6 comes from experimental and supersedes 0.21.4 unstable.
    Drivers:

10 April 2011

Cyril Brulebois: Getting replaced by scripts

As already blogged by Riku, getting replaced by script is really great! Until now, I ve had a crontab fetching my supporting-very-big-mails (up to 100MB or so) mailbox every few minutes, and looking into my =incoming-buildd/ maildir on a very regular fashion. With some simple mutt maildir hooks, replying to a Successful log would trigger extracting the changes file from there, setting some options, like PGP inline signing, and the mail would be ready to go back to the buildd. That part was just about being a GPG-signing monkey, so really not a funny part. Since we no longer have to worry about this boring and time-consuming task, I ve switched to a crontab firing up 4 times a day, and I try to deal with all incoming mails at once. Coupled with the new filters (e.g. on out-of-date packages on the buildd status page), I started using my time to file FTBFS bugs again, so that maintainers notice their packages fail to build without having to wait for a non-happening testing migration. After 10 days, the following mutt filter in =debian-bts/ lists 69 bugs:
~s "Bug#.*FTBFS" ~P ~d 01/04/2011-
(Subject contains Bug#.*FTBFS, mails from me, starting from 01/04/2011.) Figuring out whether that s due to another package s bug, an outdated chroot, a temporary glitch, etc. might take some time; that s why it s a bit hard to stay on top of things; and when the backlog grows up, motivation to go through this tedious task can be pretty low, especially when one sees repeated mistakes. I hope the amount of (possible) use cases for #620686 will decrease over time; instead, I d be very happy if maintainers could at least check what s mentioned in configure.ac/configure.in. Keeping an eye on its diff between upstream versions should be easy enough. ;)

9 April 2011

Cyril Brulebois: Debian XSF News #9

This is the ninth Debian XSF News issue. As can be seen below, I m not yet decided how to present various items. This time, I ll try to gather all updated packages since the previous issue, grouped by category, with a single line summary. Lengthy comments come after that list of updated packages.
  1. Here come the updated packages, with contributors/uploaders between square brackets (Timo = Timo Aaltonen, JVdG = Julien Viard de Galbert, Robert = Robert Hooker). Protocol:
    • [KiBi] x11proto-core: new upstream release, bringing Sinhala support experimental.
    Libraries:
    • [Timo,KiBi] libx11: new upstream release, fixing some hang issues unstable.
    • [KiBi] libxi: new upstream release unstable.
    • [KiBi] libxkbcommon: finally accepted by ftpmasters, needed for wayland experimental.
    Server:
    • [KiBi] xorg-server: stable release 1.9.5, unlikely to cause regressions from the previous release candidate; in other words: a good candidate for testing if the Linux kernel migrates some day unstable.
    • [KiBi] xorg-server: first release candidate for the first stable bugfix release in the 1.10 series, which finally builds experimental.
    Drivers: Others:
    • [KiBi] xorg: originally a few tweaks to make it possible to install X on Hurd unstable
    • [KiBi] xorg: but wkhtmltopdf failed on several buildds, so I disabled PDF generation, and completed the switch to asciidoc mentioned in DXN#8 unstable.
    • [KiBi] xorg-sgml-doctools: new upstream release, adds support for docbook external references unstable.
    • [Robert,KiBi] xutils-dev: new util-macros release, and a version lookup file unstable.
  2. Why am I carefully uploading video driver packages to experimental only? Because bad regressions happen, on a regular basis; so it seems quite nice to keep well-tested versions in unstable for now. Once the X stack has migrated to testing (which as explained in DXN#7 and DXN#8 is waiting for the Linux kernel to migrate), new versions in unstable are welcome, so that one can tell easily whether bugs with those versions are regressions from the versions available in testing. In the meanwhile, one can build packages from the git repositories, using the debian-unstable branch (which is the default).
  3. Why am I so rash then, uploading input drivers to unstable as they are released? First of all, our waiting for the kernel means we have no issues on the 10-day delay front. Second of all, input bugs are usually fixed very quickly upstream (you can go there and thank Peter Hutterer in particular). So staying very close to whatever upstream ships makes some sense.
  4. Why am I uploading drivers twice? Since it isn t specific to the current situation, but a general question when it comes to supporting two versions of the server in parallel, I decided to document that in an handling multiple server versions thanks to experimental page. The answer to this specific question is available in the note at the bottom of that page.
See you in a few days for a follow-up Debian XSF News issue.

6 April 2011

Sven Mueller: Strange iptables error with kernels >= 2.6.32 solved

Alright. If you ever come into the same situation I was in and need a newer kernel (2.6.32 or up, perhaps also 2.6.31) on some system with old iptables package (versions below 1.4.0 I think, 1.3.5 in my case: CentOS5/RHEL5), you might get this helpful error message when using the iprange module in your iptables rules: iptables: Unknown error 18446744073709551615 Or even more helpful, if you use iptables-restore to load your rules, you will get an error in the line containing the COMMIT statement (iptables-restore: line X failed). The reason for this is that the netfilter guys have removed an interface to the iprange module in kernel version 2.6.31 or 2.6.32 (see my bug report at #711 of the netfilter bugzilla). Just posting this so it might hopefully help others if they get into the same situation.

5 April 2011

Cyril Brulebois: Running X from LXC

Mandatory warning: What follows is for testing only, and insecure (root all over the place, giving access to host devices from the container, etc.). Problem of the day Giving Linux containers a try Getting devices Example, with a Radeon card, KMS enabled, let s assume those devices are wanted:
crw-rw---- 1 root video 226, 0 Apr  5 02:34 /dev/dri/card0
crw-rw---- 1 root video  29, 0 Apr  5 02:34 /dev/fb0
crw------- 1 root root    4, 7 Apr  5 02:34 /dev/tty7
crw------- 1 root root    4, 8 Apr  5 02:34 /dev/tty8
Note the major, minor right between owner groups and dates, and edit the config file accordingly, adding those lines (watch the syntax, it doesn t like extra whitespaces):
lxc.cgroup.devices.allow = c 226:0 rwm
lxc.cgroup.devices.allow = c 29:0 rwm
lxc.cgroup.devices.allow = c 4:7 rwm
lxc.cgroup.devices.allow = c 4:8 rwm
Once the container restarted, create the devices:
cd /dev
mkdir -p dri
mknod -m 666 dri/card0 c 226 0
mknod -m 666 fb0       c 29 0
mknod -m 666 tty7      c 4 7
mknod -m 666 tty8      c 4 8
Getting serious Enjoy:
export DISPLAY=:0
awesome &
# this is not a benchmark:
glxgears &
# direct rendering:
glxinfo egrep '(direct renderer)'
which printed here:
direct rendering: Yes
OpenGL renderer string: Gallium 0.4 on ATI RS690

3 April 2011

Steve Kemp: A couple of small tweaks

Today I made a couple of small tweaks to my systems. First of all I updated my email handling to allow further restrictions to be applied to incoming mail. Generally the way I handle incoming mail is to first of all test the recipient, then apply spam checks. To allow mail for a new localpart to be received I'll run this:
cd /srv/example.com/users/valid
touch localpart
The result of the file /srv/example.com/users/valid/localpart existing is that mail is accepted for localpart@example.com. As of today that still works - any file beneath users/valid allows the appropriate localpart to receive email. But now a directory indicates an ACL. So I can create:
rm    /srv/example.com/users/valid/root
mkdir /srv/example.com/users/valid/root/
touch /srv/example.com/users/valid/root/1.2.3.4
touch /srv/example.com/users/valid/root/2.3.4.5
Now only the named IP addresses may mail root@example.com. Finally I updated the proxy which is handling incoming access to my websites, so that I actually take advantage of the regular expression support.
    '(xen-hosting.net www.xen-hosting.net)':  
        'rules':  
            '^/': 'http://kvm-hosting.org/'
         ,
     ,
    '(xen-hosting.org www.xen-hosting.org)':  
        'rules':  
            '^/': 'http://kvm-hosting.org/'
         ,
     ,
Using regular expressions meant that I didn't have seperate matches for xen-hosting.org and www.xen-hosting.org. (Obviously I could have combined all four hosts into one regexp, but it looks cleaner this way.) ObQuote: "Nobody likes a perky goth" - Blood Ties.

Cyril Brulebois: Debian XSF News #8

This is the eighth Debian XSF News issue. For a change, I m going to use a numbered list, which should help telling people which item to look for when pointing to a given URL. Feel free to let me know if that seems like a nice idea or whether that hurts readability. Also, it was prepared several days ago already, so I m publishing it (with the needed bits of polishing it still needed) without mentioning what happened in the last few days (see you in the next DXN issue!).
  1. Let s start with a few common bugs reported over the past few weeks:
    • The server can crash due to some X Font Server (XFS) issue as reported upstream in FDO#31501 or in Debian as #616578. The easy fix is to get rid of FontPath in xorg.conf, or to remove the xfs package. It s deprecated anyway.
    • Xdm used to crash when started from init, but not afterwards (#617208). Not exactly fun to reproduce, but with the help of a VM, bisecting libxt to find the guilty commit was quite easy. After a quick upload with this commit reverted, a real fix was pushed upstream; a new upstream was released, packaged, and uploaded right after that.
    • We ve had several reports of flickering screens, which are actually due to upowerd s polling every 30 seconds: #613745.
    • Many bug reports were filed due to a regression on the kernel side for the 6.0.1 squeeze point release, leading to cursor issues with Intel graphics: #618665.
  2. Receiving several similar reports reminded me of the CurrentProblemsInUnstable page on the wiki, which is long unmaintained (and that s why I m not linking to it). I m not exactly sure what to do at this point, but I think having a similar page on http://pkg-xorg.alioth.debian.org/, linked from the how to report bugs page would make sense. Common issues as well as their solutions or workarounds for stable should probably go to the FAQ instead.
  3. As explained in DXN#7, we re waiting for the kernel to migrate to wheezy. The 2.6.38 upstream release was quickly pushed to unstable, which is great news, even if it s not really ready yet (since it s still failing to build on armel and mips).
  4. I ve been using markdown for our documentation, basically since it looked sufficient for our needs, and since I ve been using it to blog for years now, but it had some limitations. I ve been hearing a lot of nice things about asciidoc for a while (hi, Corsac!), so I gave it a quick shot. Being quite happy with it, I converted our documentation to asciidoc, which at the bare minimum buys us a nice CSS (at least nicer than the one I wrote ), and with automatic table of contents if we ask for it, which should help navigating to the appropriate place. A few drawbacks:
    • The syntax (or the parser s behaviour) changed a lot since lenny s version, so updating the online documentation broke badly. Thanks to the nice Alioth admins, the version from lenny-backports was quickly installed and the website should look fine.
    • The automatic table of contents is generated through JavaScript, which doesn t play nicely with wkhtmltopdf (WebKit-based HTML to PDF converter), since the table of contents gets pixelated in the generated PDF documents. We could use a2x to generate documents through the DocBook way, but that means dealing with XSL stylesheets as far as I can tell; that looks time-consuming and a rather low-priority task. But of course, contributions are welcome.
  5. When I fixed missing XSecurity (#599657) for squeeze, I didn t notice the 1.9 packages were forked right before that, so were affected too. I fixed it in sid since then (and in git for experimental). I noticed that when Ian reported a crash with large timeouts in xauth calls, which I couldn t reproduce since untrusted cookies without XSecurity don t trigger this issue. I reported that upstream as FDO#35066, which got marked as a duplicate of (currently restricted) FDO#27134. My patch is currently still waiting for a review.
  6. Let s mention upcoming updates, prepared in git, but not uploaded yet:
    • mesa 7.10.1, prepared by Chris (RAOF); will probably be uploaded to experimental, unless 7.10 migrates to testing first, in which case that update will target unstable.
    • Intel driver: Lintian s been complaining about the .so symlinks for a while, and I finally gave it a quick look. It seems one is supposed to put e.g. libI810XvMC.so.1 in /etc/X11/XvMCConfig to use that library, so the symlinks are indeed not needed at all, and I removed them.
    • Tias Guns and Timo Aaltonen introduced xinput-calibrator in a git repository; that s a generic touchscreen calibration tool.
  7. Here come the updated packages, with uploader between square brackets (JVdG = Julien Viard de Galbert, Sean = Sean Finney). For the next issue, I ll try to link to the relevant entries in the Package Tracking System.
    • [KiBi] libxt: to unstable, as mentioned above, with a hot fix, then with a real fix.
    • [KiBi] synaptics input driver: to unstable and experimental, fixing the FTBFS on GNU/kFreeBSD.
    • [KiBi] xterm: new upstream, to unstable.
    • [KiBi] libdrm: new upstream, to experimental. A few patches to hide private symbols were sent upstream, but I ve seen no reactions yet (and that apparently happened in the past already).
    • [KiBi] xorg-server 1.9.5rc1 then 1.9.5, to unstable.
    • [KiBi] xutils-dev to unstable: the bootstrap issue goes away, thanks to Steve s report.
    • [KiBi] libxp to unstable, nothing fancy, that s libxp
    • [KiBi] keyboard input driver: mostly documentation update, to unstable and experimental.
    • [KiBi] mouse input driver: fixes BSD issues, to unstable and experimental.
    • [KiBi] intel video driver: to experimental, but the debian-unstable branch can be used to build the driver against unstable s server.
    • [KiBi] xfixes: protocol to unstable, and library to experimental (just in case); this brings support for pointer barriers.
    • [JVdG] openchrome video driver: Julien introduced a debugging package, and got rid of the (old!) via transitional package. He also performed his first upload as a Debian Maintainer. Yay!
    • [KiBi] siliconmotion video driver: to unstable.
    • [KiBi] pixman: new upstream release candidate, to experimental
    • [Sean] last but not least: many compiz packages to experimental.

1 April 2011

Josselin Mouette: GNOME.Asia distribution collaboration session

Today we gathered the representatives of different distributions that are present at GNOME.Asia to discuss what GNOME could do to improve its support for distributions that distribute it, especially in matters of long-term support. It is kind of sad that there weren t any representatives from Canonical nor Red Hat, but the discussion turned out really interesting and we learned a lot about the packaging habits of each other. Furthermore, there were several concrete leads that were explored, which will lead to proposals from the GNOME foundation to all distributions. Helping with long-term support The most widespread GNOME version in the LTS releases that happened recently is 2.30, which is used by Debian squeeze, Ubuntu LTS 10.04, RHEL 6, and Solaris 11. It looks like an accident, but on the other hand: In the future, a decision to use a common GNOME release could, anyway, only come from the distributions themselves, not from GNOME. A proposal that many people agreed upon was to give distribution maintainers commit access to old branches that GNOME module maintainers don t touch anymore. This way they could share their patches more easily and make new releases of these old branches. This would imply, of course, setting up rules about what changes are allowed, that distributions would have to agree upon (how to treat feature additions for example). Managing bugs Currently it is hard to tell, for a distributor, whether other distributions are affected too and whether they have released a fix for that. It was agreed upon that Launchpad s feature of linking bugs between distributions, including version tracking, would exactly fill that need. One of the solutions would then be to add such a feature to Bugzilla, but it is a lot of work since currently it doesn t have any kind of version tracking. Another proposal was to deploy a new Launchpad instance to do serve as a hub between downstream bug systems and the GNOME Bugzilla. The condition for this to work would be to make it extremely easy to clone bugs between it and Bugzilla, and also if possible from the downstream bug systems. On the side-related topic of how not to crawl under bugs, it might be possible to get bugs forwarded with a single command from the Debian BTS to Bugzilla, using the XML-RPC interface. Upstream also considers that bugs sent to Debian are generally of higher quality than those from e.g. Ubuntu, and would be OK with us routing some of them directly to upstream (like we already do for Evolution). Communicating about the availability of patches Currently distributors are hardly ever informed that patches relevant for their distribution have been committed. They often learn of them by sheer luck while lurking on Bugzilla. The distributors-list ML is clearly the relevant media for that purpose, but it is clearly not used enough. It would need to be advertised more among both GNOME module maintainers, and among downstream maintainers as well. On this matter, the disappearance of the x.y.3 GNOME releases (starting with 2.28) was evoked. The problem was that most of those releases were about insufficient changes to justify e.g. stable updates in distributions. The proposed solution is to encourage maintainers of modules with bugs to fix to release new versions (through an annoucement on desktop-devel-announce), and to send a list of modules with new versions to downstream distributors so that they can integrate them. This avoids the GNOME release team the hassle of making a new release, while still giving distributions that use them some bugfixes. Providing a new service to LTS distributions The idea of having the GNOME foundation employ a person to gather, on the GNOME side, all changes that are relevant to older GNOME versions, and prepare new stable versions, was discussed. This would be a new service for which commercial distributions would need to pay a fee. It s not clear how this information would be privately disclosed and the impact on non-commercial distributions. But it doesn t seem likely that e.g. Red Hat would be interested since they employ a lot of core GNOME hackers who are already doing this job.
I don t know what impact these proposals can have on GNOME packaging in Debian, but apart from the last one that I find dubious, it seems that they could greatly improve our support of GNOME in stable Debian releases, be it by having more versions to upload during the freeze, or by having more stuff in point releases. Fr d ric Muller promised to come back to us with more concrete stuff.

Aigars Mahinovs: New Nokia games coming

Warning, this post is COMPANY CONFIDENTIAL, do not spread outside of authorized corporate internal communication channels. Today Nokia will announce that in order to increase investor confidence and foster brand loyalty all Nokia Symbian phones in the world will receive two free Nokia-themed games. The first game will be Angry Nokias Nokias have discovered that other phones are taking their market share away and now they are very, very angry! Fling cool and shiny Nokia phone and destroy the competition. Complete all free 30 levels and be first to collect all golden Ovi s by gathering MeeGo and Windows Phone 7 logos in the levels! The other game that is sure to be an instant hit among true Nokia fans will be the Nokia Ninja you are a humble user and sales people are throwing phones at you all kinds of phones. But beware most of those phones are not Nokias! Use your finger to slice trough the competition, rake up combos and achievements! But be careful you do not want to slice trough a Nokia phone! Only trough instant brand recognition you can rake up truly great scores in this game. Nokia connecting people. (P.S. Check the date)

31 March 2011

Jordi Mallach: A tale of Trist nia and its Quadrennial Royal Ball

In one of the corners of what is now know as Europa, there was a rich, prosperous and beautiful kingdom known as Trist nia. In the past, not that long ago, it had been a number of smaller kingdoms and caliphates, all with their own cultures, religions and ways of life. Wars, and series of marriages of convenience eventually configured what ended up being the united kingdom of Trist nia. Throughout the years, some of the unified cultures grew and flourished, while others struggled to survive in their ever-shrinking areas of influence. A required introduction Sometimes, the minor cultures would suffer due to oppression coming from the delegates of the King, who would ban any expression of these cultures, as they were seen as a potential threat to the kingdom's stability and unity. For example, just a few decades before the main subject of this tale, the predecessor of the incumbent King took power by force, after crushing everyone who opposed his uprise during a bloody and hard civil war. His reign was ruthless and he imposed draconian laws uppon his people: usage and teaching of the minor languages was banned, and everyone was forced to use the language of the Centr lia region, in public or private. After four decades, the majority of the Tristanian people were sick enough of the situation to consider standing against their fear of the regime and demand freedom, but repression prevailed until the old general died. His place was taken by the King's grandson even if the people had expressed, just before the Great War, that they had had enough kings and demanded a ruler they could choose directly. Of course, the new King seemed a lot nicer than who they had been suffering for ages, so when asked if they accepted the new situation, an overwhelming majority said yes . However, there was a region, Verd lia, where the majority said no . Things were actually more complicated. Verdalians formed a traditional, proud society, and while the years of oppression had undoubtedly weakened it, they had managed to preserve their very unique culture, language and traditions healthy. The Verdal language was really weird to the ears of Centr lians and even other minor cultures of the Kingdom, and erudites struggled to find its real origins, not being able to reach plausible conclusions. Verdanians, as we already know, were a traditional society, living in a land of deep and poorly connected valleys. Little they knew or cared about the complicated matters of Centr lia and other regions. What made them happy was to take care their sheep and cows, keep a good fire in their living room and, every now and then, enjoy one of their log cutting contests. The impositions of the former dictator were too much for them, and some of them started sabotaging, assaulting and killing some of the dictator's soldiers, agents and officers. This was a huge risk at the time; getting caught meant death penalty for sure, and at first, even people from other regions were in favour of these actions. However, this popular support greatly diminished when the new King took the throne, as these minority continued with the killings, while most of the people saw it was no longer justified. The Royal Ball One of the very first measures the young King introduced was to organise the Royal Ball of Trist nia , a major event through which the people of the different regions would be able to elect their delegates to the Crown. Every four years, a Great Ball contest would happen in Centr lia, and the winners would be able to decide by their own on some of the matters that affected their region. Verdanians would send a few teams of dancers, each of which came from different towns or areas. Some Verdanian teams were happy about the King and the new political situation, but other teams weren't so much. And some others, while being simple non-violent dancers, were known to be supporters of the violent minority who kept on harassing, assaulting and even killing in their struggle for freedom of Verd nia . The Verdanian groups aligned with the different culture of Verd nia (including those who were said to support the violent) tended to get a lot more points in the dancing contest, and a majority of the elected delegates were appointed by them, making it easier to pass laws and edicts that favoured protection of their ways, traditions and language. No matter how hard they tried, the dancing groups closer to Centr lia kept losing to the majority. After many years of dance contests, these groups used their closeness to the King's court to pass the Ball Law of Tristanian, that would ban any dancing group which didn't condemn the assaults and killings that kept happening in Verd nia. The unsurprising result was that, with less dancing groups participating in the following Royal Ball, the Verdanian majority was broken and new delegates, friendly of the Centralian officers, were elected. Many people who had been in favour of assaults and killings began to question this strategy, and this political movement's unity started to break. In the end, the dancers decided to part ways with the violent; they wanted to dance in the next ball, and to do so, they wrote a letter to the King, in which they explicitly expressed their rejection of violent ways, and their embracing of dancing as the only means to drive their political agenda. An objective reading of the new Ball Law clearly showed that this was enough: the text only said the requisite for a dancing group was to disavow all kinds of violence. This wasn't really expected in Centr lia, so they started to add new requirements in an attempt to keep this group from the contest: their decisive majority in Verd nia was at stake. The Royal Ball was nearing and registrations for the contest would soon close. The Centralian government first argued that the dancing group should reject the violence coming from the Verdanian extremists in particular. The dancers did it. Then they argued that the dancers were the same people who had been supporting violence in Verd nia for years, and obviously their violence rejection statement was a lie. The dancers struggled to find new dancers who had not been involved in past dances. But it was not enough. They then claimed that this dance group should be quarantined for four years, until they could prove they really were serious about their new non-violent ideas. The dance group made a plea to the Trist nian Supreme Counsel, a group of sixteen experts in law of the Kingdom, and argued that all of these draconian requirements were not part of the law that was being enforced by the King. Their appeal to the elder counselors was in vain, though. They ruled this dancing group was as criminal as the violent minority they had once supported, and should by no means take part in the Royal Ball. As a last, desperate measure, the dancing group reached an agreement with other Verdanian dancers to join forces. They would adopt a new name and new dancing costume colours. Many feared this would only end up in the ban of the other dancing group. Unfortunately, the end of this story has not been written yet, but it will be completed very soon. Only time will tell if things continue being very sad and unfair in Trist nia, or if the dance contest will once again be impartial, with legitimate results.

29 March 2011

Steve Langasek: Multiarch Monomania

So the other day, I was able to do this in an Ubuntu natty amd64 chroot for the first time.
# cat > /etc/apt/apt.conf.d/multiarch-me
APT::Architectures   "amd64"; "i386";  ;
^D
# cat >> /etc/dpkg/dpkg.cfg
foreign-architecture i386
^D
# apt-get update
# apt-get install flashplugin-installer:i386
Reading package lists... Done
Building dependency tree       
Reading state information... Done
[...]
The following NEW packages will be installed:
  flashplugin-installer:i386 flashplugin-nonfree:i386 gcc-4.5-base:i386
  libatk1.0-0:i386 libavahi-client3:i386 libavahi-common-data:i386
  libavahi-common3:i386 libc6:i386 libcairo2:i386 libcomerr2:i386
  libcups2:i386 libdatrie1:i386 libdbus-1-3:i386 libdrm2:i386
  libegl1-mesa:i386 libexpat1:i386 libfontconfig1:i386 libfreetype6:i386
  libgcc1:i386 libgcrypt11:i386 libgdk-pixbuf2.0-0:i386 libgl1-mesa-glx:i386
  libglib2.0-0:i386 libgnutls26:i386 libgpg-error0:i386 libgssapi-krb5-2:i386
  libgtk2.0-0:i386 libgtk2.0-common libice6:i386 libjasper1:i386
  libjpeg62:i386 libk5crypto3:i386 libkeyutils1:i386 libkrb5-3:i386
  libkrb5support0:i386 libnspr4:i386 libnspr4-0d:i386 libnss3:i386
  libnss3-1d:i386 libpango1.0-0:i386 libpcre3:i386 libpixman-1-0:i386
  libpng12-0:i386 libselinux1:i386 libsm6:i386 libsqlite3-0:i386
  libstdc++6:i386 libtasn1-3:i386 libthai-data libthai0:i386 libtiff4:i386
  libudev0:i386 libuuid1:i386 libx11-6:i386 libx11-data libx11-xcb1:i386
  libxau6:i386 libxcb-dri2-0:i386 libxcb-render0:i386 libxcb-shape0:i386
  libxcb-shm0:i386 libxcb-xfixes0:i386 libxcb1:i386 libxcomposite1:i386
  libxcursor1:i386 libxdamage1:i386 libxdmcp6:i386 libxext6:i386
  libxfixes3:i386 libxft2:i386 libxi6:i386 libxinerama1:i386 libxrandr2:i386
  libxrender1:i386 libxt6:i386 libxxf86vm1:i386 x11-common zlib1g:i386
0 upgraded, 78 newly installed, 0 to remove and 3 not upgraded.
Need to get 15.1 MB/15.6 MB of archives.
After this operation, 48.9 MB of additional disk space will be used.
Do you want to continue [Y/n]?
It is a truly heady experience, after so many years of talking about the need to properly support multiarch in Debian and Ubuntu, to see support for cross-installation of packages come to fruition. If you've talked to me any time in the past couple of weeks and noticed it's a little hard to get me to change the subject, well, that's why. Many who have grown accustomed to Debian and Ubuntu's lack of support for installing i386 packages on amd64 (or vice versa) may wonder what the fuss is about. (Whereas others who are well versed in distributions such as Red Hat and SuSE may laugh and wonder what took us so long...) So maybe a few words of explanation are in order. If you've ever installed ia32-libs on an amd64 machine anywhere; if you've ever noticed a bug where ia32-libs didn't work right because of wrong system paths, or had to file a request for another library to be added to ia32-libs because it wasn't included in the set of libraries Debian decided to package up in this grotesque, all-in-one 32-bit compatibility bundle; if you've ever decided not to install a 64-bit OS on your perfectly 64-bit-capable hardware because of concern that you wouldn't be able to run $random32-bitonly_application; multiarch is for you. If you've gotten stuck maintaining a lib32foo "biarch" package in Debian due to popular demand, multiarch is definitely for you. :) If you've ever cross-compiled software for a different Debian architecture than the one you were running, multiarch is for you. If you've ever wanted to run binaries for a different architecture under emulation, and found it awkward to set up the library dependencies, multiarch is for you, too. Because although the .deb world may be a little late to the party, we're also naturally taking things much further than anyone's done with rpm. Multiarch won't just give you the ability to install 32-bit libs on 64-bit systems; it'll give you the ability to install libs for any known architecture on any system. And a whole lot of pain just falls out of the equation in the process. A cross-compiling environment looks the same as a native-compiling environment. An emulated system looks the same as a native system. We can start to seriously consider cross-grading systems from one architecture to another. And all this is happening now. The groundwork is there in Ubuntu natty. Wheezy will be the release that brings multiarch to Debian. When dpkg 1.16.0 is uploaded to unstable real soon now, the bootstrapping will begin. I am immensely grateful to everyone who's helped make multiarch a reality - to Tollef, Matt and others for seeding the vision; Aurelien, Matthias and Arthur for their work to ready the toolchain; David and Michael for the apt implementation; Guillem and Raphael for the dpkg implementation, and Linaro's support to help make this possible; and the many other developers who've helped to refine this design over the years in numerous other BoFs, sessions and mailing list threads. I'm excited to find out what the Debian community will do with multiarch now that it's upon us. Christian, maybe you should start a pool for how long it will take before all the libraries shipped in ia32-libs have been converted to multiarch and we can drop ia32-libs from the archive?

25 March 2011

Dirk Eddelbuettel: R inside Qt: A simple RInside application

The RInside package makes it pretty simple and straightforward to embed R, the wonderful statistical programming environment and language, inside of a C++ application. This uses both the robust embedding API provided by R itself, and the higher-level abstractions from our Rcpp package. A number of examples are shown on this blog both here and here as well as on the RInside page; and the source package actually contains well over a dozen complete examples which cover anything from simple examples to parallel use via MPI for parallel computing. Beginning users sometimes ask about how to use RInside inside larger projects. And as I had meant to experiment with embedding inside of the powerful Qt framework anyway, I started to dabble a little. A first result is now in the SVN sources of RInside. My starting point was the classic tkdensity demo that comes with R itself. It is a good point of departure as Tcl/Tk makes it very portable---in fact it should run on every platform that runs R---and quite expressive. And having followed some of the GUI experiments around R over the years, I have also seen various re-implementations using different GUI frameworks. And so I am adding mine to this body of work: Example of embedding R via RInside into a Qt C++ application: density estimation for a mixture The problem I addressed first was actual buildability. For the RInside examples, Romain and I provide a Makefile that just works by making calls to R itself to learn about flags for R, Rcpp and RInside such that all required headers and libraries are found. That is actually relatively straightforward (and documented in our vignettes) but a little intimidating at first---which is why a ready-made Makefile is a good thing. Qt of course uses qmake and the .pro files to encode / resolve dependencies. So task one was to map what our Makefile does into its variables. Turns out that wasn't all that hard:
## -*- mode: Makefile; c-indent-level: 4; c-basic-offset: 4;  tab-width: 8; -*-
##
## Qt usage example for RInside, inspired by the standard 'density
## sliders' example for other GUI toolkits
##
## Copyright (C) 2011  Dirk Eddelbuettel and Romain Francois
TEMPLATE =              app
HEADERS =               qtdensity.h 
SOURCES =               qtdensity.cpp main.cpp
QT +=                   svg
## comment this out if you need a different version of R, 
## and set set R_HOME accordingly as an environment variable
R_HOME =                $$system(R RHOME)
## include headers and libraries for R 
RCPPFLAGS =             $$system($$R_HOME/bin/R CMD config --cppflags)
RLDFLAGS =              $$system($$R_HOME/bin/R CMD config --ldflags)
RBLAS =                 $$system($$R_HOME/bin/R CMD config BLAS_LIBS)
RLAPACK =               $$system($$R_HOME/bin/R CMD config LAPACK_LIBS)
## if you need to set an rpath to R itself, also uncomment
#RRPATH =               -Wl,-rpath,$$R_HOME/lib
## include headers and libraries for Rcpp interface classes
RCPPINCL =              $$system($$R_HOME/bin/Rscript -e \'Rcpp:::CxxFlags\(\)\')
RCPPLIBS =              $$system($$R_HOME/bin/Rscript -e \'Rcpp:::LdFlags\(\)\')
## for some reason when building with Qt we get this each time
## so we turn unused parameter warnings off
RCPPWARNING =           -Wno-unused-parameter 
## include headers and libraries for RInside embedding classes
RINSIDEINCL =           $$system($$R_HOME/bin/Rscript -e \'RInside:::CxxFlags\(\)\')
RINSIDELIBS =           $$system($$R_HOME/bin/Rscript -e \'RInside:::LdFlags\(\)\')
## compiler etc settings used in default make rules
QMAKE_CXXFLAGS +=       $$RCPPWARNING $$RCPPFLAGS $$RCPPINCL $$RINSIDEINCL
QMAKE_LFLAGS +=         $$RLDFLAGS $$RBLAS $$RLAPACK $$RCPPLIBS $$RINSIDELIBS
## addition clean targets
QMAKE_CLEAN +=          qtdensity Makefile
The double dollar signs and escaping of parentheses are a little tedious, but hey it works and expands the compiler and linker flags such that everything <emjust works="Works">. The code itself is pretty straightforward too. We instantiate the RInside object as well as the main Qt application object. We then instantiate a new object of class QtDensity that will launch the main widget; it is given a reference to the RInside object.
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4;  tab-width: 8; -*-
//
// Qt usage example for RInside, inspired by the standard 'density
// sliders' example for other GUI toolkits
//
// Copyright (C) 2011  Dirk Eddelbuettel and Romain Francois
#include <QApplication>
#include "qtdensity.h"
int main(int argc, char *argv[])
 
    RInside R(argc, argv);  		// create an embedded R instance
    QApplication app(argc, argv);
    QtDensity qtdensity(R);
    return app.exec();
 
The definition of the main object is pretty simple: a few private variables, and a few functions to interact with the GUI and get values from the radio buttons, slider or input field---as well as functions to update the chart or re-draw the random variables.
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4;  tab-width: 8; -*-
//
// Qt usage example for RInside, inspired by the standard 'density
// sliders' example for other GUI toolkits
//
// Copyright (C) 2011  Dirk Eddelbuettel and Romain Francois
#ifndef QTDENSITY_H
#define QTDENSITY_H
#include <RInside.h>
#include <QMainWindow>
#include <QHBoxLayout>
#include <QSlider>
#include <QSpinBox>
#include <QLabel>
#include <QTemporaryFile>
#include <QSvgWidget>
class QtDensity : public QMainWindow
 
    Q_OBJECT
public:
    QtDensity(RInside & R);
private slots:
    void getBandwidth(int bw);
    void getKernel(int kernel);
    void getRandomDataCmd(QString txt);
    void runRandomDataCmd(void);
private:
    void setupDisplay(void);    // standard GUI boilderplate of arranging things
    void plot(void);            // run a density plot in R and update the
    void filterFile(void);      // modify the richer SVG produced by R
    QSvgWidget *m_svg;          // the SVG device
    RInside & m_R;              // reference to the R instance passed to constructor
    QString m_tempfile;         // name of file used by R for plots
    QString m_svgfile;          // another temp file, this time from Qt
    int m_bw, m_kernel;         // parameters used to estimate the density
    QString m_cmd;              // random draw command string
 ;
#endif
Lastly, no big magic in the code either (apart from the standard magic provided by RInside). A bit of standard GUI layouting, and then some functions to pick values from the inputs as well as to compute / update the output. One issue is worth mentioning. The screenshot and code show the second version of this little application. I built a first one using a standard portable network graphics (png) file. That was fine, but not crisp as png is a pixel format so I went back and experimented with scalable vector graphics (svg) instead. One can create svg output with R in a number of ways, one of which is the cairoDevice package by Michael Lawrence (who also wrote RGtk2 and good chunks of Ggobi). Now, it turns out that Qt displays the so-called SVG tiny standard whereas R creates a fuller SVG format. Some discussion with Michael reveals that one can modify the svg file suitably (which is what the function filterFile below does) and it all works. Well: almost. There is a bug (and Michael thinks it is the SVG rendering) in which the density estimate does not get clipped to the plotting region.
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4;  tab-width: 8; -*-
//
// Qt usage example for RInside, inspired by the standard 'density
// sliders' example for other GUI toolkits -- this time with SVG
//
// Copyright (C) 2011  Dirk Eddelbuettel and Romain Francois
#include <QtGui>
#include "qtdensity.h"
QtDensity::QtDensity(RInside & R) : m_R(R)
 
    m_bw = 100;                 // initial bandwidth, will be scaled by 100 so 1.0
    m_kernel = 0;               // initial kernel: gaussian
    m_cmd = "c(rnorm(100,0,1), rnorm(50,5,1))"; // simple mixture
    m_R["bw"] = m_bw;           // pass bandwidth to R, and have R compute a temp.file name
    m_tempfile = QString::fromStdString(Rcpp::as<std::string>(m_R.parseEval("tfile <- tempfile()")));
    m_svgfile = QString::fromStdString(Rcpp::as<std::string>(m_R.parseEval("sfile <- tempfile()")));
    m_R.parseEvalQ("library(cairoDevice)");
    setupDisplay();
 
void QtDensity::setupDisplay(void)   
    QWidget *window = new QWidget;
    window->setWindowTitle("Qt and RInside demo: density estimation");
    QSpinBox *spinBox = new QSpinBox;
    QSlider *slider = new QSlider(Qt::Horizontal);
    spinBox->setRange(5, 200);
    slider->setRange(5, 200);
    QObject::connect(spinBox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
    QObject::connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int)));
    spinBox->setValue(m_bw);
    QObject::connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(getBandwidth(int)));
    QLabel *cmdLabel = new QLabel("R command for random data creation");
    QLineEdit *cmdEntry = new QLineEdit(m_cmd);
    QObject::connect(cmdEntry,  SIGNAL(textEdited(QString)), this, SLOT(getRandomDataCmd(QString)));
    QObject::connect(cmdEntry,  SIGNAL(editingFinished()), this, SLOT(runRandomDataCmd()));
    QGroupBox *kernelRadioBox = new QGroupBox("Density Estimation kernel");
    QRadioButton *radio1 = new QRadioButton("&Gaussian");
    QRadioButton *radio2 = new QRadioButton("&Epanechnikov");
    QRadioButton *radio3 = new QRadioButton("&Rectangular");
    QRadioButton *radio4 = new QRadioButton("&Triangular");
    QRadioButton *radio5 = new QRadioButton("&Cosine");
    radio1->setChecked(true);
    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addWidget(radio1);
    vbox->addWidget(radio2);
    vbox->addWidget(radio3);
    vbox->addWidget(radio4);
    vbox->addWidget(radio5);
    kernelRadioBox->setMinimumSize(260,140);
    kernelRadioBox->setMaximumSize(260,140);
    kernelRadioBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    kernelRadioBox->setLayout(vbox);
    QButtonGroup *kernelGroup = new QButtonGroup;
    kernelGroup->addButton(radio1, 0);
    kernelGroup->addButton(radio2, 1);
    kernelGroup->addButton(radio3, 2);
    kernelGroup->addButton(radio4, 3);
    kernelGroup->addButton(radio5, 4);
    QObject::connect(kernelGroup, SIGNAL(buttonClicked(int)), this, SLOT(getKernel(int)));
    m_svg = new QSvgWidget();
    runRandomDataCmd();         // also calls plot()
    QGroupBox *estimationBox = new QGroupBox("Density estimation bandwidth (scaled by 100)");
    QHBoxLayout *spinners = new QHBoxLayout;
    spinners->addWidget(spinBox);
    spinners->addWidget(slider);
    QVBoxLayout *topright = new QVBoxLayout;
    topright->addLayout(spinners);
    topright->addWidget(cmdLabel);
    topright->addWidget(cmdEntry);
    estimationBox->setMinimumSize(360,140);
    estimationBox->setMaximumSize(360,140);
    estimationBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    estimationBox->setLayout(topright);
    QHBoxLayout *upperlayout = new QHBoxLayout;
    upperlayout->addWidget(kernelRadioBox);
    upperlayout->addWidget(estimationBox);
    QHBoxLayout *svglayout = new QHBoxLayout;
    svglayout->addWidget(m_svg);
    QVBoxLayout *outer = new QVBoxLayout;
    outer->addLayout(upperlayout);
    outer->addLayout(svglayout);
    window->setLayout(outer);
    window->show();
 
void QtDensity::plot(void)  
    const char *kernelstrings[] =   "gaussian", "epanechnikov", "rectangular", "triangular", "cosine"  ;
    m_R["bw"] = m_bw;
    m_R["kernel"] = kernelstrings[m_kernel]; // that passes the string to R
    std::string cmd1 = "Cairo(width=6,height=6,pointsize=10,surface='svg',filename=tfile); "
                       "plot(density(y, bw=bw/100, kernel=kernel), xlim=range(y)+c(-2,2), main=\"Kernel: ";
    std::string cmd2 = "\"); points(y, rep(0, length(y)), pch=16, col=rgb(0,0,0,1/4));  dev.off()";
    std::string cmd = cmd1 + kernelstrings[m_kernel] + cmd2; // stick the selected kernel in the middle
    m_R.parseEvalQ(cmd);
    filterFile();               // we need to simplify the svg file for display by Qt 
    m_svg->load(m_svgfile);
 
void QtDensity::getBandwidth(int bw)  
    if (bw != m_bw)  
        m_bw = bw;
        plot();
     
 
void QtDensity::getKernel(int kernel)  
    if (kernel != m_kernel)  
        m_kernel = kernel;
        plot();
     
 
void QtDensity::getRandomDataCmd(QString txt)  
    m_cmd = txt;
 
void QtDensity::runRandomDataCmd(void)  
    std::string cmd = "y <- " + m_cmd.toStdString();
    m_R.parseEvalQ(cmd);
    plot();                     // after each random draw, update plot with estimate
 
void QtDensity::filterFile()  
    // cairoDevice creates richer SVG than Qt can display
    // but per Michaele Lawrence, a simple trick is to s/symbol/g/ which we do here
    QFile infile(m_tempfile);
    infile.open(QFile::ReadOnly);
    QFile outfile(m_svgfile);
    outfile.open(QFile::WriteOnly   QFile::Truncate);
    
    QTextStream in(&infile);
    QTextStream out(&outfile);
    QRegExp rx1("<symbol"); 
    QRegExp rx2("</symbol");    
    while (!in.atEnd())  
        QString line = in.readLine();
        line.replace(rx1, "<g"); // so '<symbol' becomes '<g ...'
        line.replace(rx2, "</g");// and '</symbol becomes '</g'
        out << line << "\n";
     
    infile.close();
    outfile.close();
 
What the little application does is actually somewhat neat for the few lines. One key features is that the generated data can be specified directly by an R expression which allows for mixtures (as shown, and as is the default). With that it easy to see how many points are needed in the second hump to make the estimate multi-modal, and how much of a distance between both centers is needed and so on. Obviously, the effect of the chosen kernel and bandwidth can also be visualized. And with the chart the being a support vector graphics display, we can resize and scale at will and it still looks crisp. The code (for both the simpler png variant and the svg version shown here) is in the SVN repository for RInside and will be in the next release. Special thanks to Michael Lawrence for patiently working through some svg woes with me over a few emails.

Update: Some typos fixed.

Update 2: Two URLs corrected.

Next.

Previous.