uname -a は冗長か?

わりとどうでもいいネタ。

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_KERNKERN_OSTYPE, KERN_HOSTNAME, KERN_OSREREASE, KERN_VERSIONCTL_HWHW_MACHINE の値 (kernel state) を取り出している。

sysctl(3) は、3なのでライブラリだけれど、src/lib/libc/gen/sysctl.c を見ると、CTL_USER以外の場合、__sysctl システムコールを呼ぶのとほぼ同じ。

システムコールの仕組みの話は飛ばして、カーネル側:

CTL_KERN のあたりの値は src/sys/kern/init_sysctl_base.cSYSCTL_SETUP() で用意されていて、ostype, hostname, osrelease, version といったグローバル変数(!)と紐づいている。

これらのうち、hostnamesrc/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 固定で ostypeversion に使われている。つまり 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 に相当する文字列が含まれていない。どちらがいいとは言えないが。