sleepの歴史探訪

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">sleepコマンドの引数には&quot;sleep 0.5&quot;のように整数だけではなく浮動小数点数を指定できるのは比較的有名。しかし、複数引数を与えるとそれらの合計値だけ待つという謎機能があるのはあまり知られていない。たとえば&quot;sleep 1 2 3&quot;だと6秒待つ</p>&mdash; sat🦥 (@satoru_takeuchi) <a href="https://twitter.com/satoru_takeuchi/status/1281773665550364672?ref_src=twsrc%5Etfw">July 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">GNU 拡張みたいですよ<a href="https://t.co/J6AnzurLxA">https://t.co/J6AnzurLxA</a>)</p>&mdash; Kaz Nishimura (@kazssym) <a href="https://twitter.com/kazssym/status/1281784478101204993?ref_src=twsrc%5Etfw">July 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">括弧が泣き別れた これならどうだ<a href="https://t.co/07AumUMTIQ">https://t.co/07AumUMTIQ</a></p>&mdash; Kaz Nishimura (@kazssym) <a href="https://twitter.com/kazssym/status/1281785021863321600?ref_src=twsrc%5Etfw">July 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ほほぉ・・・ちょっとソースコードを確認してみよう。もしかすると、こういう仕様になった経緯が見つかるかもしれない！

# TL;DR (要約)
- sleepコマンドは、従来秒数指定しかできなかった。（時分秒指定も無し）。
- coreutilsで実装する段階で、時分秒指定と同時に、複数指定で合算でスリープするようになった(1992年)
- 浮動小数指定もできるようになった(1999年）
- BSD系では現状まだ、秒数指定のまま。

# 過去の歴史を手繰ってみる

まずは、wikipediaで経緯を確認してみよう。

https://en.wikipedia.org/wiki/Sleep_(command)

そして、その実装はcoreutilsの中に書かれている、こちらか……

https://github.com/coreutils/coreutils/blob/master/src/sleep.c

これのhistoryを手繰ってみると……　おおお！！！一番最初から、この仕様で実装されている！！

ということはcommit履歴に原因は書いてない……　とほほほ……

https://github.com/coreutils/coreutils/blob/ccbd1d7dc5189f4637468a8136f672e60ee0e531/src/sleep.c#L45

```c
  for (i = 1; i < argc; i++)
    seconds += argdecode (argv[i]);

  sleep (seconds);
```

# ではなぜ、この仕様になっているのだろうか？（推定）

どうやら「時分秒」指定をできるようにする　→　合算した方が便利っぽい、と発想したものと推定される。

ポイントは「時分秒サポート」と「合算」は同時という事。

## coreutil以前

sleepコマンドそのもの歴史はこちら。 

https://en.wikipedia.org/wiki/Sleep_(command)

ここにある通り、UNIX Likeなしステム時点で、sleepコマンドは存在していた。

## 2.8 BSD (1981年)
manにsleep 1の記載なし。

## 2.9.1 BSD (1983年)

https://www.freebsd.org/cgi/man.cgi?query=sleep&sektion=1&manpath=2.9.1+BSD

| 項目 | サポート |
|:-:|:-:|
| 秒数指定  | 65535まで |
| 単位指定  | ✕ |
| 複数指定  | ✕ |
| 少数指定  | ✕ |

## 2.10 BSD (1985年)

https://www.freebsd.org/cgi/man.cgi?query=sleep&sektion=1&manpath=2.10+BSD

| 項目 | サポート |
|:-:|:-:|
| 秒数指定  |  2,147,483,647 まで |
| 単位指定  | ✕ |
| 複数指定  | ✕ |
| 少数指定  | ✕ |

## Sun OS 4.1.3 (1987年)

https://www.freebsd.org/cgi/man.cgi?query=sleep&sektion=1&manpath=SunOS+4.1.3

| 項目 | サポート |
|:-:|:-:|
| 秒数指定  |  2,147,483,647 まで |
| 単位指定  | ✕ |
| 複数指定  | ✕ |
| 少数指定  | ✕ |

## Initial revision (1992年)

初期バージョンでは、単位指定と複数指定はできるが、少数指定はできなかった。

https://github.com/coreutils/coreutils/blob/ccbd1d7dc5189f4637468a8136f672e60ee0e531/src/sleep.c

| 項目 | サポート |
|:-:|:-:|
| 秒数指定  | UINT_MAX まで |
| 単位指定  | ◯ |
| 複数指定  | ◯ |
| 少数指定  | ✕ |

つまり、5時間30分のSleepをしたければ、`sleep 5h 30m`はサポートしていた。

GNU sh-utils 2.0 相当かな？

https://www.freebsd.org/cgi/man.cgi?query=sleep&sektion=1&manpath=Debian+2.2.7


## Rewrite to allow fractional seconds and to handle SIGCONT.（1999年)

1999年11月28日のcommitによって、少数指定ができるようになった。

https://github.com/coreutils/coreutils/commit/56172516598e1f48a629830aa5ce2c9ab9240bb7

| 項目 | サポート |
|:-:|:-:|
| 秒数指定  | DBL_MAXまで |
| 単位指定  | ◯ |
| 複数指定  | ◯ |
| 少数指定  | ◯ |

これによって、5時間30分のSleepをしたければ、`sleep 5.5h`もサポートできるようになった。

# まとめ（再掲）

- sleepコマンドは、従来秒数指定しかできなかった。（時分秒指定も無し）。
- coreutilsで実装する段階で、時分秒指定と同時に、複数指定で合算でスリープするようになった(1992年)
- 浮動小数指定もできるようになった(1999年）
- BSD系では現状まだ、秒数指定のまま。

以上になります。