ハクソク

世界を動かす技術を、日本語で。

TMPとTEMPの環境変数が両方存在するのはなぜか? (2015)

概要

  • 環境変数TMPTEMPは、一時ファイルの保存場所を指定するために存在
  • 歴史的経緯により、どちらを使うかはプログラムごとに異なる
  • MS-DOSとWindowsの進化の中で両者が併存
  • 一部プログラムは両方をチェックし、優先順位もまちまち
  • WindowsではGetTempFileName関数がTMPを優先

TMPとTEMP:一時ファイル用環境変数の歴史

  • 1973年当時、CP/Mには環境変数が存在しなかった

    • 一時ファイルの保存先は、プログラムごとに実行ファイルのバイトを書き換えて設定
  • WordStarのようなCP/Mプログラムは、マニュアルにパッチ方法を記載

    • 独自サブルーチン用のパッチスペースも確保
    • プリンタ制御などのカスタマイズ例
  • 1981年、8086プロセッサMS-DOSが登場

    • 設計目標はCP/Mプログラムの機械翻訳による移植性
    • 8080のHLレジスタが8086のBXレジスタに対応
    • 移植性重視のため、MS-DOS初期プログラムは環境変数を利用しなかった
  • MS-DOSが進化し、環境変数の導入

    • 新規開発プログラムが設定情報として環境変数を利用
    • 一時ファイル保存先としてTEMPTMPが登場し、両者が主流に
  • MS-DOS 2.0でパイプ機能追加

    • 一時ファイルの保存先にTEMPを採用
    • しかし、他プログラムはTEMPまたはTMPのどちらか、あるいは両方をチェック
    • DISKCOPYEDITはTEMP→TMPの順で確認

Windows時代のTMPとTEMP

  • WindowsではGetTempFileName関数がTMPを優先
    • Windowsプログラムはこの関数を利用することが多い
  • 環境変数設定画面には今もTMPTEMPが併記
    • どちらが使われるかはプログラム次第
    • まさに「Adidas対Puma」のような共存状態

著者情報

  • 著者Raymondは30年以上Windows進化に関与
    • 2003年にWebサイト「The Old New Thing」を開設
    • サイトは予想以上の人気を博し、書籍化も実現(Addison Wesley 2007年)
    • Windows Dev Docs Twitterでも時折登場し、ユーモラスなエピソードを発信

Hackerたちの意見

1995年頃かな。テレストラ(オーストラリアの通信会社)。組織全体で約5万台のデスクトップコンピュータがあった。ある日、みんなのネットワークのホームディレクトリに「null」っていう小さなファイルが現れたんだ。どうやら* nixの人が.batファイルを書こうとしたみたい。なんで既存の標準を採用する必要があるんだろう?(「標準化する理由は?」って聞こうと思ったけど、北米の人たちを混乱させるかもって気づいた。 : )
> ある日、みんなのネットワークのホームディレクトリに「null」っていう小さなファイルが現れた。* nixの人が.batファイルを書こうとしたみたいだけど、最初は/dev/nullを試して失敗したから、ただのnullにしたのかな?そうじゃないと、Unixプログラマーがこんなことするのはおかしいよね。むしろ、DOSプログラマーがNULを「null」と間違えた可能性が高い。
彼が捨てようとしたテキストには何が書いてあったの?
あるLogitechのドライバインストールプログラム(どのバージョンか、どの製品かは不明だけど)もそうだった…HDにNULLという名前のファイルが見つかって、もちろん何かが> NULLというBATファイルもあったよ。
そんなにカオスだったとは知らなかった。だから、この話の教訓は、常に同じパスを指すようにしないと、どうなるかってことかな…。
> 私の記憶では、ほとんどのCP/Mプログラムはパッチで設定されていた。少なくとも、私はそうやって設定してた。WordStarのマニュアルには、何をするためにどのバイトをパッチすればいいかの詳細が載ってたのを覚えてる。プリンターのカスタムサポートを追加する必要がある場合に備えて、自分のサブルーチンを書くためのパッチスペースも数十バイト用意されてた。へぇ、面白いね。私の時代の前の話だし、これについては聞いたことなかった :D
うん、確かにそういうことがあった。パッチコードはZ80/8080のマシンコードで書かなきゃいけなかった。私はこの機能を使って、自分のWordstarのために高性能なキーボードとディスプレイのルーチンを書いたよ。
> 「私の記憶では、ほとんどのCP/Mプログラムはパッチで設定されていた。」 へぇ、それは面白いね。私の時代の前のことだから、聞いたことなかったよ :D そうそう、実際にあったんだよ。元々CP/M用のプログラム(例えば、DOS用のWordStar 7.0)では、長い間続いてた。WordStar 7のドキュメントには、プログラムの動作を変更するために使うパッチの場所が載ってたよ(確か、DOSのdebug.exe用だったと思う)。
そういうのは今でもあるよ。sucklessが書いてるものは、一般的にconfig.hを変更して再コンパイルすることで設定されるんだ。https://suckless.org/ 編集: あ、これがこのページの別のスレッドで既に言及されてたのを見逃してた。
それは面白いね。私の時代の前のことだから、聞いたことなかったよ。RAMとディスクスペースがすごく限られてたから必要だったんだよね。ほとんどのコンピュータにはアセンブラが付いてきたし、多くのCP/Mプログラムは32KのRAMと130Kの遅いフロッピーディスクで動くことが期待されてた。もっとひどいのはカセットテープからだったり。64KのRAMと360Kのディスクがあったら、特別な存在だったんだよ。今とは違って、ほとんどのプログラムは市場の底辺向けに最適化されてた。できるだけ多くのシステムで動かないと、もっと多くのコピーを売れなかったからね。人にハードウェアをアップグレードしろなんて言わなかった。失敗は自分の責任で、顧客のせいじゃなかった。外部設定ファイルやその設定ファイルを生成するプログラムを置く余裕なんてなかったんだ。一般的な機能はコマンドラインパラメータでアクセスできたけど、そのロジックも貴重なバイトを消費してた。今の人たちは、MacBook Neoが8,000,000,000バイトのRAMしかないって文句言ってるけど、そんな限られたスペースじゃ何もできないって。でも1978年には、2,048バイトで基本的なIDE全体を書けたんだよ。
> 私の記憶では、ほとんどのCP/Mプログラムはパッチで設定されていた。正直言って、私のホームディレクトリに散らばってるドットファイルより、こういう設定の方が好きだったな。
そういうの、標準化されてほしいな。何とかして.configフォルダーを強制できるディストリビューションがあれば、私にとっては最高だね。でも、もうチャンスを逃しちゃったかも。
ちょっと変わったsucklessの人たちの哲学の一部は、彼らのプロジェクトがほとんどソースコードを変更して再コンパイルすることで設定されるってことだね。これは、現代のオープンソースの流れに似たアプローチだと思う。ただ、彼らの一般的な禁欲主義が、プロジェクトをちょっと好みが分かれるものにしてるんじゃないかな。
まあ、全部 .config に入ってるはずなんだけど、問題は多くのアプリ開発者が自分たちが特別な存在だと思って、自分専用のディレクトリが必要だって勘違いしてることだよね。
実行ファイルのバイナリパッチを好んでたの?マジで?
もしみんなが XDG ベースディレクトリ仕様に従ってたら、設定ファイルの散乱なんて問題にならないのに。どんどん多くのプロジェクトがこれを取り入れてるし、Firefoxみたいな抵抗勢力もいるけどね。
中央のバイナリレジストリに散らばった設定より、grepできてテキストエディタで管理できるドットファイルの方がいいな。でも、これは単に私がそういうのに慣れてるだけかも。
CP/M の言及に混乱してる。著者は後で重要になるって言ってるけど、CP/Mや8080 CPUとは関係ないって説明してるし。
どのテキストを引用してるのか教えてもらえる?
同意。CP/Mはストーリーとは関係ないし、8080/8086も全然関係ないよ。要するに、マイクロソフトは自分たちが使ってたのに、標準化することを全く気にしなかったってことだね。
CP/Mが環境変数を設定に使っていたら、TMPとTEMPの標準が確立されて、DOSもそれを採用していたかもしれない。でも実際のところ、CP/Mにはディレクトリがなかったし、DOS 1.0にもなかった。
< 1973年に戻ってみよう。マイクロコンピュータで一般的だったオペレーティングシステムは CP/M だった。レイモンドのブログは好きだけど、これはちょっとおかしい。1973年にはマイクロコンピュータはプロトタイプとしてしか存在してなかったし(インテルの Intellec 開発システムみたいな)、それ用のオペレーティングシステムはなかった。厳密に言えば、キルダールは1973年に CP/M の開発を始めたけど、その時点では PDP-10 メインフレームのシミュレーター上でしか動かなかった。1979年ならともかく、1973年は早すぎる…
ウィキペディアによると1974年に作られたらしいから、ここでのタイムラインには何かおかしいところがあるね。
> 1979年、確かに。1973年?早すぎる… これが面白いのは、2020年と今の間の時間差と同じだってことだよね。それで、2020年にはChatGPTがなかったなんて思ってる。
初期の開発者がほとんど考えずに決めたと思われるけど、長い間影響を与え続ける決定のいい例だね。
一時的な決定ほど永続的なものはないよね。
働いていたS&P500の製品のコアにあるテーブルは、いつまでも「attornies」と名付けられることになるだろう。なぜなら、誰も早い段階で気づかなかったから。
それに、プログラムが「TMP」を選んだのは、MS-DOSのファイル拡張子が最大3文字だったからだと思う。プログラムは一時ファイルの名前に「.TMP」を使ってたしね。
Microsoftのこういうイライラすることを何十年も指摘してきたけど、面白いことに「シニア開発者」って自信満々な人がいつも答えを持ってたんだよね。「ほら、tempはtemporaryの略だよ。TmpはトラブルシュートマイPCの略。デバッグログ用なんだ。だから俺がシニアでお前がそうじゃないんだよ。」って。俺がもっとシニアになったら、実際にそれを疑問に思ってよかったって分かったし、今は元のMicrosoftの開発者と話せるようになって、彼らが「うっかりミス」について説明してくれるんだ。どうしてそれが有効な言い訳なのか、後方互換性って言うけど、頻繁にコアの互換性やビジネスフロー(新しいOutlookみたいな)を壊す変更があるのに、彼らは完全に手を引くんだ。「俺は悪い開発者じゃない、新しい連中に聞いてくれ。」って。でも新しい連中には聞けないし、彼らはleetcodeの画面の後ろに隠れてる。だから本当の問題が解決されず、新しいOutlookがあるのも無理はないよ。前にいたシニア開発者が今そこで働いてるし、実際の開発者はみんな引退しちゃった。Microsoftからユーザーのホームドキュメントフォルダがランダムなプログラムに不適切に使われたり、OneDriveに強制的に削除されたりすることについて本当の答えをもらったとしても、彼らが用意した答えや技術文書、オンラインの怒ったインタビューでの説明は、Microsoftがランダムな変更を押し出してこれらの動作を悪化させると、6ヶ月以内に無効になっちゃうんだ。まるでメモ帳のアップデートみたいに。開発者のインタビューでは、これはリスクゼロであるべきシンプルなプログラムだって言われてたのに、結局Microsoft認証ログインとコパイロットが追加されちゃった。leetcodeの開発者の態度やMicrosoftの文化が業界全体を台無しにしてるよ。まともな議論ができないし、すべてが「お前はMicrosoftで働いてないからお前の主張は無効だ」ってなる。Google Chromeがアプリデータにインストールされて管理者権限を回避するために悪用されたのは、記憶に残る出来事だよね。それは明らかに、3rdパーティが管理者権限を回避するために使うことを意図した機能じゃないのに、今では開発者たちによって意図された機能としてリテコンされてる。だって、当時のChromeは3rdパーティの例外プログラムを何百万台のロックダウンされたビジネスコンピュータに展開するのが大変だったから。
Unixプログラムがhttp_proxyを探すかHTTP_PROXYを探すかが一貫してなかったのと似てるね。今では多くのプログラムが両方を探してるけど、同じ順番でとは限らないかも。