Errata
The following table summarizes errors, or alleged errors, that have come to
my attention mostly via emails from readers. I've identified the contributor in
the Credit column; if that's blank, it means I get the credit. (Double credit
really, since I made the original mistake, too.)
The Comment column contains a description of the error and its resolution. If
anything there is italicized, I'm quoting the person in the Credit column.
I haven't worked out the actual textual correction to the book in some cases,
so the Correction column may be blank. Also, in some cases I haven't verified
that the contribution is correct, so be cautious about taking anything here as
fact unless it's something in the Correction column. (Although if Geoff Clare said it, it's
most likely true.)
If the error affects Example source, the file(s) involved are listed in the
File column. If that column is blank, it may mean that I haven't yet identified
changes to the source files, not that no changes are needed.
In other words, please treat this page as a work-in-progress.
(I'm trying to think what was going on with me while I was writing page 287,
which has 5 errors.)
Section |
Page |
File |
Comment |
Credit |
Correction |
1.4.2 |
34 |
|
... the EC_FLUSH macro, in ec.h, is defined taking one
argument that seems to me not be used. There was an earlier
implementation that did use the argument, to further identify the source of
the error. I decided that wasn't necessary, but left the argument in.
Perhaps this is a good idea, but I should have at least provided an
explanation. |
Fabio De Francesco |
p. 36, end of 3rd bullet, add: "(The argument isn't used.)" |
1.6 |
56 |
|
I said there was disagreement "among the various standards
about whether the 'va' macros" go in stdio.h or stdarg.h. Geoff Clare
writes: The problem you had is entirely gcc's fault.
When you compile with gcc it uses its own <stdarg.h> header, but the
normal Solaris <stdio.h> header. SUS requires that these both define va_list,
so they need to cooperate such that if they are both included then the one
that is included second does not try to redefine va_list. Solaris's <stdarg.h>
does cooperate properly with <stdio.h> in this respect, but gcc's own <stdarg.h>
does not.
There is no "disagreement" between the standards. The SUS requirement for
va_list to be defined by <stdio.h> is simply an extension to Standard C. Nor
is Solaris any different from the other SUS-compliant systems here. They all
define va_list in both <stdarg.h> and <stdio.h> (when the appropriate FTM is
defined). The only difference is the internal mechanism those headers use to
cooperate with each other. |
Geoff Clare |
1st para.: delete the words "among the various standards"
and insert the words "gcc on" before "Solaris". |
2.12 |
98 |
|
Misspelled "kernel." Spelled correctly on the previous and
next lines, and in the same sentence in 1985 edition! |
Haris Memic |
"kernal" should be "kernel." |
2.15 |
113 |
|
Michael Kerrisk has different results for writev. See the
post on
the AUP Forum. |
Michael Kerrisk |
Reference to Michael's post added to footnote 12. |
Ex. 2.5 |
121 |
|
"an Bseek" should be "a Bseek" |
Michael Kerrisk |
Change "an" to "a". |
3.4.1 |
145 |
|
|
|
Replace the word "we've" on the first line with "I've". |
3.5.1 |
149 |
|
At page 149 in the first itemized paragraph, you showed some example
using /dev/ad0s1g and root file system, but I think that the
'/dev/ad0s1g' should be changed to '/dev/ad0s1m', and I think
that this modification more fits to your original intention.
|
Byung-Joon Lee |
Replace "g" with "m". |
3.6.2 |
166 |
|
fchdir synopsis: "directorby" |
Michael Kerrisk |
Change it to "directory by". |
3.6.5 |
178 |
aupls.c |
I wrote the correction in the column to the right, but
Geoff Claire disagrees. I haven't checked into this yet. I think the
program behaves more sensibly without this change.
As far as I can tell the only difference it makes is what happens when you
pass the name of a non-directory file as the argument to aupls (and -d is
not used). The original program would output the details for that file. With
the above change it ignores the file.
I realise that the intention is for the argument to be a directory (as
indicated in the "usage" message), but the program needs to do something
reasonable if a non-directory is specified. The original behaviour was fine.
A reasonable alternative would be to give an error message saying that the
specified file is not a directory. Just ignoring it does not seem reasonable
to me. |
Geoff Clare |
In function do_entry, the line
if (stat_only || !is_dir)
{
should be
if (stat_only) {
|
3.7 |
181 |
|
In table 3.3 on page 181 the "Changed by" entries for
st_atime and st_ctime should be the other way round. (st_atime can be
changed by utime(); st_ctime is only changed by side-effect.) |
Geoff Clare |
Change as indicated. |
3.7.2 |
183 |
|
In synopsis header, "ichown". |
Michael Kerrisk |
Change to "lchown". |
4.3.1 |
227 |
|
Description of TOSTOP: "clocked" |
Michael Kerrisk |
Change to "blocked". |
4.5.10 |
243 |
|
On page 243 you suggest changing character size and
parity settings in c_cflag for raw mode. This may work fine with a terminal
emulator, but if there is real hardware involved these are hardware settings
that need to match the terminal device. Changing them could cause data
corruption. Also when changing c_cflag settings, tcsetattr() can fail with
EINVAL to indicate that the requested settings are not supported. I would
recommend that you remove the parts that mess with CSIZE/CS8 and PARENB.
(Clearing INPCK is fine.) |
Geoff Clare |
|
4.7 |
248 |
|
You say on page 248 that the name /dev/tty wasn't a
requirement prior to SUS2. That's not true - it was also in SUS1 and XPG4. |
Geoff Clare |
1st para.: Insert "always" after "wasn't" and delete the
words "prior to SUS2". |
4.10.1 |
261 |
ptutil.c |
On page 261 the O_NOCTTY flag is used in the
posix_openpt() call but it is missing from the open() of /dev/ptmx. |
Geoff Clare |
Add "| O_NOCTTY" to the 2nd arg of open. |
4.10.1 |
264-265 |
|
Now the fun one - STREAMS ptys (page 264/265). SUS2
requires that STREAMS ptys work correctly if you just open the slave device
obtained from ptsname(). There is no need to push any modules on a UNIX98
system. Or more precisely, there is no need when a standards-conforming
environment is used on a UNIX98 system. Solaris does conform to UNIX98 but
it provides both conforming and non-conforming environments. If your code is
compiled with Sun's c89 compiler, the pty will end up with two instances of
the ptem and ldterm modules on the STREAM, causing havoc (e.g. double
echoing of typed characters). To avoid this problem you need to use I_FIND
to check whether each module is already on the STREAM before you I_PUSH it. |
Geoff Clare |
|
4.10.2 |
274 |
record.c |
|
|
On p. 274, 4th line from the bottom: The ec_neg1 test
should be ec_false. (See the comment on the 3rd line from the top on p. 37.) |
5.2 |
282 |
|
2nd bullet: "a =" |
Michael Kerrisk |
Change to "an =". |
5.*, 6.* |
285 and other places |
|
You have calls to execl() with just NULL as the last
argument. It needs to be (char *)NULL or (char *)0. ... The reason the cast
is needed is because NULL is allowed to be defined as plain 0, and execl()
is a variadic function so the compiler has no way of knowing it should
convert the 0 to a pointer instead of passing it as an int. |
Geoff Clare |
"NULL" changed to "(char *)NULL" in these places: synopses
for execl, execlp, and execle on p. 285, 288, and 289, and in Appendix D;
example code on p. 286, 287 (2 places), 368, 372, 374 (2 places), 375 (2
places), 391, 393, 396, and 401. |
5.3 |
287 |
|
"fd < open_max - 1" should be "fd < open_max" |
Geoff Clare |
" - 1" removed in 2 places. |
5.3 |
287 |
|
The first F_SETFD should be F_GETFD |
Geoff Clare |
|
5.3 |
289 |
|
On page 289 you say about execlp() and execvp()
executing shell scripts that "It's up to the implementation as to what shell
it uses." SUS and POSIX require that the script is executed as if by a
standards-conforming "sh" utility. Note that this is another case where
Solaris provides both standards-conforming and non-conforming behaviours. If
a program compiled with Sun's c89 compiler calls execlp() then the shell
used is /usr/xpg4/bin/sh (or I think it was /bin/ksh on older versions of
Solaris). With plain cc (or gcc) it is /bin/sh. |
Geoff Clare |
2nd para. from the bottom: Add the words ", but it must be
standards-conforming" after the last word in the sentence ("uses"). |
5.3 |
290 |
|
"On nearly all systems, the work to deal with the #!
line is done by execvp, not by the shell itself". Perhaps there are some
systems which do handle it inside the exec library functions, but I believe
most systems handle #! inside the kernel itself. |
Geoff Clare |
No change. |
5.8 |
308 |
|
In display_status() you should only use WTERMSIG if
WIFSIGNALED is true. If WIFSTOPPED is true you should use WSTOPSIG to get
the signal number. |
Geoff Clare |
|
5.12 |
318 |
|
You say that when superuser calls setuid() or setgid()
the call "sets both the real and saved values". It sets the effective value
as well. |
Geoff Clare |
Change synopses titles to add ", effective," after "real"
on p. 318 and in Appendix D. |
5.15 |
320 |
|
When nice() returns -1, to tell whether it was an error
you have to set errno to zero before the call and if it returns -1 then
check if errno is non-zero (just like sysconf() and pathconf()). |
Geoff Clare |
Change footnote 13 to read: "Finally fixed in the latest
version of [SUS2002]. You can set errno to zero before the call and then
test it afterwards." |
5.16 |
324 |
|
2nd para. from bottom: "member" |
Michael Kerrisk |
Change to "members". |
5.17.3 |
336 |
|
Incorrect reference to "pthread_func" |
Greg King |
p. 336, 3rd line from top: change "pthread_func" to "thread_func". |
5.17.5 |
348 |
|
You can't use your ec_*() error handling macros inside a pthread_cleanup_push/pthread_cleanup_pop block. SUS3 says "The effect of the
use of return, break, continue, and goto to prematurely leave a code block
described by a pair of pthread_cleanup_push() and pthread_cleanup_pop()
functions calls is undefined." |
Geoff Clare |
|
5.18.2 |
354 |
|
The waitpid() call has &e->ue_result as the second
argument, which is a pointer to ssize_t but waitpid() takes a pointer to
int. |
Geoff Clare |
|
6.2.1 |
362-363 |
|
After the fpathconf() call you should only examine errno
if fpathconf() returned -1. I.e. the "if (errno != 0)" at the top of page
363 should be "if (v == -1 && errno != 0)". |
Geoff Clare |
Code at top of p. 363 changed to: if (v == -1)
if (errno != 0)
EC_FAIL
else
printf("No limit for PIPE_BUF\n");
else
printf("PIPE_BUF = %ld\n", v);
|
6.2 |
371 |
|
You say "the standard says nothing about what file
descriptors pipe will use". It does actually require that they are the two
lowest available. However, this doesn't help as far as the point you are
making is concerned, since the standard doesn't say they have to be in
order. I.e. if 0 and 1 are closed then pipe(pfd) is allowed to set pfd[0] =
1 and pfd[1] = 0. |
Geoff Clare |
At top of p. 371, replace "what file descriptors pipe will
use" with "which end is which". |
7.4.2 |
429 |
|
|
Jim Fathman |
First sentence of last paragraph: Insert the word "no"
before "conflicts." |
|
449 |
|
On page 449, the declarations for mq_timedsend and
mq_timedreceive seem to have
been copied and pasted from their non-timed equivalents on page 448. They
have
the extra timespec parameter, but no separating comma after priority or
priorityp. |
Paul Floyd |
Add the comma. |
7.7.2 |
452 |
|
The second snprintf() uses %d for a pid_t argument. It
needs to cast the pid to long and use %ld. |
Geoff Clare |
|
7.7.2 |
453 |
|
The line (void)mq_unlink(mqname);
should be
if (mq_unlink(mqname) == -1)
so that errno is only examined if mq_unlink() failed. |
Geoff Clare |
|
7.7.3 |
456 |
|
Non-support of POSIX Message Queues: Since you wrote the
book, support for POSIX Message queues has been added (Linux 2.6.6, May
2004). |
Michael Kerrisk |
|
7.9.1 |
461-462 |
|
You say it's okay to pass an int, pointer to struct
semid_ds or an array of unsigned shorts as the fourth semctl() argument
instead of passing a union semun. It isn't okay, because semctl() is a
variable-argument function whose prototype only specifies the types of the
first three arguments. |
Geoff Clare |
p. 461: Delete the start of the sentence on the last line
beginning "Actually, you ...".
p. 462: Delete the rest of that sentence (1st two lines): "type int ...
directly.". |
7.10.1 |
472 |
|
The unlink() should be sem_unlink(). |
Geoff Clare |
In the function SimpleSemRemove, change "unlink" to "sem_unlink". |
7.10.2 |
475 |
|
Non-support of POSIX Process Shared Semaphores: Well,
actually, even at the time you were writing, this support did exist in Linux
2.6. It was added during the 2.5 development series. Of course that would
have been easy to miss if one wasn't closely following Linux development. |
Michael Kerrisk |
2nd para. from bottom, 2nd line: Change "they" to "some
versions". |
7.11.3 |
485 |
|
flockfile() doesn't set file locks! It "locks" a FILE
object in the same sense that pthread_mutex_lock() locks a mutex. I.e. it
prevents other threads (in the same process) from accessing that stdio
stream until the owning thread unlocks it. Its purpose is to allow a
sequence of getc() or putc() calls to be replaced with one flockfile() then
the corresponding sequence of getc_unlocked() or putc_unlocked() calls then
a funlockfile(), thus eliminating all the intermediate unlock+lock
operations done internally by getc() or putc(). |
Geoff Clare |
Delete entire 1st para. on p. 485. |
7.14.1 |
505 |
|
In "The call, sem_open" it should be shm_open. |
Geoff Clare |
In 1st para., change it to "shm_open". |
8.8.4 |
591 |
ndb.c |
... the printed port numbers came out wrong because
display_servent() doesn't convert s_port to host byte order. I.e. the s->s_port
printf argument should be ntohs(s->s_port). |
Geoff Clare |
"s->s_port" changed to "ntohs(s->s_port)" and outputted
ports changed as follows:
change 5120 to 20
change 5120 to 20
change 5376 to 21
change 5376 to 21
change 5632 to 22
change 5632 to 22
change 5888 to 23
change 5888 to 23
change 6400 to 25
change 6400 to 25
change 6912 to 27
change 6912 to 27
change 7424 to 29
change 7424 to 29
change 7936 to 31
change 7936 to 31
|
7.14.3 |
515 |
|
Non-support of POSIX Shared Memories: You say Linux
doesn't support POSIX Shared Memory. This is wrong: Linux has supported
POSIX Shared Memory since kernel 2.4 (glibc 2.2 or later required) -- around
the start of 2001. |
Michael Kerrisk |
Last para. of 7.14.3: Insert "some versions of" before the
word "Linux". |
8.9.5 |
596 |
|
"For inet_pron" |
Geoff Clare |
In 2nd. para from bottom, change it to "inet_pton". |
|
635 |
|
... the comment /* non-zero to set, zero to clear */ for
the siginterrupt() "on" argument is the wrong way round. Non-zero means
system calls will be interrupted, which is equivalent to SA_RESTART being
clear. |
Geoff Clare |
Change the argument name to "flag". Swap "set" and "clear"
in the comment. |
9.5.1 |
639 |
|
3rd para.: The convention of si_code <= 0 for signals
from a process and si_code > 0 for signals from the kernel is only followed
on some systems. It isn't required by the standard and shouldn't be relied
on in portable code. (An example of a system which doesn't follow the
convention is HP-UX, where SI_USER and SI_QUEUE are negative but SI_TIMER,
SI_ASYNCIO and SI_MESGQ are positive.) |
Geoff Clare |
Change "If" to "Usually, if". |
9.5.5 |
646 |
|
"much as pselect adds a time-out to select". ... select
already had a time-out; pselect adds a signal mask. |
Geoff Clare |
Delete the phrase ", much as ... select" |
Ref. |
704 |
|
[STE2003] has a copyright date of 2004. |
Michael Kerrisk |
Change 2003 at end of entry to 2004. Leave "[Ste2003]"
unchanged. |