2016-08-25 2 views
-2

Я пытаюсь получить имя хоста моей школы mac os. Я не могу использовать gethostname(), как это описано в разделе 3 man-страниц моих школьных макинтошей, а не в разделе 2. Есть ли другой способ получить имя хоста, не используя gethostname()? Мне разрешено использовать только libc функции в man 2 section.Как получить имя хоста mac os в C

+2

first: http://linux.die.net/man/2/gethostname, second: почему это важно, какой раздел страниц руководства? – KevinDTimm

+1

Почему раздел справочной страницы о том, что 'gethostname()' задокументирован в проблеме? (в BSD-производных системах, в разделе 2 только системные вызовы, а библиотечные функции - в разделе 3)? – dhke

+0

обходное решение: 'f = popen (" hostname ")' then read 'f' –

ответ

-1

gethostname всего лишь sysctl, а sysctl - всего лишь syscall.
И системные вызовы (по определению) в разделе 2 руководства.

Так захватить ваш любимый дизассемблер (или otool -tV, если у вас нет), nm библиотеки в /usr/lib/system, чтобы выяснить, какие из них экспортировать _gethostname и _sysctl и заставить работать (или искать источник: P).

Ниже я вновь реализованы с использованием gethostnamesysctl и 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 потребовался бы дополнительный аргумент, а именно идентификатор процесса, из которого должны быть получены аргументы.
    В этом случае name будет выглядеть следующим образом:

    int name[] = { CTL_KERN, KERN_PROCARGS, pid }; 
    

    и namelen должны быть установлены в 3 соответственно.

Сейчас в вышеприведенном реализации я использовал puts, что вы явно не разрешено делать, но я надеюсь, что вы можете выяснить, как повторно реализовать strlen и использовать write системный вызов с тем , ;)

+0

Мы не являемся сайтом «сделать мою домашнюю работу». Предоставление намеков должно было хватить, публикация всего кода не помогла бы ОП улучшить свои исследования или навыки кодирования. – Olaf

Смежные вопросы