わりとどうでもいいネタ。
uname -a
を実行すると、
$ uname -a
NetBSD xxx.ceres.ne.jp 9.0_STABLE NetBSD 9.0_STABLE (GENERIC) #0: Fri Apr 3
02:59:31 JST 2020 est@xxx.ceres.ne.jp:/xxx/amd64/obj/sys/arch/amd64/compile
/GENERIC amd64
NetBSD とか 9.0_STABLE とか、2回出てきて冗長な気がする。
NetBSD が悪いわけではなく、BSD 系全般(とか Darwin とか)こんな感じだったはずだが(※)。
NetBSD の uname -a
(4.4BSD 由来なので他も大体同じ)は、src/usr.bin/uname/uname.c
を見ると、uname(3) を使って struct utsname u
を取り出して、u.sysname, u.nodename, u.release, u.version, u.machine
の順に表示している。
uname(3) は、src/lib/libc/gen/uname.c
を見ると、sysctl(3) で CTL_KERN
の KERN_OSTYPE, KERN_HOSTNAME, KERN_OSREREASE, KERN_VERSION
や CTL_HW
の HW_MACHINE
の値 (kernel state) を取り出している。
sysctl(3) は、3なのでライブラリだけれど、src/lib/libc/gen/sysctl.c
を見ると、CTL_USER
以外の場合、__sysctl
システムコールを呼ぶのとほぼ同じ。
システムコールの仕組みの話は飛ばして、カーネル側:
CTL_KERN
のあたりの値は src/sys/kern/init_sysctl_base.c
の SYSCTL_SETUP()
で用意されていて、ostype, hostname, osrelease, version
といったグローバル変数(!)と紐づいている。
これらのうち、hostname
は src/sys/kern/kern_sysctl.c
で宣言されている。
/*
* Attributes stored in the kernel.
*/
char hostname[MAXHOSTNAMELEN];
int hostnamelen;
他はソースツリー上になくて、カーネルのコンパイル時に作られる vers.c
で宣言されている。
const char ostype[] = "NetBSD";
const char osrelease[] = "9.0_STABLE";
const char sccs[] = ...
const char version[] = "NetBSD 9.0_STABLE (GENERIC) #0: ...";
このファイルは src/sys/conf/newvers.sh
から作られていて、
...
osrelcmd=${cwd}/osrelease.sh
ost="NetBSD"
osr=$(sh $osrelcmd)
fullversion="${ost} ${osr} (${id})${reproversion}\n"
...
fullversion_source="$(printf "%b" "${fullversion}" | source_lines)"
...
cat << _EOF > vers.c
...
const char ostype[] = "${ost}";
const char osrelease[] = "${osr}";
const char sccs[] = "@(#)" ${fullversion_source};
const char version[] = ${fullversion_source};
...
シェル変数 ${ost}
は NetBSD 固定で ostype
と version
に使われている。つまり uname -a
で2回出てくる NetBSD は両方ともこの newvers.sh
に書かれた ost="NetBSD"
の文字列が巡り巡って表示されているわけである。(source_lines
はC言語ソースのための特殊文字のエスケープ処理なのでここでは気にしない。)
シェル変数 ${osr}
は src/sys/conf/osrelease.sh
で作られているが、これは <sys/param.h>
の #define __NetBSD_Version__ ...
の後のコメントを拾っている。
何にせよ、出どころが同じなので、力強く「冗長である」と言ってよさそう。
……別に何も困るわけではないのですが。
※Linux, Solaris, AIX などの場合は、version (uname -v
) に ostype や osrelease に相当する文字列が含まれていない。どちらがいいとは言えないが。