chiark / gitweb /
Use reliable signal handling for reopening logs.
[tripe] / client.c
index e78f86e7829fae3e5593c34b38d1b750746506a5..019d68f120f95a6ee9b412d48cca68b17132ea64 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: client.c,v 1.2 2001/02/04 01:17:54 mdw Exp $
+ * $Id: client.c,v 1.5 2001/02/16 21:23:39 mdw Exp $
  *
  * Client for TrIPE
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: client.c,v $
+ * Revision 1.5  2001/02/16 21:23:39  mdw
+ * Use reliable signal handling for reopening logs.
+ *
+ * Revision 1.4  2001/02/06 09:34:53  mdw
+ * Change ERR response to FAIL for consistency with other programs.
+ *
+ * Revision 1.3  2001/02/04 17:10:15  mdw
+ * Reopen logfiles on receipt of @SIGHUP@ (not done very well).  Don't
+ * change directory -- just mangle pathnames instead.
+ *
  * Revision 1.2  2001/02/04 01:17:54  mdw
  * Create a configuration header file to tidy up command lines.
  *
 #include <mLib/alloc.h>
 #include <mLib/darray.h>
 #include <mLib/dstr.h>
-#include <mLib/lbuf.h>
 #include <mLib/mdwopt.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
 #include <mLib/sel.h>
 #include <mLib/selbuf.h>
+#include <mLib/sig.h>
 #include <mLib/str.h>
 
 #include "util.h"
@@ -87,6 +97,7 @@
 
 static FILE *logfp = 0;
 static unsigned f = 0;
+static const char *logname = 0;
 static int fd;
 
 #define f_bogus 1u
@@ -151,7 +162,7 @@ static void cline(char *p, void *b)
       writelog("error", d.buf);
       dstr_destroy(&d);
     }
-  } else if (strcmp(q, "ERR") == 0)
+  } else if (strcmp(q, "FAIL") == 0)
     die(EXIT_FAILURE, "%s", p);
   else if (strcmp(q, "INFO") == 0)
     puts(p);
@@ -185,6 +196,22 @@ static void uline(char *p, void *b)
   }
 }
 
+static void logfile(const char *name)
+{
+  if (logfp)
+    fclose(logfp);
+  if ((logfp = fopen(name, "a")) == 0) {
+    die(EXIT_FAILURE, "error opening logfile `%s': %s",
+       name, strerror(errno));
+  }
+  setvbuf(logfp, 0, _IOLBF, BUFSIZ);
+}
+
+static void sighup(int sig, void *v)
+{
+  logfile(logname);
+}
+
 static void version(FILE *fp)
 {
   pquis(fp, "$, TrIPE version " VERSION "\n");
@@ -301,12 +328,8 @@ int main(int argc, char *argv[])
        f |= f_warn;
        break;
       case 'f':
-       if (logfp)
-         fclose(logfp);
-       if ((logfp = fopen(optarg, "a")) == 0) {
-         die(EXIT_FAILURE, "error opening logfile `%s': %s",
-             optarg, strerror(errno));
-       }
+       logname = optarg;
+       logfile(logname);
        f |= f_noinput;
        break;
       default:
@@ -319,13 +342,6 @@ int main(int argc, char *argv[])
     exit(EXIT_FAILURE);
   }
 
-  /* --- Set the world up --- */
-
-  if (chdir(dir)) {
-    die(EXIT_FAILURE, "couldn't set current directory to `%s': %s",
-       dir, strerror(errno));
-  }
-
   /* --- Connect to the server --- */
 
   if (f & f_spawn) {
@@ -344,7 +360,8 @@ int main(int argc, char *argv[])
 
     DA_UNSHIFT(&spawnopts, (char *)spawnpath);
     if (!(f & f_spawnopts)) {
-      DA_PUSH(&spawnopts, "-d.");
+      DA_PUSH(&spawnopts, "-d");
+      DA_PUSH(&spawnopts, (char *)dir);
       DA_PUSH(&spawnopts, "-a");
       DA_PUSH(&spawnopts, (char *)sock);
     }
@@ -361,6 +378,9 @@ int main(int argc, char *argv[])
       dup2(pfd[1], STDOUT_FILENO);
       close(pfd[1]);
       close(pfd[0]);
+      if (logfp)
+       fclose(logfp);
+      closelog();
       execvp(DA(&spawnopts)[0], DA(&spawnopts));
       die(127, "couldn't exec `%s': %s", spawnpath, strerror(errno));
     }
@@ -370,17 +390,20 @@ int main(int argc, char *argv[])
   } else {
     struct sockaddr_un sun;
     size_t sz = strlen(sock) + 1;
-    if (sz > sizeof(sun.sun_path))
+    dstr d = DSTR_INIT;
+    dstr_putf(&d, "%s/%s", dir, sock);
+    if (d.sz + 1 > sizeof(sun.sun_path))
       die(EXIT_FAILURE, "socket name `%s' too long", sock);
     memset(&sun, 0, sizeof(sun));
     sun.sun_family = AF_UNIX;
-    memcpy(sun.sun_path, sock, sz);
-    sz += offsetof(struct sockaddr_un, sun_path);
+    memcpy(sun.sun_path, d.buf, d.sz + 1);
+    sz = d.sz + offsetof(struct sockaddr_un, sun_path) + 1;
+    dstr_destroy(&d);
     if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
       die(EXIT_FAILURE, "error making socket: %s", strerror(errno));
     if (connect(fd, (struct sockaddr *)&sun, sz)) {
       die(EXIT_FAILURE, "error connecting to `%s': %s",
-         sock, strerror(errno));
+         sun.sun_path, strerror(errno));
     }
   }
 
@@ -399,7 +422,7 @@ int main(int argc, char *argv[])
     selbuf_init(&bu, &sel, STDIN_FILENO, uline, &bu);
     selbuf_init(&bs, &sel, fd, sline, &bs);
     for (;;) {
-      if (sel_select(&sel))
+      if (sel_select(&sel) && errno != EINTR && errno != EAGAIN)
        die(EXIT_FAILURE, "select failed: %s", strerror(errno));
     }
   }
@@ -423,20 +446,23 @@ int main(int argc, char *argv[])
   /* --- Pull everything else out of the box --- */
 
   {
-    lbuf b;
-    lbuf_init(&b, cline, 0);
+    sel_state sel;
+    selbuf b;
+    sig hup;
+
+    sel_init(&sel);
+    selbuf_init(&b, &sel, fd, cline, 0);
+
     if (f & f_syslog)
       openlog(QUIS, 0, LOG_DAEMON);
+    if (logfp) {
+      sig_init(&sel);
+      sig_add(&hup, SIGHUP, sighup, 0);
+    }
     for (;;) {
-      size_t sz = lbuf_free(&b, &p);
-      ssize_t n = read(fd, p, sz);
-      if (n < 0)
-       die(EXIT_FAILURE, "read failed: %s", strerror(errno));
-      if (n == 0)
-       break;
-      lbuf_flush(&b, p, n);
+      if (sel_select(&sel) && errno != EINTR && errno != EAGAIN)
+       die(EXIT_FAILURE, "select failed: %s", strerror(errno));
     }
-    lbuf_close(&b);
   }
 
   return (0);