------------------------
coreutils4.5.1 tee.c代码分析
今天早上起来,吃完早餐,弹会儿琴,就开始读代码了。
昨天看了一点,接着看tee.c,整体比较简单,不过神奇的是,tee,可以同时写进多个文件,我原来从来没想过这样:
echo "hello world" | tee a.txt b.txt c.txt | grep "hello"
看到没,tee可把输入写进多个文件,并同时写到标准输出。它是如何做到的呢?
在tee2中。大体思路是:
tee2(文件个数,文件名数组参数)
建立一个文件名数组,大小比参数中传来的大1
再把参数中,文件名[0---n-1]====>新文件名数组[1----n]
标准输入0====》新文件名数组[0]
下面就从标准输入读一段,再把这段写到每个文件中。过程如下:
/* Move all the names `up' one in the argv array to make room for
the entry for standard output. This writes into argv[argc]. */
for (i = nfiles; i >= 1; i--)
files[i] = files[i - 1];
SET_BINARY2 (0, 1);
/* In the array of NFILES + 1 descriptors, make
the first one correspond to standard output. */
descriptors[0] = stdout;
files[0] = _("standard output");
SETVBUF (stdout, NULL, _IONBF, 0);
这是把标准输入弄进数组中的那一段。
再把数组中每个文件打开。
for (i = 1; i <= nfiles; i++)
{
descriptors[i] = fopen (files[i], mode_string);
if (descriptors[i] == NULL)
{
error (0, errno, "%s", files[i]);
ret = 1;
}
else
{
SETVBUF (descriptors[i], NULL, _IONBF, 0);
SET_BINARY (fileno (descriptors[i]));
}
}
下面就是写
while (1)
{
bytes_read = read (0, buffer, sizeof buffer);
#ifdef EINTR
if (bytes_read < 0 && errno == EINTR)
continue;
#endif
if (bytes_read <= 0)
break;
/* Write to all NFILES + 1 descriptors.
Standard output is the first one. */
for (i = 0; i <= nfiles; i++)
{
if (descriptors[i] != NULL)
fwrite (buffer, bytes_read, 1, descriptors[i]);
}
}
这个程序写得真流畅。我体会到点儿乐趣了。