c - 如何在C中获取mac os的主机名

标签 c

我正在尝试获取我学校 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_PROCARGSname 将需要一个附加参数,即应检索参数的进程 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/

相关文章:

c - 有一个测试卡在无限循环中,你能找到它吗?

c - 如何访问共享内存中的变量

使用 ExitThread 关闭线程 - C

c# - 如何从 .NET 调用 C 库

c - 这段代码中的段错误?

c - C 语言的 super 基本服务器-客户端应用程序

gets() 函数中的 CR 字符

c - 将指针的值赋给静态变量

c - 使用 if 和 swap 语句按升序排列数字

c - MPI - 在障碍后尝试打印广播变量,显示其他一些变量