summaryrefslogtreecommitdiff
path: root/tools/pido.c
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-06-02 16:07:44 (GMT)
committerJohn Denker <jsd@av8n.com>2012-06-03 00:30:23 (GMT)
commit32e75879103a943ac682cbde7b37ea4e4fbc24ab (patch)
treee734de5ec0cb5ece57d0f5aa01f6731a11f86a9b /tools/pido.c
parent9c9c853dd2c7b4b174fd435d092bb43e737b8b35 (diff)
add some tools
Diffstat (limited to 'tools/pido.c')
-rw-r--r--tools/pido.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/tools/pido.c b/tools/pido.c
new file mode 100644
index 0000000..9b92337
--- /dev/null
+++ b/tools/pido.c
@@ -0,0 +1,85 @@
+///////////////
+// pido
+// writes the pid, then execs something.
+//
+// Usage:
+// pido pidfile /absolute/path/prog progarg1 progarg2 ...
+
+// If the first arg is missing or is "-" or is ""
+// then we write to STDOUT.
+// If the first arg is "--" then we write to STDERR.
+// Otherwise the first arg is an ordinary filename.
+
+// Pido is important for scripts in init.d/ if they
+// want to start a pipeline.
+
+// If you use the command:
+// aa | bb | cc &
+// then $! returns the pid of cc.
+// Alas, aa and/or bb may be just as important as cc
+// (or even more important).
+// For example, cc might be a simple logging utility,
+// while aa is the daemon of interest.
+//
+// It is often true BUT NOT PROVABLY TRUE that the pid
+// of bb is $! minus 1, and the pid of aa is $! minus 2.
+
+// If you want something provably correct, do this:
+// pido /var/run/aa.pid /absolute/path/aa | bb | cc &
+// Then you know the correct pid of aa has been written
+// to the file aa.pid.
+
+// The perfect test for this is:
+// ./pido - ./pido -
+// which should print the same pid number twice.
+
+// There might be a way to do this with a simple shell script:
+// echo ... exec ...
+// but if there is, I haven't figured it out.
+
+
+#include <unistd.h>
+#include <stdlib.h> /* for exit() */
+#include <errno.h>
+#include <sys/types.h> /* for fork(), wait() */
+#include <stdio.h>
+
+////////////////////////////////////////
+// Here with data coming in on fd 0.
+// and control coming in on ft 1.
+
+int main(int argc, char* argv[], char* env[]) {
+
+ FILE* ouch = stdout;
+ int isfile = 1;
+ if (argc > 1) {
+ if (argv[1][0] == '-' || argv[1][0] == 0) {
+ isfile = 0;
+ if (argv[1][1] == '-') ouch = stderr;
+ }
+ if (isfile) {
+ ouch = fopen (argv[1], "w");
+ if (!ouch) {
+ fprintf(stderr, "pido: cannot open pidfile '%s': ", argv[1]);
+ perror(0);
+ exit (1);
+ }
+ }
+ }
+
+ fprintf(ouch, "%d\n", getpid());
+
+ if (isfile) fclose(ouch);
+
+ if (argc > 2) {
+ execve(argv[2], argv+2, env);
+ fprintf(stderr, "pido: failed to exec '%s': ", argv[2]);
+ perror(0);
+ for (int ii = 0; ii < argc; ii++){
+ fprintf(stderr, "'%s' ", argv[ii]);
+ }
+ fprintf(stderr, "\n");
+ exit(2);
+ }
+ return 0;
+}