真の UNIX 標準規格 System V Interface Definition (SVID) について

## はじめに

POSIX のコマンド一覧を見てやけに少ないなと思ったことはないでしょうか？例えば `useradd` がないのでユーザーが作れませんし`crontab` はあるのに `cron` がないと中途半端です。重要なものがいくつも欠けおり、あれだけのコマンドでは到底 Unix を使うことができません。実は「Unix に実装すべき最低限の仕様」を定義した標準規格は他にありました。それが UNIX をこの世に生み出した AT&T 自身による標準規格 [System V Interface Definition](https://ja.wikipedia.org/wiki/System_V_Interface_Definition) (SVID) です。この記事は POSIX に敗れて消えてしまったもう一つの UNIX 標準規格 SVID ・・・のコマンドの話です。（私の知識不足により C 言語インターフェースの話は含まれません。）

## SVID と POSIX の歴史

SVID は POSIX よりも早く標準規格を発表しています。ただし SVID1 登場の一年前に /usr/group によって /usr/groupd Standard という標準規格が発表されています。/usr/groupd Standard には IEEE や ISO も貢献しており、これが POSIX の基礎となっているようです。

- 1981: /usr/group 標準化委員会で標準化作業が始まる（のちに POSIX の基礎となる）
- 1984: /usr/group Standard 完成（System III ベース + BSD）
- 1985: SVID1 (System V Release 2 対応）
- 1986: SVID2 (System V Release 3 対応)
- 1988: **POSIX.1 (IEEE Std 1003.1-1988)**
- 1989: SVID3 (System V Release 4.0 対応) 
- 1992: **POSIX.2 (IEEE Std 1003.2-1992)**
- 1995: SVID4: XPG4 と POSIX 1003.1-1990 に準拠するように更新
- 2001: **POSIX.1-2001 (IEEE Std 1003.1-2001)**
  - POSIX.2 が統合。その他の標準仕様が同期され現在の形となる
- 2008: **POSIX.1-2008 (IEEE Std 1003.1-2008)**
  - 最新の POSIX は POSIX.1-2008 2017 edition （バグ修正版）
- 202x: **POSIX.1-202x** (2022 年後期予定）

もう少し詳細な歴史や各仕様へのリンク先は「[POSIXとUnix関連の標準規格と歴史年表 (IEEE, SVID, XPG, SUS)](https://qiita.com/ko1nksm/items/c79f802742e0c3be066d)」を参照してください。

## UNIX と POSIX の方向性の違い

SVID1 が登場した頃、すでに Unix は System V 系と BSD 系に分かれていました。4BSD がリリースされた頃です（ちなみに Linux は誕生しておらず GNU プロジェクトは開始したばかりです）。System V Interface Definition はその名の通り、System V という OS を定義するものであり BSD の事情は（基本的に？）考慮されていません。一方 POSIX は Portable Operating System Interface （移植可能な OS のインターフェース）の略からも分かるように System V と BSD など複数の OS でソフトウェアが移植可能になるように考慮されています。その方針の違いが標準仕様の内容にも現れています。

SVID は Unix (System V)として必要だと考えたものをすべて定義しました。一方 POSIX は複数の Unix (System V と BSD) で共通で動く最低限のものだけを抜き出して定義しました。AT&T が考えた System V のコマンドは、System V と BSD の両方で動くコマンドよりも多いです。つまり **POSIX は Unix 系 OS が持っていなければならないとするすべてのコマンドを定義しているわけではない**ということです。（C 言語用インターフェースも同じだと思いますが調べていません）。

- SVID ・・・ Unix (System V) が**持つべき**最低限の仕様
- POSIX ・・・ Unix (System V、BSD 等) で**共通して使える**最低限の仕様

似たような文章ですが、この 2 つは POSIX の方が仕様が少ないと言うだけではなく異なる結果をもたらします。SVID の場合は必要があると思ったら新しい仕様を追加することが比較的簡単に行うことができます。時代に合わせて新しい機能コマンドを追加していくことができますし、正確で漏れがない仕様にすることで System V を実装する環境の間で高い移植性を実現することができたでしょう。しかし POSIX の場合はそうはいきません。各環境でバラバラに実装されているものの中から共通で使えるものだけを仕様にするという方針なので標準化される内容は少なく、基本的に仕様が作られるよりも実装の開発が先行します。（POSIX 準拠の新しい実装を開発するプロジェクトは別です。そのようなプロジェクトとして [toybox](https://landley.net/toybox/) があります。）

POSIX は実際の実装の中から共通分母を取り出して作られたものなので、POSIX が作られた時点では、各 OS ベンダーが POSIX に準拠するのは簡単だったでしょう（互換性がない部分はそもそも仕様に含まないので当然ですね）。それが当時 POSIX が支持された理由の一つだと思います。また POSIX は厳格なものでも絶対的なものでもなく、POSIX の定めた仕様に従うような強制はしませんでした。POSIX は未定義の部分が多く完全なものにはなっていませんが、それは将来への拡張が行えるようにするための意図的なものです。実装は POSIX に準拠しつつも自由に拡張を行うことができます。OS ベンダーに自由に拡張する余地（それはロックインに利用可能です）が与えられたことも POSIX が支持された理由の一つでしょう。

しかしこの方針は POSIX 主導で仕様が作られることはないということを意味します（その例外として POSIX 主導で仕様が作られた [pax](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html) コマンドがありますが現状を見れば分かる通り `tar` コマンドを置き換えることはできませんでした）。そのため POSIX 標準化時点ですでに互換性がないものや新しく登場するコマンドやオプション（例 `route` コマンドや `date` コマンドのオプション）は実装者のさじ加減で決まるため互換性が低くなってしていまいました。すべての実装で同じように実装されなければ POSIX の仕様に取り入れられることはありませんし、[古いナンセンスな仕様](https://en.wikipedia.org/wiki/POSIX#512-_vs_1024-byte_blocks)も残り続けます。そして POSIX は 30 年の間、ほとんど仕様が改定されず、新たな互換性の問題が発生するという残念な結果になっています。（とは言えオープンソース文化が発達したおかげで被害は最小限で済んでいます。今はそれぞれのベンダーが新しいコマンドを作る必要はなくに単に移植するだけです。）

少し話がそれましたが、SVID は [Unix 戦争](https://en.wikipedia.org/wiki/Unix_wars)に負けはしましたが、Unix を誕生させたのは AT&T です。Unix というものを一番正しく理解していたのは AT&T と考えても間違いないでしょう。また BSD との移植性を考えることなく、Unix の正統系列である System V に必要なコマンドを定義しました。つまり SVID こそが真の Unix の標準規格であると考えても過言ではないと思います。**（異論あり。[コメント](#comments)参照）**

ということで、本来 Unix という OS が持っていなければならなかったコマンドとはなにか？というのを過去の SVID 標準規格を元に POSIX 標準規格と比較しながら見ていきたいと思います。

## コマンド一覧

- `*` は POSIX で標準化されているコマンドです
- `+` は 過去に POSIX で標準化されていたが現在は削除されているコマンドです

コマンドの意味は [System V Interface Definition Fourth Edition](http://www.sco.com/developers/devspecs/) の Volume 2 または Volume 3 を参照してください。また POSIX で削除されたコマンドの一部は [POSIX Rationale for Shell & Utilities](https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap04.html) でその理由を知ることができます。

### BASIC COMMANDS AND UTILITIES

```
ar *        defadm      kill *      pfmt        strchg
awk *       df *        lfmt        pg +        strconf
banner +    diff3       line +      pr *        sum +
basename *  diff *      listusers   printf *    tail *
cal *       dirname *   ln *        ps *        tee *
calendar +  du *        ls *        pwd *       test *
cat *       echo *      mail +      red +       touch *
cd *        ed *        mkdir *     rm *        tr *
chmod *     expr *      more *      rmail       true *
cmp *       false *     mv *        rmdir *     umask *
col +       file *      nawk        rsh         uname *
comm *      find *      nl *        sed *       uncompress *
compress *  fmt         nohup *     sh *        uniq *
cp *        gettxt      pack +      sleep *     unpack +
cpio +      grep *      page        sort *      wait *
ctags *     head *      paste *     spell +     wc *
cut *       iconv *     pcat +      split *     zcat *
date *      jsh
```

基本的なコマンドで見たことがあるようなコマンドばかりです。殆どが POSIX でも標準化されています。OS に依存するものではないため他の環境でも容易に同じように動作させることができたのだと思います。

### ADVANCED COMMANDS AND UTILITIES

```
at *        cu +        lp *        su          uustat *
atq         dd *        lpstat +    tabs *      uuto +
atrm        dircmp +    mailx *     tar +       uux *
batch *     ex *        mesg *      tty *       vi *
cancel +    gencat *    newgrp *    uucp *      wall +
chgrp *     groups      news        uudecode *  who *
chown *     iconv *     od *        uuencode *  write *
cron        id *        passwd      uulog +
crontab *   join *      priocntl    uuname +
csplit *    logname *   stty *      uupick +
```

こちらも見たことがあるようなコマンドが多く POSIX でも標準化されています。`atq` や `atrm` や `cron` などあって然るべきもの本家にはちゃんと定義されていたということがわかります。

### ADMINISTERED SYSTEMS COMMANDS AND UTILITIES

```
acctcms     fdp         lastlogin   pkgparam    setmnt
acctcom     ffile       link *      pkgproto    setuname
acctcon1    fimage      logins      pkgrm       shutacct
acctcon2    fmtmsg      logkeeper   pkgtrans    srchtxt
acctdisk    fsck        migration   prctmp      startup
acctmerg    fsdb        mkfs        prdaily     sync
accton      fstyp       mkmsgs      prtacct     sysdef
acctprc1    fuser *     mknod       prtconf     timex
acctprc2    fwtmp       modadmin    pwck        turnacct
acctwtmp    groupadd    monacct     removef     umount
backup      groupdel    mount       restore     unlink *
bkexcept    groupmod    msgalert    rsnotify    urestore
bkhistory   grpck       msglog      rsoper      ursstatus
bkoper      incfile     msgrpt      rsstat      useradd
bkreg       init        mvdir       runacct     userdel
bkstatus    installf    nice *      sa1         usermod
chargefee   ipcrm *     pkgadd      sa2         volcopy
ckpacct     ipcs *      pkgask      sacadm      whodo
devnm       killall     pkgchk      sadc        wtmpfix
diskusg     labelit     pkginfo     sadp        zdump
dodisk      last        pkgmk       sar         zic
fdisk
```

システム管理系コマンドです。聞いたことがないようなものが結構ありますが、ディスク管理の `fdisk` や `mkfs` 、パーティションの `mount` や `unmount`、ユーザー管理の `useradd` や `groupadd` など、POSIX では標準化されていませんが、通常の利用でなくはならないコマンドもいくつかあります。`pkg*` はパッケージ管理ツールのようですね。こういったコマンドも SVID ではちゃんと定義されていたということがわかります。

### AUDITING EXTENSION COMMANDS AND UTILITIES

```
auditcnv    auditlog    auditoff    auditrpt    auditset
auditfltr   auditmap    auditon
```

監査のためのコマンドのようです。知らないコマンドばかりですが個人的にこういったコマンドを使ったことがないので、よく知られているコマンドかどうか判断できません。しかしこういった監査のコマンドも Unix の機能として考えられていたということがわかります。

### ENHANCED SECURITY EXTENSION COMMANDS AND UTILITIES

```
admalloc    defsak      getacl      lvlprt      setacl  
adminrole   devattr     getdev      mailcheck   tcpio
adminuser   devstat     lvldelete   mldmode     tfadmin
chlvl       filepriv    lvlname     putdev
```

これもよく知らないコマンドばかりですが、名前からすると `setacl` / `getacl` はそのまんま ACL 関連のコマンドでしょう。Unix はもう少しセキュリティ関連の拡張機能を備えているべきだったということでしょう。

### REMOTE SERVICES COMMANDS AND UTILITIES

```
chkey       keyserv     rpcinfo     dfmounts    newkey
share       dfshares    rpcbind     unshare     keylogin
rpcgen
```

こちらもよくわかりませんが、かろうじて `rpc*` は RPC 関連のなにかだというのはわかります。同じコマンドかどうかはわかりませんが macOS でも使えるようです。つまり Unix はリモートサービスのコマンドも備えています。

### SOFTWARE DEVELOPMENT COMMANDS AND UTILITIES

```
admin *     delta *     lint +      rmdel *     tsort *
as          dis         lorder      sact *      unget *
cc +        env *       m4 *        size        val *
cflow *     gcore       make *      strip *     what *
chroot +    get *       nm *        time *      xargs　*
cxref *     ld          prof        truss       yacc *
debug       lex *       prs *
```

久々に見覚えがあるコマンドが登場しました。ソフトウェア開発用のコマンドですね。`xargs` は ADVANCED COMMANDS AND UTILITIES あたりでも良いような気がしますが、開発用コマンドとしての位置づけだったようです。`tsort` (topological sort) は `sort` の一種として考えられるかもしれないけど使い方難しいだろう（というか使ったことありません）と思っていたのですが、開発用コマンドとして扱われているというのであれば納得です。

### TERMINAL INTERFACE COMMANDS AND UTILITIES

```
captoinfo   clear       infocmp     tic         tput *
```

ターミナル関連のコマンドです。`tput` は結構おなじみのコマンドですが、個人的には現実的にメリットが小さく逆に移植性が下がると判断してるので、あえて使わないことにしていたりします。

### REMOTE ADMINISTRATION COMMANDS AND UTILITIES

```
catreq      catsend     distauth    remtab      distrpt
pkgcat      pkgdel      distconf    pkgreq      pkgsend
pkgtrk      pkgput      remalias    remclean    remkill
remadmin    remop       remstat
```

さてまたよくわからないコマンドだらけですが、どうやらリモートのシステム管理を行うためのコマンドのようですね。下位で使うネットワークプロトコルはよくわかりませんが、サーバーに接続できている状態でそのサーバーを管理するということはできたようです。

## POSIX のみで標準化されているコマンド

今度は逆に POSIX では標準化されているけど SVID では標準化されていないコマンドです。標準化されなかっただけで実際の環境にはインストールされていたのではないかと思っていますが当時のことはよくわかりません。シェルで実装すべきシェルビルトインと、POSIX が追加しすぐに削除される運命にある Batch Utilities は省いています。

| Command   | First appeared           |     | Command  | First appeared           |
| --------- | ------------------------ | --- | -------- | ------------------------ |
| asa       | 1983 System V            |     | man      | 1972 Version 2 AT&T UNIX |
| bc        | 1975 Version 6 AT&T UNIX |     | mkfifo   | 1994 4.4BSD ?            |
| cksum     | 1994 4.4BSD ?            |     | patch    | 1986 4.3BSD              |
| expand    | 1979 3BSD                |     | pathchk  | ?                        |
| fold      | 1978 1BSD                |     | pax      | 1994 4.4BSD ?            |
| fort77    | 1992 XPG4                |     | renice   | 1980 4BSD                |
| getconf   | ?                        |     | sccs     | 1986 4.3BSD              |
| locale    | ?                        |     | strings  | 1979 2BSD                |
| localedef | ?                        |     | talk     | 1983 4.2BSD              |
| logger    | 1986 4.3BSD              |     | unexpand | 1979 3BSD                |

First appeared は [wikipedia の List of Unix commands](https://en.wikipedia.org/wiki/List_of_Unix_commands) から取ってきています。ほとんどが BSD 由来のコマンドとであることがわかります。SVID にも BSD 由来のコマンド（例 `vi`） がいくつかあるので SVID がわざと BSD コマンドを省いていたということにはならないと思います。ただ POSIX では SVID で標準化されてないコマンドでも、実際の環境にはほぼ入っているという理由でこれらも含めたのではないでしょうか。「Unix が持つべきコマンドか」という観点で選んだ SVID と「移植性があるコマンドか？」という観点で選んだ POSIX の違いです。

## SVID で定義されたコマンドは必要十分なのか？

SVID にはネットワークに関するコマンド（`ifconfig` や `route` コマンド等）がありません。それは必要ないと思っていたからではなくタイミングの問題だと思っています。ネットワーク通信をするのに必須なソケット API は 1983 年 4.2BSD で実装されました。また `ifconfig` や `route` コマンドは 4.2BSD に含まれています。一方 AT&T の Unix では BSD のソケット API がベンダーの手によって System III (1982) に移植されていたようですが、System V Release 4 (1989) までは搭載されず、代わりに AT&T で開発した [STREAMS](https://ja.wikipedia.org/wiki/STREAMS) の方を推奨していたようです。おそらくこのせいでネットワーク関連のコマンドが SVID では標準化が追いつかなかったのだと思います。

[The Design and Implementation of the 4.4BSD Operating System](https://docs.freebsd.org/en/books/design-44bsd) より

> Another benefit is that the new interface is highly portable. Shortly after a test release was available from Berkeley, the socket interface had been ported to System III by a UNIX vendor (although AT&T did not support the socket interface until the release of System V Release 4, deciding instead to use the Eighth Edition stream mechanism). The socket interface was also ported to run in many Ethernet boards by vendors, such as Excelan and Interlan, that were selling into the PC market, where the machines were too small to run networking in the main processor. More recently, the socket interface was used as the basis for Microsoft’s Winsock networking interface for Windows.

もう一つの例としては `sudo` コマンドがあります。このコマンドはセキュリティをより現実的なものとするために必須と言っても良いもので実際に広く利用されています（例外として OpenBSD ではよりセキュリティが強化された `doas` が使われています）。`su` コマンドは SVID で標準化されていますが `sudo` コマンドはありません。その理由は `sudo` がいつ作られたか？を調べることでわかります。公式サイトの [A Brief History of Sudo](https://www.sudo.ws/history.html) によると `sudo` が作られたのは 1980 年頃らしいですが、一般公開（ニュースグループに投稿）されたのは 1985 年 12 月です。最初の SVID1 が作られたは 1985 年の春ですので到底間に合うわけがありません。最後の SVID4 が登場する 1995 年までの間に System V に移植された可能性はありますが、リリースしたばかりですしその後 sudoers 形式の強化を含む修正が行われており SVID に含めるまでもないと判断しても不思議ではないでしょう。あとどうでもいいんですけど sudo の公式サイト始めて見たんですけど、須藤さんのマスコットって食パンのきぐるみなんですね。なんか某ナシ型のきぐるみとコラボしたら面白いんじゃないかなと・・・いやなんでもないです。

それから**コマンドが不十分なのは POSIX も同じです。30 年前に作られてからほとんど追加が行われていないので、現在の常識では必須と言えるようなものはコマンドされていません**。というのを付け加えておきます。

## さいごに

ということで AT&T が考えた「Unix に必要なコマンドとはなにか？」という話でした。SVID には POSIX で規定されているものよりも遥かに多くのコマンドが定義されていたということがわかります。

POSIX は SVID に比べて多くのコマンドが足りません。もちろんこれは POSIX が劣っているという意味ではありません。単に方針の違いで System V と BSD で移植性がなかったから、もしくは POSIX で定義すべきようなコマンドではなかったという理由で定義されなかったと言うだけのことです。例えばライブラリやデータベース、ミドルウェアのようなものは OS とのインターフェースではないので最初から POSIX の対象外です。POSIX には Unix に必要なコマンド（もしくはソフトウェア開発に必要なコマンド）がすべて定義されてないという事実から言えることは **POSIX で規定されているコマンドだけを使ってソフトウェアを開発するのはベストプラクティスではない**ということ。はっきりわかんだね。

[POSIX - Scope](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap01.html)

> The following areas are outside of the scope of POSIX.1-2017:
> 
> - Graphics interfaces
> - Database management system interfaces
> - Record I/O considerations
> - Object or binary code portability
> - System configuration and resource availability
> 
> POSIX.1-2017 describes the external characteristics and facilities that are of importance to application developers, rather than the internal construction techniques employed to achieve these capabilities. Special emphasis is placed on those functions and facilities that are needed in a wide variety of commercial applications.

またもう一つ重要なのは POSIX が規定しているのは「移植性がないコマンドの中からの抜粋」であるということです。例えば `git` や `jq` などの実装しているベンダーが一つしか無いものは POSIX では規定されません（規定する意味がない）。実装しているベンダーが一つしか無いのにいったい何を見て「どこでも同じように動く」オプションを羅列すれば良いのでしょうか？すべてのオプションを羅列すれば良いのでしょうか？

例えば `wget` コマンドは元々 GNU が開発したコマンドですが、今は BusyBox も実装しています（他にも ToyBox が実装していますがまだ開発中です）。もし GNU だけが開発している状態であれば、すべての機能がどこでも同じように動くのは明らかですから、これを POSIX で標準化する意味はありません。しかし実装が 3 つにもなれば特定の実装でしか動かないオプションもあるでしょう。そういう段階になれば「共通で使えるオプション」を標準化する意味が生まれます。POSIX で標準化されるというのはこういう事です。

SVID は Unix に必要なコマンドが記載されていますが POSIX はそうではありません。POSIX には複数のベンダーで共通しているコマンドが記載されています。と言えば聞こえは良いですが、実際には複数のベンダーが同じ名前でコマンドを実装しており移植性に問題があるからこそ記載されているのです。つまり **POSIX コマンドは「どこでも同じように動くコマンド」ではなくて逆に「どこでも同じようには動かないコマンド」** なのです。これだけははっきりと真実を伝えたかった。