2007-10-29
My problem with learning new programming languages
There's any number of programming languages I'd like to learn, ranging from the prosaic like C++, Java, and JavaScript (mostly because it would make it easier to work with various interesting things written in them, like Firefox) to the esoteric favorites like Haskell and Erlang. Unfortunately, I have a problem.
My problem is that I can't learning languages by themselves in the abstract; I can't just sit down and learn one just to know it. I need to be learning them to use them on something, and the something has to feel real and motivating to me. Without a real project to use the language on, my motivation collapses; the whole exercise becomes a purely intellectual pursuit and I turn away to more interesting things.
(It doesn't have to be a project that really cries out for the language,
and it doesn't have to be a big project, although it does have to be
something that I actually want; for example, my first Python code was
a little thing to spit out /etc/lilo.conf stanzas for the kernels it
found in /boot. However, this is more difficult in languages that
aren't really suitable for little command line utilities or that really
want to be used in big projects, from which I conclude that I will not
be learning Java any time soon.)
I find this a bit irritating, because I would like to know things like Haskell; they certainly seem interesting, and I keep reading snippets of tutorials (and explanations of monads). But I can only read so much without writing a program, partly to test my understanding, and my motivation for writing programs that won't do anything useful is lacking.
(Haskell is probably going to be a real challenge; most of the stuff I want to do involves file IO, which seems to imply a fairly immediate dive down into the depths of IO monads and so on. Maybe I'll find a relatively pure logic problem to tackle.)
2007-10-10
How to properly look up hostnames from IP addresses
Looking up reverse DNS to determine the hostname of an IP address that you are talking to is one of those almost simple things that software keeps getting wrong. So here is how you do it, in two variants.
First, if you use DNS and have an (almost) empty /etc/hosts or just
don't care about looking up something in it, is the simple version:
gethostbyaddr()the IP address. If it fails, you are done. Otherwise you have the claimed hostname.(Technically you have a claimed hostname, since hosts may have multiple PTR records. Your
gethostbyaddr()equivalent may return multiple names in this case; if so, pick one.)- check to make sure that the claimed hostname is not an IP address;
many systems will helpfully do successful hostname lookups on IP addresses.
If the claimed hostname is an IP address, fail the hostname lookup.
- Add a dot (
.) to the end of the claimed hostname, andgethostbyname()the result. If it fails, you are done. Otherwise, check to see if any of the returned IP addresses is the original IP address.
The first two steps are the 'reverse lookup'; the third is the 'forward lookup'.
Adding a dot to the end of the claimed hostname forces a rooted DNS lookup without any use of your DNS search list of default domains. Without this, it's possible that a local host will block a successful check on an outside one because the local host has a short name that is the same as the full name of the outside host.
If you have an /etc/hosts with short names, you need to add an extra
step at the end: if the forward lookup check has failed, try it again
without adding the trailing dot. This allows it to match a short name
in /etc/hosts that may have been returned by the reverse lookup.
Depending on what you are using the hostname for, you may want to map it to a consistent (ASCII) case or preserve it as the reverse lookup gave it to you. (If you are presenting it to the user and you care, you may then want to worry about IDNA issues.)