なんだかCLIの便利なプログラムがあって、でも一般人にシリアルコンソールをつかわせるわけにはいかないのでGUIのWrapperを作る必要が出てきた。こういうことよくありますよね。ないですか?
で、そんなのすぐ作れるはずだろと思って調べたんだけど出てこなかったんですよね。まず似たようなものに、標準Cライブラリにpopenという関数があって、こいつは子プロセスを実行して、その結果をFILE *で読み取れる超便利なやつ。手元にMacがあったので、「LinuxでもMacOSでも一緒だろ」と思ってMacOSで調べたら、popenに"r+"を指定すればFILE*に書き込めると。
でもLinuxのpopenにはこれがなかったんです。
いろいろ調べて試行錯誤した結果、dup2とpipe2をつかってふにふにすればできるようでした。
void popen2(char *cmd, char *arg1, FILE **infp, FILE **outfp)
{
static int infd[2];
static int outfd[2];
*infp = NULL;
*outfp = NULL;
if (pipe2(infd, O_NONBLOCK) == -1) {
return;
}
if (pipe2(outfd, 0) == -1) {
return;
}
int fork_result = fork();
if (fork_result == -1) {
printf("fork error %s\n", errno);
return;
} else if (fork_result == 0) {
close(infd[0]);
close(STDOUT_FILENO);
dup2(infd[1], STDOUT_FILENO);
close(outfd[1]);
close(STDIN_FILENO);
dup2(outfd[0], STDIN_FILENO);
execl(cmd, cmd, arg1, (char*) NULL);
} else {
close(infd[1]);
*infp = fdopen(infd[0], "r");
close(outfd[0]);
*outfp = fdopen(outfd[1], "a");
}
}
こういうのは、学生時代にシステムプログラミングの講義の内容に含まれていたはずで、でも僕はその講義をサボって全然授業を聞いてなかったんですよね…もっと真面目に勉強しておいたらよかったなあと思ったのでした。