课后习题存在错误,在官网勘误表中更正如下:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>

int
main(int argc, char *argv[])
{
    if (argc != 3 || strcmp(argv[1], "--help") == 0) {
        fprintf(stderr, "Usage: %s uid1 uid2\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    printf("%s %s\n", getpwuid(atoi(argv[1]))->pw_name,
                      getpwuid(atoi(argv[2]))->pw_name);

    exit(EXIT_SUCCESS);
}

可重入和非可重入函数

可重入函数:函数由两条或者多条线程调用时,即使是交叉执行,其效果也与各线程以任意顺序调用时一致。

作者官网的解释:
Explanation:
The exercise was intended to demonstrate the nonreentrant nature of getpwnam() (and related functions, such as getpwuid()), but the experiment I proposed to do so was wrong. (And unfortunately it looks as though I didn't test this exact example.) As René Thomsen pointed out, the code of the original exercise wouldn't yield the results described in the text "since after each argument a copy of the value in the passwd structure for pw_uid is passed, and since this a direct value (not a reference) there should be no trouble [with] the next call overwriting this value, since it still has the copy."
在本书21章21.1.2节同样有介绍,更新全局变量或静态数据结构的函数可能是不可重入的。
函数crypt() getpwnam() 等也是不可重入函数,原因是他们使用了静态分配的内存来返回信息.
SUSv3为该组函数定义了与之等价的一组可冲入函数getpwnam_r() getpwuid_r() getgrnam_r() getgrgid_t().参数包括passwd或group结构以及缓冲区.
可以通过man getpwnam_r man getgrnam_r查看.