MSYS2での入力の終わり
MSYS2の各環境が何を対象としたプログラムを作成するのか理解してしまえば話は簡単。
foo.c
#include <stdio.h> int main(void) { int c; while ((c = getchar()) != EOF) printf("%c", c); fprintf(stderr, "EOF\n"); return 0; }
mingw64.exeまたはmingw32.exeにて、
$ gcc foo.c -std=c99 -pedantic -Wall -Wextra -o foo-mingw.exe
前述の通り、foo-mingw.exeはコマンドプロンプト用なので、コマンドプロンプトにて、
C:\> foo-mingw.exe hello, world hello, world ^Z EOF C:\>
のように、標準入力の終了を知らせるEOFはCtrl+Zである。
このプログラムをMSYS2のデフォルトシェルであるbash上で実行しようとすると、
$ ./foo-mingw hello, world
改行を入力しても標準出力への出力も無く、
この状態で入力を終了しようと、Ctrl+Dと打っても、全く終わらない。
それどころか、Ctrl+Cで強制終了させると、
その前に入力したCtrl+Dのせいなのか、シェルに返った途端にシェル自体が終了した。
foo-mingw.exeはコマンドプロンプト用ということなので、
Ctrl+Zで終了させようとすると、
$ ./foo-mingw hello, world Stopped $
一見すると終了したように見えるが、結局標準出力には何も出力がないし、
EOF検出後に出るはずのEOF表示もない。
これは、Ctrl+Zが中断シグナルとして解釈されてシェルに戻ってしまったからである。
結局、foo-mingw.exeはコマンドプロンプト用であり、MSYS2環境用ではないということだ。
シンプルな解決策は、msys2.exeが提供する環境でプログラムを作成すればよい。
つまり、msys2.exe上で、
$ gcc foo.c -std=c99 -pedantic -Wall -Wextra -o foo-msys.exe
として作成したプログラムはMSYS2環境下で動作する。
$ ./foo-msys hello, world hello, world EOF $
この場合のEOFはもちろんCtrl+Dである。
もう一つの解決策はwinptyを使うことである。
$ pacman -Si winpty リポジトリ : msys 名前 : winpty バージョン : 0.4.3-1 説明 : A Windows software package providing an interface similar to a Unix pty-master for communicating with Windows console programs ...snip
これを使用すれば、mingw64.exeやmingw32.exeで作成したプログラムをMSYS2環境で使える。
$ winpty ./foo-mingw hello, world hello, world ^Z EOF $
この場合はEOFとしてコマンドプロンプト上と同様にCtrl+Zを使用することになる。
winptyの問題点は、標準入出力が端末に接続されていない場合には使えないことである。
$ winpty ./foo-mingw > hoge stdout is not a tty $ winpty ./foo-mingw < hoge stdin is not a tty $ winpty ./foo-mingw <<EOD > hello, world > EOD stdin is not a tty $
のように怒られてしまう。残念。