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);
+}