2014-05-26 :-(
_ 午後
1300 タッチパネルはかく語りき
_ [NetBSD][/bin/echo][コードリーディング]NetBSD /bin/echo を読む
src/bin/echo/echo.c
こう使ったとする。
% echo foo bar baz foo bar baz
コード読む
/* ARGSUSED */ int main(int argc, char *argv[]) { int nflag; setprogname(argv[0]); (void)setlocale(LC_ALL, ""); // getopt 使うまでもないよ! /* This utility may NOT do getopt(3) option parsing. */ if (*++argv && !strcmp(*argv, "-n")) { ++argv; nflag = 1; } else nflag = 0; // argv は以下のとおり // argv[1] : foo // argv[2] : bar // argv[3] : baz while (*argv) { (void)printf("%s", *argv); if (*++argv) (void)putchar(' '); } // 最後に改行を印字 if (nflag == 0) (void)putchar('\n'); fflush(stdout); // fflush の動作を保証するため? if (ferror(stdout)) exit(1); exit(0); /* NOTREACHED */ }
-n オプションの意味
-n Do not print the trailing newline character.
_ [NetBSD][/bin/hostname][コードリーディング]NetBSD /bin/hostname を読む
ソース src/bin/hostname/hostname.c
マニュアル hostname - NetBSD Manual Pages
使用例
% hostname sakura.area51.gr.jp
% hostname -s sakura
コード読む。
main で完結する。
冒頭の変数
char *p, hostname[MAXHOSTNAMELEN + 1];
MAXHOSTNAMELEN は src/sys/sys/param.h に定義されてる。
/* * Machine-independent constants (some used in following include files). * Redefined constants are from POSIX 1003.1 limits file. * * MAXCOMLEN should be >= sizeof(ac_comm) (see <acct.h>) * MAXHOSTNAMELEN should be >= (_POSIX_HOST_NAME_MAX + 1) (see <limits.h>) * MAXLOGNAME should be >= UT_NAMESIZE (see <utmp.h>) */ #include <sys/syslimits.h> #define MAXCOMLEN 16 /* max command name remembered */ #define MAXINTERP PATH_MAX /* max interpreter file name length */ /* DEPRECATED: use LOGIN_NAME_MAX instead. */ #define MAXLOGNAME (LOGIN_NAME_MAX - 1) /* max login name length */ #define NCARGS ARG_MAX /* max bytes for an exec function */ #define NGROUPS NGROUPS_MAX /* max number groups */ #define NOGROUP 65535 /* marker for empty group set member */ #define MAXHOSTNAMELEN 256 /* max hostname size */
おもな処理。ようするに sethostname または gethostname を呼ぶ。
if (*argv) { // ホスト名が指定されている場合はホスト名を設定 if (sethostname(*argv, strlen(*argv))) err(1, "sethostname"); } else { // 指定されてなければ gethostname でホスト名を取得 if (gethostname(hostname, sizeof(hostname))) err(1, "gethostname"); // ヌル文字を入れる hostname[sizeof(hostname) - 1] = '\0'; // -s で呼び出された場合 最初の . を探す。 // そこにヌル文字を突っ込むことで強制的に文字列を終了する。つまりドメイン名を削除 if (sflag && (p = strchr(hostname, '.'))) *p = '\0'; (void)printf("%s\n", hostname); }
hostname は以下のファイルに定義されている。libc です。
src/lib/libc/gen/gethostname.c
int gethostname(name, namelen) char *name; size_t namelen; { int mib[2]; size_t size; _DIAGASSERT(name != NULL); mib[0] = CTL_KERN; mib[1] = KERN_HOSTNAME; size = namelen; // 第 3 引数が非 NULL なので情報を取得 if (sysctl(mib, 2, name, &size, NULL, 0) == -1) return (-1); return (0); }
sethostname も同じところにある。
src/lib/libc/gen/sethostname.c
int sethostname(name, namelen) const char *name; size_t namelen; { int mib[2]; _DIAGASSERT(name != NULL); mib[0] = CTL_KERN; mib[1] = KERN_HOSTNAME; // 第 3 引数が NULL なので情報を設定 if (sysctl(mib, 2, NULL, NULL, name, namelen) == -1) return (-1); return (0); }
双方とも sysctl を呼んでいる。
sysctl のマニュアル。
- sysctl(3) - NetBSD Manual Pages プログラマ向け
- sysctl(7) - NetBSD Manual Pages システム管理者向け
sysctl(3) より。sysctl の第 3 引数が NULL ならば設定。そうでなければ情報を取得。
The information is copied into the buffer specified by oldp. The size of the buffer is given by the location specified by oldlenp before the call, and that location gives the amount of data copied after a successful call. If the amount of data available is greater than the size of the buffer supplied, the call supplies as much data as fits in the buffer provided and returns with the error code ENOMEM. If the old value is not desired, oldp and oldlenp should be set to NULL.
sysctl(7) より。CTL_KERN と KERN_HOSTNAME を指定すると kern.hostname が使われる。
Name Constant Next level names Description kern CTL_KERN <sys/sysctl.h> High kernel limits
kern.hostname (KERN_HOSTNAME) Get or set the hostname(1).