> Publications > CGI Developer's Guide

Errata    <general | chapter 4 | chapter 5 | chapter 7 | chapter 9 | chapter 10 | chapter 11 | chapter 12>    (01)

General Notes    (02)

There are undoubtedly far more errors than listed here. Most of these were reported by readers. Please help me and other readers by reporting any errors you might catch. You can send me e-mail at    (03)

cgihtml    (04)

Most of the C code relies on my cgihtml library. The biggest gaffe was that it was not included on the CD-ROM. You can get the latest version of cgihtml at:    (05)

Since the publication of the book, cgihtml has evolved quite a bit with additional features and many, many bugfixes. I encourage you to get the latest version from the above URL.    (07)

unistd.h    (08)

Porting code to Windows    (09)

In a sidebar in Chapter 4 (pp61-62), I describe the the differences between a carriage return and a newline. Correct CGI programs will send both a carriage return and a newline to terminate headers. However, both C and Perl in Windows default to using "text mode," which will treat carriage returns like newlines.    (010)

To make your code as portable as possible, I recommend simply using newlines (\n) as line terminators. While not strictly correct, newlines seem to work universally, while carriage returns and newlines (\r\n) will sometimes not be interpreted correctly.    (011)

Chapter 4    (012)

Typos    (013)

Contributed by J.T. Haskell <>    (014)

On page 77 in Listing 4.12, line 11 of the perl code is incorrect. It should read:    (015)

"<p>".(localtime)."</p>\n";    (016)

Chapter 5    (017)

Incorrect Locking Scheme    (018)

Contributed by: Rick Osterberg <>, Urban Ottosson <>    (019)

The counter program I present in Listing 5.2 uses a flawed locking scheme. The correction here applies to the other examples in my book that use the same locking scheme.    (020)

In my C examples, I have three locking functions: lock_file(), unlock_file(), and wait_for_lock(). The application calls wait_for_lock() to see if a lockfile exists; if one does, it waits until it goes away. It then calls lock_file().    (021)

The problem is that waiting for the lockfile and creating a lockfile needs to be an atomic operation, and in my examples, they're not. In the time between wait_for_lock() and lock_file(), another application may create a lockfile, and boom, you have a problem.    (022)

It's not enough to simply package the routines wait_for_lock() and lock_file() into a single function. You need to use one atomic function call that will check for a lock by attempting to create one.    (023)

Unfortunately, this cannot be done portably. If there is interest, I will provide source code for both UNIX and Windows to properly handle lockfiles.    (024)

The guestbook example in Listing 5.14 suffers from the same locking problem.    (025)

Typos    (026)

Contributed by: Flint <>, Frederick Mueller <>    (027)

On page 112, in the Caution box, the encoded string should be:    (028)

y%3D=x&xmin%3D=-5&xmax%3D=5    (029)

The string with decoded hexadecimal values should be:    (030)

y==x&xmin==-5&xmax==5    (031)

On page 125 in Listing 5.15, the variable definition of str in the function date_and_time() should be:    (032)

char *str = malloc(sizeof(char) * 80 + 1);    (033)

Near the bottom of that same page, in the append function, the call to unlock_file() is missing a closed parentheses, and two lines later, there is a random close parentheses and semicolon that should not be there. This chunk of code should read:    (034)

if ((guestfile = fopen(fname, "a")) == NULL) {
}    (035)

Chapter 7    (036)

Typos    (037)

On page 156, the C code on the last line should read:    (038)

printf("Content-Type: text/plain\r\n\r\n");    (039)

Chapter 9    (040)

Alternatives to SSIs. (p196)    (041)

Contributed by Byron Rendar <>    (042)

I state, "In Chapter 4, I offer several alternatives to using server-side includes." However, referring back to Chapter 4, it's not clear what those alternatives are.    (043)

In my opinion, there are two good alternatives to SSI:    (044)

Typos. (pp202-203)    (047)

Contributed by Byron Rendar <>    (048)

On p202, I say, "If message, for example, were longer than 80 characters, the code in Listing 9.2 would crash." "Listing 9.2" should be "Listing 9.1."    (049)

In Table 9.1, the single quotes in the last entry are supposed to be back ticks.    (050)

Chapter 10    (051)

Typos (p237)    (052)

Contributed by Matthias Pigulla <>    (053)

In Listing 10.11, there is a while loop in main that reads:    (054)

while (window != NULL) {
  fprintf(output, "%s,", escape_commas((*window).entry.value));
}    (055)

This will cause an infinite loop, since the pointer is never advanced. It should read:    (056)

while (window != NULL) {
  fprintf(output, "%s,", escape_commas((*window).entry.value));
  window = window->next;
}    (057)

Typos (p239)    (058)

Contributed by Byron Rendar <>    (059)

In the paragraph above listing 10.13, the text says backslashes but the symbols used are forward slashes. The symbols are incorrect; they should be backslashes (\).    (060)

Chapter 11    (061)

Typos (p267)    (062)

In Listing 11.15 (form.cgi), -| should be |-:    (063)

open(MAIL, "|-") || exec $sendmail,$mailto;    (064)

Chapter 12    (065)

Typos (p280)    (066)

Contributed by Will Allan <>    (067)

In Listing 12.1 (rolodex.c), llist *entries; should be llist entries;.    (068)