1 つのアイデアは、標準の Unix ユーティリティの機能を模倣することですが、tee
外部のリダイレクトに依存することなく、プログラム内で完全に模倣することです。
だから私は簡単な関数を書いたmytee()
.これはうまくいくようだ. それは使用しますshmget(), pipe(), fork(), and dup2()
:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
static char *mytee(int size) {
int shmid = shmget(IPC_PRIVATE, size + 1, 0660 | IPC_CREAT);
int pipe_fds[2];
pipe(pipe_fds);
switch (fork()) {
case -1: // = error
perror("fork");
exit(EXIT_FAILURE);
case 0: { // = child
char *out = shmat(shmid, 0, 0), c;
int i = 0;
out[0] = 0;
dup2(pipe_fds[0], 0); // redirect pipe to child's stdin
setvbuf(stdout, 0, _IONBF, 0);
while (read(0, &c, 1) == 1 && i < size) {
printf("<%c>", c); // pass parent's stdout to real stdout,
out[i++] = c; // and then buffer in mycapture buffer
out[i] = 0; // (the extra <> are just for clarity)
}
_exit(EXIT_SUCCESS);
}
default: // = parent
dup2(pipe_fds[1], 1); // replace stdout with output to child
setvbuf(stdout, 0, _IONBF, 0);
return shmat(shmid, 0, 0); // return the child's capture buffer
}
}
私のテストプログラムは次のとおりです。
int main(void) {
char *mycapture = mytee(100); // capture first 100 bytes
printf("Hello World"); // sample test string
sleep(1);
fprintf(stderr, "\nCaptured: <%s>\n", mycapture);
return 0;
}
出力は次のとおりです。
<H><e><l><l><o>< ><W><o><r><l><d>
Captured: <Hello World>
アプリケーションでこれを使用するにmytee()
は、テスト ステートメントprintf("<%c>", c)
をwrite(1, &c, 1)
. また、 への呼び出しでシグナルを処理する必要がある場合がありますread
。そして、2 つdup2()
のそれぞれの後に、次を追加することができます。
close(pipe_fds[0]);
close(pipe_fds[1]);
この種のリファレンスについては、たとえば、Dave Curry による27 年前の 220 ページの優れた短い O'Reillyの Unix システムでの C の使用を参照してください。