わりとどうでもいいネタ。
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 に相当する文字列が含まれていない。どちらがいいとは言えないが。