the djb way


errno patches

On systems using the GNU C Library ("glibc") version 2.3.x and later, most of the packages released by Bernstein to date will, unfortunately, not compile without some modification.

The GNU glibc library 2.3.x is the Standard C library found on most Linux distributions today. The modifications are necessary to correct an incompatibility in errno declarations between Bernstein's software and this library.

The incompatibility arises because Bernstein's source code contains explicit declarations of the global variable errno in the form of:

extern int errno;

Although this is a common idiom of classic C programming and conforms with POSIX 1003.1a, 1990, it is no longer consistent with Standard C and the latest POSIX specification (IEEE Std 1003.1, 2004 Edition). The correct declaration for errno is now obtained by including the standard header file:

#include <errno.h>

You know you have this problem if you see output similar to the following when you try to build the package (the sample output here follows make for a clockspeed build on a Linux system):

# make
[...compiler output...]
./load sntpclock ip.o libtai.a strerr.a substdio.a error.a \
str.a fs.a  `cat socket.lib`
strerr.a(strerr_sys.o)(.text+0x7): In function `strerr_sysinit':
: undefined reference to `errno'
substdio.a(substdo.o)(.text+0x47): In function `allwrite':
: undefined reference to `errno'
collect2: ld returned 1 exit status
make: *** [sntpclock] Error 1

Fortunately, the fix is quite simple. Simply remove the explicit declarations of errno and replace them with:

#include <errno.h>

This will include the proper declaration of errno for the host system library.

Now, while you could grep and edit the source distribution for instances of the offending declaration yourself, you don't have to. Some kind souls have already gone to the trouble for us, and have made their efforts available by way of patch files.

patch files are used to apply specific changes to the original source distribution. They take their name from the patch(1) program that is used to apply them.

As an example of their usage, here is a build sequence involving a patch for clockspeed:

# cd /usr/local/djb/build
# tar -xzvf ../dist/clockspeed-0.62.tar.gz
# cd clockspeed-0.62
# patch -p1 < ../../patches/clockspeed-0.62.errno.patch
[output from patch...]
# make setup check

As shown above, the patch command takes its input from the patchfile named clockspeed-0.62.errno.patch. (The patchfile may be located anywhere on your system; in the example above, it is located in /usr/local/djb/patches.)

Where to get the patchfiles? The errno patches described at this site link to Mate Wierdl's archive at:

ftp://moni.csi.hu/pub/glibc-2.3.1/

If you need one you'll need 'em all:

# mkdir /usr/local/djb/patches
# cd /usr/local/djb/patches
# wget ftp://moni.csi.hu/pub/glibc-2.3.1/*.patch

These patches are also available from our local archive in this tarball:

http://www.thedjbway.org/patches/djb_errno_patches.tgz

Note that BSD systems use their own, non-GNU, Standard C library and--so far at least--Bernstein's software will compile successfully on these systems without modification. However, the errno patch procedures described here are harmless on BSD systems, and technically correct, even if they are not strictly necessary.

the bernstein patchless workaround

In the build instructions for the djbdns package, Bernstein himself comments on the errno issue as a "Linux bug". The workaround he suggests is to instruct the compiler to include the errno.h header file from the command line:

$ gcc -include /usr/include/errno.h  ...

In most packages this workaround may be obtained by modifying the conf-cc file. For example, the conf-cc file in the clockspeed distribution can be modified from:


gcc -O2

To:


gcc -O2 -include /usr/include/errno.h

After modifying conf-cc, build the package with make as usual. The errno.h file will then be included in the build without having to patch any source files.

references

Standard C permits the global variable errno to be any modifiable lvalue evaluating to type int, not necessarily a simple variable. From C A Reference Manual, Fifth Edition (Harbison & Steel, 2002), page 327:

In Standard C, errno need not be a variable; it can be macro that expands to any modifiable lvalue of type int.

In the case of glibc, in fact, errno is defined as a macro that expands to a function call.

From Advanced UNIX Programming, Second Edition (Rochkind, 2004), page 24:

You can use errno like an integer, although it's not necessarily an integer variable. If you're using threads, errno is likely to involve a function call, because the different threads can't reliably all use the same global variables. So don't declare errno yourself (which used to be exactly what you were supposed to do), but use the definition in the header.

Okay, got it: errno, not an integer.

But old habits die hard, and gratuitous breakage of software is unfortunate. We recently (fall 2004) observed the esteemed Perl hacker Randal Schwartz express this sentiment on a local users' group mailing list:

Why would errno *not* be an integer?

If Linux broke this, Linux ain't unix at *all* anymore.

Copyright © 2002, 2003, 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.10.16, wcm.