ときに popen() は便利

ライブラリを探してインストールしたり,ドキュメントを読んだり,動作を確認したりする手間をかけたくないとき,コマンドで実現できることであれば,popen() を使うという手があります.

例えば,標準入力から読み込んだデータを gzip で圧縮して "out.gz" に保存するプログラムなら,popen() と pclose() を使って以下のように記述できます.

#include <stdio.h>

int main()
{
  char buf[4096];

  ::FILE *fp = ::popen("gzip -c > out.gz", "w");
  if (fp == NULL)
  {
    ::fprintf(stderr, "error: failed to open process\n");
    return 1;
  }

  ::size_t size;
  do
  {
    size = ::fread(buf, 1, sizeof(buf), stdin);
    ::fwrite(buf, 1, size, fp);
  } while (size != 0);

  ::pclose(fp);

  return 0;
}

圧縮ファイル "out.gz" を読み込む場合なら,"gzip -cd out.gz" を第一引数に,"r" を第二引数にして popen() を呼び出せば,入力用の FILE * が手に入ります.

コマンドを bzip2 や xz に切り替えれば他の圧縮形式にも対応できますし,圧縮レベル・ブロックサイズ・圧縮プリセットの切り替えも簡単にできます.パイプによる入出力の連結で対処できないときは便利です.

とはいえ,欠点も多数あります.入力文字列をコマンドとして実行することになるので,セキュリティ上の問題が発生しやすいとか,何か問題があったときに原因が分かりにくいとか….