chiark / gitweb /
debian/: Redo the multiarch support for Debhelper 9.
[tripe] / client / tripectl.c
index 0daaacbad1b7ae401f05b3e10d970387a59234cc..e264a7346375edfeeeed29553cf252ce7b754568 100644 (file)
@@ -52,6 +52,8 @@
 #include <mLib/daemonize.h>
 #include <mLib/darray.h>
 #include <mLib/dstr.h>
+#include <mLib/macros.h>
+#include <mLib/mdup.h>
 #include <mLib/mdwopt.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
@@ -79,6 +81,7 @@ static const char *pidfile = 0;
 static const char *logname = 0;
 static FILE *logfp = 0;
 static unsigned f = 0;
+static const char *watch = 0;
 static int fd;
 static const char *bgtag = 0;
 
@@ -91,6 +94,8 @@ static const char *bgtag = 0;
 #define f_noinput 64u
 #define f_warn 128u
 #define f_uclose 256u
+#define f_losing 512u
+#define f_nostamp 1024u
 
 /*----- Main code ---------------------------------------------------------*/
 
@@ -107,8 +112,9 @@ static void writelog(const char *cat, const char *msg)
   char buf[256];
   time_t t = time(0);
   struct tm *tm = localtime(&t);
-  strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
-  fprintf(logfp, "%s %s: %s\n", buf, cat, msg);
+  if (f & f_nostamp) buf[0] = 0;
+  else strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S ", tm);
+  fprintf(logfp, "%s%s: %s\n", buf, cat, msg);
 }
 
 static void checkbg(char **p)
@@ -120,7 +126,7 @@ static void checkbg(char **p)
     die(EXIT_FAILURE, "unexpected background tag `%s'", q);
 }
 
-static void dolog(int prio, const char *msg, ...)
+static void PRINTF_LIKE(2, 3) dolog(int prio, const char *msg, ...)
 {
   va_list ap;
   dstr d = DSTR_INIT;
@@ -153,15 +159,16 @@ static void cline(char *p, size_t len, void *b)
   if (!p) {
     if (f & f_command)
       die(EXIT_FAILURE, "server dropped the connection");
+    f &= ~f_losing;
     exit(0);
   }
   q = str_getword(&p);
   if (!q)
     return;
   if (strcmp(q, "WARN") == 0)
-    dolog(LOG_WARNING, p);
+    dolog(LOG_WARNING, "%s", p);
   else if (strcmp(q, "TRACE") == 0)
-    dolog(LOG_DEBUG, p);
+    dolog(LOG_DEBUG, "%s", p);
   else if (!(f & f_command))
     dolog(LOG_ERR, "unexpected output `%s %s'", q, p);
   else if (strcmp(q, "FAIL") == 0) {
@@ -270,7 +277,11 @@ static void logfile(const char *name)
 {
   FILE *fp;
 
-  if ((fp = fopen(name, "a")) != 0) {
+  if (strcmp(name, "-") == 0)
+    logfp = stdout;
+  else if (strcmp(name, "!") == 0)
+    logfp = stderr;
+  else if ((fp = fopen(name, "a")) != 0) {
     if (logfp)
       fclose(logfp);
     logfp =  fp;
@@ -281,9 +292,9 @@ static void logfile(const char *name)
     if (logfp)
       writelog("error", d.buf);
     else if (logname)
-      die(EXIT_FAILURE, d.buf);
+      die(EXIT_FAILURE, "%s", d.buf);
     if (f & f_syslog)
-      syslog(LOG_ERR, d.buf);
+      syslog(LOG_ERR, "%s", d.buf);
     dstr_destroy(&d);
   }
 }
@@ -295,7 +306,7 @@ static void cleanup(void) { if (pidfile) unlink(pidfile); }
 static void sigdie(int sig)
   { cleanup(); signal(sig, SIG_DFL); raise(sig); }
 
-static void putarg(string_v *av, const char *fmt, ...)
+static void PRINTF_LIKE(2, 3) putarg(string_v *av, const char *fmt, ...)
 {
   va_list ap;
   dstr d = DSTR_INIT;
@@ -350,7 +361,9 @@ Options in full:\n\
 \n\
 -l, --syslog           Log messages to system log.\n\
 -f, --logfile=FILE     Log messages to FILE.\n\
+-t, --no-timestamp     When logging to a file, don't emit timestamps.\n\
 -w, --warnings         Show warnings when running commands.\n\
+-W, --watch=THINGS     Watch for THINGS after connecting.\n\
 ", fp);
 }
 
@@ -367,6 +380,7 @@ int main(int argc, char *argv[])
   uid_t u = -1;
   gid_t g = -1;
   int pfd[2], efd[2];
+  mdup_fd md[3];
   pid_t kid;
   struct sigaction sa;
   sigset_t newmask, oldmask;
@@ -401,12 +415,14 @@ int main(int argc, char *argv[])
       { "spawn-args",  OPTF_ARGREQ,    0,      'S' },
       { "syslog",      0,              0,      'l' },
       { "logfile",     OPTF_ARGREQ,    0,      'f' },
+      { "no-timestamp",        0,              0,      't' },
       { "warnings",    0,              0,      'w' },
+      { "watch",       OPTF_ARGREQ,    0,      'W' },
       { "pidfile",     OPTF_ARGREQ,    0,      'P' },
       { 0,             0,              0,      0 }
     };
 
-    i = mdwopt(argc, argv, "+hvuDU:G:d:a:sp:S:lwf:nP:", opts, 0, 0, 0);
+    i = mdwopt(argc, argv, "+hvuDU:G:d:a:sp:S:lwW:f:nP:t", opts, 0, 0, 0);
     if (i < 0)
       break;
     switch (i) {
@@ -452,10 +468,16 @@ int main(int argc, char *argv[])
       case 'w':
        f |= f_warn;
        break;
+      case 'W':
+       watch = optarg;
+       break;
       case 'f':
        logname = optarg;
        f |= f_noinput;
        break;
+      case 't':
+       f |= f_nostamp;
+       break;
       case 'P':
        pidfile = optarg;
        break;
@@ -475,8 +497,6 @@ int main(int argc, char *argv[])
     die(EXIT_FAILURE, "couldn't set `%s' as current directory: %s",
        dir, strerror(errno));
   }
-  if (logname)
-    logfile(logname);
   if (!pidfile && (f & f_daemon) && ((f & f_syslog) || logname))
     pidfile = "tripectl.pid";
   if (pidfile && (pidfp = fopen(pidfile, "w")) == 0) {
@@ -516,12 +536,12 @@ int main(int argc, char *argv[])
     if ((kid = fork()) < 0)
       die(EXIT_FAILURE, "fork failed: %s", strerror(errno));
     if (!kid) {
-      dup2(pfd[1], STDIN_FILENO);
-      dup2(pfd[1], STDOUT_FILENO);
-      dup2(efd[1], STDERR_FILENO);
-      close(pfd[0]); close(pfd[1]);
-      close(efd[0]); close(efd[1]);
-      if (logfp) fclose(logfp);
+      close(pfd[0]); close(efd[0]);
+      sigprocmask(SIG_SETMASK, &oldmask, 0);
+      md[0].cur = pfd[1]; md[0].want = STDIN_FILENO;
+      md[1].cur = pfd[1]; md[1].want = STDOUT_FILENO;
+      md[2].cur = efd[1]; md[2].want = STDERR_FILENO;
+      mdup(md, 3);
       if (pidfp) fclose(pidfp);
       closelog();
       if (f & f_daemon) detachtty();
@@ -548,7 +568,10 @@ int main(int argc, char *argv[])
     }
   }
 
+  f |= f_losing; /* pessimism */
   u_setugid(u, g);
+  if (logname)
+    logfile(logname);
   if (f & f_daemon) {
     if (daemonize())
       die(EXIT_FAILURE, "error becoming daemon: %s", strerror(errno));
@@ -561,8 +584,12 @@ int main(int argc, char *argv[])
 
   /* --- If we're meant to be interactive, do that --- */
 
-  if (optind == argc)
-    setup("WATCH -A+tw");
+  if (optind == argc) {
+    DRESET(&d);
+    dstr_puts(&d, "watch");
+    u_quotify(&d, watch ? watch : "-A+tw");
+    setup(d.buf);
+  }
   if (!(f & f_noinput) && optind == argc) {
     selbuf_init(&bu, &sel, STDIN_FILENO, uline, &bu);
     selbuf_init(&bs, &sel, fd, sline, &bs);
@@ -575,7 +602,11 @@ int main(int argc, char *argv[])
   /* --- If there's a command, submit it --- */
 
   if (optind < argc) {
-    setup((f & f_warn) ? "WATCH -A+w" : "WATCH -A");
+    DRESET(&d);
+    dstr_puts(&d, "watch");
+    u_quotify(&d, watch ? watch : (f & f_warn) ? "-A+w" : "-A");
+    setup(d.buf);
+    DRESET(&d);
     while (optind < argc)
       u_quotify(&d, argv[optind++]);
     dstr_putc(&d, '\n');