FreeCalypso > hg > fc-rfcal-tools
diff scripts/fc-rfcal-tee.c @ 90:713749548df6
fc-rfcal-tri900 script and fc-rfcal-tee helper implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 17 Jul 2017 05:51:31 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/fc-rfcal-tee.c Mon Jul 17 05:51:31 2017 +0000 @@ -0,0 +1,86 @@ +/* + * This C program is a workaround for a stupidity in Bourne shell. + * I would like to have a shell script like the following: + * + * set -e + * fc-rfcal-vcxo | tee vcxo + * fc-rfcal-rxband 900 | tee rx-900 + * fc-rfcal-rxband 1800 | tee rx-1800 + * ... + * + * and if one of the fc-rfcal-* steps encounters an error and returns + * a non-zero exit code, I want the script to stop right there, hence + * the set -e at the beginning. Sounds like a very simple and reasonable + * desire, doesn't it? But oh noes - because I am piping the output + * through tee in order to save it in log files, the process return + * codes from fc-rfcal-* get *ignored* by the shell (the always successful + * exit code from tee is all that counts), and it will keep executing + * the following lines without stopping. + * + * This C program is like tee, but with invokation of the "main" command + * whose output is to be saved built in. The process forks, the "main" + * command is executed in the child, the parent performs the tee function, + * and when the child terminates, the parent propagates its exit code. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +char shell_pathname[] = "/bin/sh"; +int log_fd; + +tee_process(pipe_fd) +{ + char buf[1024]; + int cc; + + while ((cc = read(pipe_fd, buf, sizeof buf)) > 0) { + write(1, buf, cc); + if (log_fd > 2) + write(log_fd, buf, cc); + } +} + +main(argc, argv) + char **argv; +{ + int p[2]; + pid_t child, waitres; + int status; + + if (argc != 3) { + fprintf(stderr, "usage: %s command logfile\n", argv[0]); + exit(1); + } + if (pipe(p) < 0) { + perror("pipe"); + exit(1); + } + child = fork(); + if (child < 0) { + perror("fork"); + exit(1); + } + if (!child) { + dup2(p[1], 1); + close(p[0]); + close(p[1]); + execl(shell_pathname, "sh", "-c", argv[1], 0); + perror(shell_pathname); + exit(1); + } + close(p[1]); + log_fd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (log_fd < 0) + perror(argv[2]); + tee_process(p[0]); + waitres = waitpid(child, &status, 0); + if (waitres == child && WIFEXITED(status)) + exit(WEXITSTATUS(status)); + else + exit(1); +}