我正在尝试获取学校Mac OS的主机名。我不能使用Mac手册页第3节中的gethostname()
,而不是第2节中的内容。是否有不使用gethostname()
的另一种获取主机名的方法?只允许在libc
中使用man 2 section
函数。
最佳答案
gethostname
只是一个sysctl
,而sysctl
只是一个syscall
。
syscall在手册的第2节中(按定义)。
因此,抓住您最喜欢的反汇编程序(如果没有,则为otool -tV
),在nm
中的/usr/lib/system
库中找出导出_gethostname
和_sysctl
的库,然后开始工作(或查找源代码: P)。
下面,我使用gethostname
重新实现sysctl
,并使用sysctl
重新实现syscall
:
#include <sys/syscall.h> // SYS_sysctl
#include <sys/sysctl.h> // CTL_KERN, KERN_HOSTNAME
#include <unistd.h> // syscall
int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen)
{
return syscall(SYS_sysctl, name, namelen, oldp, oldlenp, newp, newlen);
}
int gethostname(char *buf, size_t buflen)
{
int name[] = { CTL_KERN, KERN_HOSTNAME };
size_t namelen = 2;
return sysctl(name, namelen, buf, &buflen, NULL, 0);
}
int puts(const char *s)
{
// left as an exercise to the reader ;)
}
int main(void)
{
#define BUFSIZE 256
char buf[BUFSIZE];
size_t buflen = BUFSIZE;
if(gethostname(buf, buflen) == 0)
{
puts(buf);
}
return 0;
}
sysctl
的实现不是太复杂。您实际上只是在其他参数前面打了SYS_sysctl
(来自sys/syscall.h
),然后将它们全部传递给syscall
。要了解
gethostname
的实现,您必须知道sysctl
的工作方式:oldp
是查询值的存储位置。newp
是将从中读取新值的位置。由于我们未设置任何新值,因此此处为NULL
。name
或多或少是sysctl
的实际参数列表,其内容取决于要查询的实际sysctl
。CTL_KERN
表示我们需要内核提供的东西。KERN_HOSTNAME
表示我们要检索主机名。而且由于
KERN_HOSTNAME
不接受任何参数,因此仅此而已。仅出于演示目的,如果您调用了
KERN_PROCARGS
,则name
将需要一个附加参数,即应检索其参数的进程ID。在这种情况下,
name
将如下所示:int name[] = { CTL_KERN, KERN_PROCARGS, pid };
和
namelen
必须相应地设置为3
。现在,在上述实现中,我已经使用了
puts
,显然您是不允许这样做的,但是我相信您可以弄清楚如何重新实现strlen
并使用write
syscall。 ;)关于c - 如何在C中获取Mac OS的主机名,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39146754/