FreeCalypso > hg > fc-rfcal-tools
view scripts/fc-rfcal-tee.c @ 109:5a7c174acd32
txlevels: rf3166-ideal and rf3166-fcdev3b profiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 13 Feb 2018 01:11:41 +0000 |
parents | 713749548df6 |
children |
line wrap: on
line source
/* * 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); }