Thursday, November 16, 2006

God Damn I Hate Cygwin

First of all, let's get the rant out of the way. Cygwin is a big pile of junk. It's like everyone who touches Cygwin gets the clue beaten out of them before they're allowed to hack on it. Here's a tip guys, if you're going to try to do something really hard (like build a POSIX compatible software layer on top of an operating system that holds many parts of the POSIX standard as the anti-thesis of its design) you have to put a lot of effort into it. Ok, done.

I recently had this problem:
Fatal server error: could not open default font 'fixed'

for which I googled, lots and lots and lots and found no adequate solution. I found the Cygwin/X Frequently Asked Questions and it had two suggests as to what the problem could be:
  1. You don't actually have the xorg-x11-fnts package installed (duh, thanks guys, yeah, that wasn't the first thing I checked).
  2. The mount point for /usr/X11R6/lib/X11/fonts was invalid at the time that Cygwin's setup.exe installed the xorg-x11-fnts package.

This advice is, of course, absolutely useless. What mount point are you talking about guys? In what way could it be "invalid"? Why would have I have to manually fuck around with this stuff anyways? My /usr/X11R6/lib/X11/fonts happens to be mounted on /, which is mounted to c:\cygwin.. ya know, like everyone else who uses cygwin. What the hell are you guys on about?

Well, turns out what they are trying to say is that you need to make a mount point for /usr/X11R6/lib/X11/fonts. The problem is that stupid "do you want to use unix mode or text mode?" option at the start of the cygwin installer. Probably 50% of people choose unix mode, then discover something doesn't work (like, say, scripts that have been checked into a repository by someone who chose textmode) and then quickly change to textmode. If you are using textmode for /. then you will have this problem. Here's how to fix it:
foo@mymachine ~
$ cd /usr/X11R6/lib/X11
foo@mymachine /usr/X11R6/lib/X11
$ mv fonts fonts_real
foo@mymachine /usr/X11R6/lib/X11
$ mount -b c:\\cygwin\\usr\\X11R6\\lib\\X11\\fonts_real 
           /usr/X11R6/lib/X11/fonts

Your fonts dir should now be mounted in "binmode". But that's not all! You need to edit /usr/X11R6/bin/font-update and look for a need_update="", between those quotes, put a 1. Now do:
foo@mymachine ~
$ /usr/X11R6/bin/font-update

and don't forget to edit /usr/X11R6/bin/font-update and take the 1 out of those quotes.

If you are a Cygwin/X developer, please, please, please add a mount command to the installer! We shouldn't have to do this shit manually!

Tuesday, November 14, 2006

Windows Printer on Linux

I'm a Ubuntu user but I also run a number of Windows machines for work purposes. I was actually shocked recently to discover that CUPS supports my Brother HL-5140 laser printer without me having to download any binary blobs from the Brother website. So that's good.

What's not so great is that gnome-cups-ui has no concept of workgroups or domains for connecting via smb to a windows printer. When you go to "add new printer" or when you view the connection properties after adding the new printer, the fields you are presented with are:

  • Host
  • Printer
  • Username
  • Password

After googling for a bit, I discovered that people have figured out that if you put the workgroup name in the Host field and then enter username:password@host/Printer into the Printer field and nothing into either the username or password fields, you can print!

Curious about this obscurity, I did an apt-get source gnome-cups-ui and hunted around for a bit. Eventually, I found some code that looks basically like this:

if (username != NULL && username[0] && password != NULL && password[0])
ret = g_strdup_printf("smb://%s:%s@%s/%s", username, password, host, printer);
else
ret = g_strdup_printf("smb://%s/%s", host, printer);

do you see what's happening? The hack outlined above uses the second case. An alternative would be to enter workgroup/username into the Username field and your password into the password field, that would use the first case. The problem with doing that, however, is that if you don't enter a password then the username will be ignored.. this isn't much good if you're trying to use the Guest account, which requires no password. Also, even if you're using a real account, the resulting URI won't parse correctly so when you refresh the connection properties you'll end up with the workgroup in the Host field and everything else (including your password) in the Printer field.

I wrote myself a nice little patch to ask for a workgroup and parse the uri correctly, etc. If anyone wants it, you can grab it from here:

gnome-cups-manager-0.31-with-workgroup.diff

However, turns out this has already been fixed in the latest CVS, so I won't be contacting the authors. Kinda makes me wonder how long it takes for fixes like this to filter out of CVS and into the distributions. Ubuntu releases are tied to the GNOME releases, so it should be one of the fastest to get fixes like this, but this is still broken in the latest Ubuntu release (Edgy).

Thursday, November 02, 2006

A 5mb binary blob in the kernel?

If you pop over to the NVIDIA web site and download the 3d card drivers for Linux, you'll note that there is a /usr/src/nv directory. In that directory is source code to the "thin layer" to the Linux kernel which NVIDIA links their binary blob. This, of course, makes no legal difference - NVIDIA are still extending the Linux kernel and therefore it is unlawful to distribute the Linux kernel along with the NVIDIA drivers, but NVIDIA doesn't do that, so it's not a problem - for them. Anyway, that's a side issue. I was thinking, recently, about the Linux kernel's "tainted" flag. Essentially, whenever you install a kernel module that isn't under some accepted open source license, the kernel sets a flag so that developers know there is a chance that any bugs you report might have been caused by code they can't fix. In general, this is not such a big deal as kernel modules are typically small and easy to isolate. The NVIDIA graphics drivers, on the other hand, are not small, they are actually over 5 meg.. loading anything that is 5 meg in size into the kernel is typically a bad idea. It's much better to split some parts out into userland and use thunks to connect the kernel part to the userland part.

So back to this /usr/src/nv directory. If you have a look, there's a bunch of source files, header files, make files and this nv-kernel.o file. That's the binary blob. They don't give us source for that bit. For me, it's 5104332 bytes, and most of the symbols have been replaced with stuff like _nv003299rm. This, of course, is to make it harder to understand if you were to try to reverse engineer it.

Now, someone out there, if you build your own kernel, I need your help (done, see comments). Go into the /usr/src/nv directory, do a make and get this thing to build. You may have to screw around with paths and stuff, and this is the reason why I havn't done it myself. Ok, got it to build? Great. Now make clean and remove the nv-kernel.o from the Makefile, then make. You should get some errors.. in particular, we're looking for "undefined symbol" errors. How many symbols are undefined?

This tells us how big the interface is between the source layer and the binary layer. If this interface is small enough we can write thunks for each symbol and move the binary layer into userland. If we do speed tests and discover that it isn't much slower to run the blob in userland then we can create a module that contains no binary code, and maybe the Linux kernel developers will consider this "untainted" enough that it is useful to someone. Knowing that interface will also help reverse engineer the binary part.