2015-04-19

The Old New Thing: なぜ環境変数にはTMPとTEMPがあるのか。どちらが正しいのか

Why are there both TMP and TEMP environment variables, and which one is right? - The Old New Thing - Site Home - MSDN Blogs

久しぶりにRaymond Chenの記事を翻訳する。

環境変数を覗いてみると、一時ファイルを置いておく場所を指定する目的の変数が2つあることに気がつくだろう。TMPとTEMPだ。なぜ2つもあるのか。もし値が異なる場合、どちらが正しいのか。

話は1973年にさかのぼる。この当時の一般的なマイクロコンピューター用のオペレーティングシステムはCP/Mだった。CP/Mオペレーティングシステムには環境変数がなかった。環境変数の話を始めるにしては不思議な時代だが、実は大事な話なのだ。環境変数が存在しなかったのだから、TMPやTEMPなどあるはずがない。当時、プログラムに一時ファイルを置いておく場所を指定したければ、プログラムごとに独自の方法で行う必要があった。たとえば、実行ファイルの特定の1バイトをパッチして一時オブジェクトを置いておくドライブレターを変更するなど。

(筆者の記憶する限り、当時のほとんどのCP/Mプログラムはパッチによって設定していた。少なくとも、筆者はそのように設定していた。筆者はWordStarマニュアルに、どのバイトをパッチすればどのように動作するのかという記述があったことを覚えている。また、プリンター用に独自の動作を設定したい場合などに、利用者が独自のサブルーチンを書くことができる数十バイトのパッチスペースが設けられていた。筆者は、「プリンターは次の文字を受け取る用意があるか?」関数を書くのに使った。これでバックグラウンドでの印刷がスムーズになった。)

1981年に話は飛ぶ。8086プロセッサーとMS-DOSオペレーティングシステムがやってきた。8086プロセッサーの設計と、MS-DOSおペーレーティングシステムの設計は、CP/Mの影響を受けている。実際、8080プロセッサー用に書かれたCP/Mプログラムは、機械的に8086プロセッサー用のMS-DOSプログラムに変換できることが設計目標だった。もちろん、変換器は自己改変コードとか、命令の途中にジャンプするとか、コードをデータとして扱うなどの変なトリックを使わないことを前提にしているが、健全なコードならば、変換器はプログラムを変換できたのだ。

(8080プロセッサー用に書かれたコードを8086プロセッサー向けに機械変換できるという目標は、8086命令セットに存在するいくつかの不思議な制約を説明できる。たとえば、8080のHとLレジスターは、8086のBHとBLレジスターにマップされている。8080では、計算されたアドレスにアクセスできるレジスターはHLだけであった。これにより、なぜ8086の4つの基本的なレジスター、AX, BX, CX, DXのうち、メモリにアクセスできるのはBXだけなのかが説明できる)

MS-DOSがCP/Mとの互換性以上に追加した機能として、環境変数がある。既存のCP/Mのプログラムは環境変数を使っていなかったので、初期のMS-DOSプログラムも使うことはなかった。なぜならば、最初のMS-DOS用のプログラムというのは、すべてCP/Mから移植されていたからだ。もちろん、TEMPやTMPといった環境変数を設定することはできるが、誰も注意を払うものなどいない。

やがて、プログラムは最初からMS-DOS用に書かれるようになり、環境変数は設定データを格納するために使えることに皆気がついた。混沌とした市場から、2つの環境変数が、一時オブジェクトを格納する場所を記述するのに使われるようになった。TEMPとTMPである。

MS-DOS 2.0はあるプログラムの出力をパイプして、別のプログラムの入力とする機能を追加した。MS-DOSはシングルタスクのオペレーティングシステムのため、この機能は、最初のプログラムの出力を一時ファイルにリダイレクトして、実行が終了するまで走らせ、しかる後に第二のプログラムを実行しつつ、入力は一時ファイルからリダイレクトするという方法でシミュレートされた。さて唐突に、MS-DOSは一時オブジェクトを作成する場所を必要とするようになった。何らかの理由で、MS-DOSの作者はTEMP環境変数を一時ファイルが作成される場所を指定する方法として使うことにした。

ところで、COMMAND.comがTEMPを使うことにしたという決定は、他のプログラムがTEMPとTMPのどちらを使うかという選択には影響しない。作者の気分次第で選ばれるものだ。多くのプログラムは両方を確認するという折衷的な戦略を取った。そして、どちらの環境変数を先に確認するかというのも、やはり作者の気分次第で選ばれた。たとえば、昔のDISKCOPYとEDITプログラムは、TMPの前にTEMPを先に確認した。

Windowsも似たような道をたどったが、何らかの理由で、GetTempFileName関数の作者は、TEMPより先にTMPを見にいった。

結果として、特定のプログラムの一時ファイルに使われるディレクトリは、プログラムの種類次第となった。WindowsプログラムはGetTempFileName関数を使って一時ファイルを作成することが多く、その場合、TMPを優先する結果となった。

環境変数の設定ダイアログをみると、まだ2つの変数、TMPとTEMPが生き残っていて、読者の興味をひきつけている。ギーク版のアディダスVSプーマのようなものだ。

4 comments:

Egtra said...

> GetTempFileName関数の作者は、TMPよりも先にTEMPを見にいった。
これ逆、翻訳で誤っています。GetTempFileNameの仕様はTMPが先ですし、原文もそういう意味合いで書かれています。
> the original authors of the Get­Temp­File­Name function chose to look for TMP before looking for TEMP.

江添亮 said...

日本語として自然な語順にするときに間違えたらしい。

Anonymous said...

つまらない誤字ですが、おペーレーティングになっていますよ。ちょっと和みました。

Egtra said...

直していただいたんですね。ありがとうございます。