我正在尝试获取我学校 mac 操作系统的主机名。我无法使用 gethostname()
,因为它位于我学校 Mac 手册页的第 3 部分,而不是第 2 部分。是否有另一种获取主机名的方法,而不使用 gethostname( )
?我只允许在 man 2 部分
中使用 libc
函数。
最佳答案
gethostname
只是一个 sysctl
,而 sysctl
只是一个 syscall
。
系统调用(根据定义)位于手册的第 2 节中。
所以,捕获你最喜欢的反汇编器(或者otool -tV
,如果你没有的话),nm
/usr/lib/system
中的库找出哪些导出 _gethostname
和 _sysctl
,然后开始工作(或查找源代码:P)。
下面我使用 sysctl
重新实现了 gethostname
,并使用 syscall
重新实现了 sysctl
:
#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
即可。 p>
要了解 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
系统调用。 ;)
关于c - 如何在C中获取mac os的主机名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39146754/