I am reading output from another process which generates output (slow and infinite). Because I want to read this data in real-time I use "stdbuf -oL" (line-buffered, data is text). I do not have control of the generating process so I cannot modify the source to force flushing.
So far stdbuf works just fine, however the process uses SOCK_RAW and needs either to be run as root, have setuid(0) or the cap_net_raw
capability. When running as non-root with setuid or capabilities stdbuf seems to be ignored. Let me demonstrate the problem:
This is a simple writer:
#include <stdio.h>
#include <unistd.h>
int main(){
int i;
for ( i = 0;; i++){
fprintf(stdout, "%d\n", i);
sleep(1);
}
}
And a simple reader:
#include <stdio.h>
int main(){
char* line = NULL;
size_t n = 0;
while (getline(&line, &n, stdin) != -1 ) {
fputs(line, stdout);
}
}
As expected, by executing ./writer | ./reader
nothing shows up until the buffer is filled. Prepending stdbuf -oL
enables line-buffering and I get the lines into the reader:
% stdbuf -oL ./writer | ./reader
0
1
2
...
But if I add cap_net_raw+ep
it stops working:
% sudo setcap cap_net_raw+ep ./writer
% stdbuf -oL ./writer | ./reader
(no output)
The same behaviour is observed when using setuid:
% sudo chown root:root ./writer
% sudo chmod +s ./writer
% stdbuf -oL ./writer | ./reader
(no output)
I'm interested in understanding why this happens and how I can continue to use stdbuf without running as root. I admit that I do not fully understand what setuid is doing behind the scenes.