Figo
Figo

Reputation: 1720

"tee" like programming api in UNIX

I want to have something like this

$> ps -ax | tee -a processes.txt

In a UNIX C programming environment, meaning not via shell scripts.

Basically is there a API so that I can tee on STDIN and/or STDOUT so that I can recording automatically anything appears on the CLI down to a file. Imagine there's a foreground process interact with user and response with some output to the terminal. I want to have everything shown in the terminal also in a file for later examination.

I would imagine something as magic as this:

tee(STDIN, "append", logFile);

Thanks!

Follow-up, this is the program I wrote according to Lars (see Answer section below), but not exactly what I desired:

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

        int pfd[2];
        if (pipe(pfd) == -1) { perror("pipe"); }


        if (fork()==0) { // child reads from pipe
                close(pfd[1]);

                mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
                int ufd = open("user_study.log", O_CREAT | O_APPEND | O_WRONLY, mode);
                if (ufd == -1) {
                        perror("Cannot open output file"); exit(1);
                } // ++

                char buf;
                while (read(pfd[0], &buf, 1) > 0) {
                        write(STDOUT_FILENO, &buf, 1); // write to stdout
                        write(ufd, &buf,1);            //   and to log
                }

                close(pfd[0]);

        } else { // parent write to pipe
                // dup STDOUT to the pipe
                close(pfd[0]);
                dup2(pfd[1], STDOUT_FILENO);

                char msg[200];
                msg[0] = "";
                do {
                        scanf("%s", msg);
                        printf("program response..");

                } while (strcmp(msg, "exit")!=0);

                close(pfd[1]);

        }

        return 1;
}

Actual running:

[feih@machine ~/mytest]$ ./a.out
abc
haha
exit 
program response..   <---- the output is delayed by the chld process, not desired
program response..
program response..

[feih@machine ~/mytest]$ less user_study.log
program response..   <---- the log doesn't contain input
program response..
program response..

Desired running and log(simulated):

[feih@machine ~/mytest]$ ./a.out
abc
program response..
haha
program response..
exit 
program response..


[feih@machine ~/mytest]$ less user_study.log 
abc
program response..      <--- the log should be the same as the running
haha
program response..
exit 
program response..

So up till now, this problem hasn't been fully resolved.

Upvotes: 1

Views: 1064

Answers (1)

user25148
user25148

Reputation:

You can do this:

  • create a pipe (see pipe(2))
  • fork
  • in the child, read from the pipe and write to each output
    • stdout and a file, or whatever you need
  • in the parent, redirect stdout to the pipe (see dup2(2))

There's a bunch of trickiness you need to take care of, but it's doable.

You can't do it this without an extra process, since printf only writes to one file descriptor (the stdout one).

Upvotes: 1

Related Questions