hylepo hylepo - 2 months ago 9
Linux Question

How can GNU time utility ignores pipe symbol and takes all what left in command line as one execve argument?

Linux, if I run

time tar -c stock_file | lz4 > stock_file.lz4
, actually it makes something like
time (tar -c stock_file | lz4 > stock_file.lz4)
, but if I write one little program:

#include <stdio.h>

int main (int argc, char **argv)
{
for (int i = 1; i < argc; ++i)
{
printf("The %dth user parameter, %s\n", i, argv[1]);
}
return 0;
}


Then I build it to
pretending_time
and run it:

shell@kernel: ~> ./pretending_time well | cat
The 1th user parameter, well


Well well, the parameter is
well
not
well | cat
, then I have the check the source code of
time
to figure it out how
time
takes
well | cat
as one parameter

git clone git://git.savannah.gnu.org/time.git


Only one file source code, feels good

int
main (argc, argv)
int argc;
char **argv;
{
const char **command_line;
RESUSE res;

......
}


Feels not good, compile it carefully

error: ‘argc’ was not declared in this scope
error: ‘argv’ was not declared in this scope
error: initializer expression list treated as compound expression
error: expected ‘,’ or ‘;’ before ‘int’
error: expected unqualified-id before ‘{’ token


What is

int
main (argc, argv)
int argc;
char **argv;
{


I have never seen it before, and I can't compile it, is this allowed in c-lang? is this the way how
time
takes the pipe symbol
|
in the parameter?

Answer

The reason time behaves differently than other (external) programs is because time is not actually a program, it's a bash builtin. For comparison, consider the following examples: with the bash builtin we get

$ time sleep 1 | sleep 2
real   0m2.003s

whereas with the external time

$ /usr/bin/time sleep 1 | sleep 2
0.00user 0.00system 0:01.00elapsed 0%CPU (0avgtext+0avgdata 7488maxresident)k

So as you can see, in first case time times both sleep operations, whereas in the second case it only times the first sleep. In general, it is impossible to build a version of time as an external program that works like the first example. The reason is that whenever bash see the pipe character, it will execute the stuff on the left and the stuff on the right independently. So the left side will never have a chance to see what the right side command looks like. On the other hand, with the builtin time, bash can recognize it and treat it specially.