我有一个程序,其系统调用getpwnam()在运行时失败。为了调试此问题,我决定单独使用此代码运行getpwnam()(它来自论坛):

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

int main(int argc, char **argv)
{
struct passwd *pw;

if (argc != 2) {
    printf("usage: %s username\n", argv[0]);
    exit(0);
}
pw = getpwnam(argv[1]);
if (pw == NULL)
    printf("getpwnam failed\n");
else
    printf("home dir = %s\n", pw->pw_dir);
    exit(0);
}

奇怪的是,这似乎取决于libnss_compat-2.3.5.so的存在:

与libnss_compat一起使用:
./pwnam roothome dir = /root
(无libnss_compat):
./pwnam rootgetpwnam failed
所以我的问题是;为什么getpwnam()取决于libnss_compat*.so?我通过nm -D命令发现libc-2.3.5.so是提供getpwnam()的库。
readelf -d向我显示libc反过来仅取决于ld.so.1。反过来,这无关紧要。那么,为什么libnss_compat会产生影响呢?

谢谢大家的帮助!!

最佳答案

NSS是名称服务交换机,它是一个可以在各种来源(传统密码文件,Network Information Service和LDAP)中查找用户信息的库。 getpwnam可以在libc中定义,但是它将在运行时加载实际的NSS库。在libc里面,我发现

$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep libnss
libnss_
libnss_
libnss_%s.so.%d.%d

最后一行显然是snprintf的格式字符串,用于构造要使用dlopen加载的实际实现库的名称。使用/etc/nsswitch.conf确定实现。

编辑我在Glibc源代码中的the library is loaded中找到了这个地方。不再(不再使用)snprintf,但是原理仍然相同。

10-05 19:48