chiark / gitweb /
Fix for new key-data interface.
[tripe] / client.c
index 697481c4959fd25212a2ec81ddc1a75a3f4d222e..314bb87cb0241103760aa81803aa585bde680b3e 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: client.c,v 1.9 2002/01/13 14:57:18 mdw Exp $
+ * $Id$
  *
  * Client for TrIPE
  *
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------* 
- *
- * $Log: client.c,v $
- * Revision 1.9  2002/01/13 14:57:18  mdw
- * Track @lbuf@ changes in mLib.
- *
- * Revision 1.8  2001/06/19 22:09:37  mdw
- * Move the program name to the right place when constructing the arguments
- * to pass to a new server.
- *
- * Revision 1.7  2001/02/22 09:07:54  mdw
- * Write a pidfile on request, and delete it when finished.
- *
- * Revision 1.6  2001/02/22 09:06:08  mdw
- * Fix logfile rotation to avoid program collapse.
- *
- * 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.
- *
- * Revision 1.1  2001/02/03 20:26:37  mdw
- * Initial checkin.
- *
- */
-
 /*----- Header files ------------------------------------------------------*/
 
 #include "config.h"
@@ -203,7 +169,48 @@ static void uline(char *p, size_t len, void *b)
     f |= f_uclose;
   } else {
     p[len] = '\n';
-    write(fd, p, len + 1);
+    errno = EIO;
+    if (write(fd, p, len + 1) != len + 1)
+      moan("write failed: %s", strerror(errno));
+  }
+}
+
+static void setup(const char *cmd)
+{
+  dstr d = DSTR_INIT;
+  char ch;
+  char *p, *q;
+  int n;
+
+  dstr_puts(&d, cmd);
+  dstr_putc(&d, '\n');
+  errno = EIO; /* Relax: be vague */
+  if (write(fd, d.buf, d.len) != d.len) {
+    die(EXIT_FAILURE, "error sending setup command `%s': %s",
+       cmd, strerror(errno));
+  }
+  dstr_reset(&d);
+  for (;;) {
+    n = read(fd, &ch, 1);
+    if (!n)
+      die(EXIT_FAILURE, "unexpected EOF during setup");
+    if (n < 0) {
+      die(EXIT_FAILURE, "error receiving reply to `%s': %s",
+         cmd, strerror(errno));
+    }
+    if (d.len < 256)
+      dstr_putc(&d, ch);
+    if (ch == '\n') {
+      p = d.buf;
+      q = str_getword(&p);
+      if (!q)
+       ;
+      else if (strcmp(q, "OK") == 0)
+       return;
+      else if (strcmp(q, "FAIL") == 0)
+       die(EXIT_FAILURE, "setup command `%s' failed: %s", cmd, p);
+      dstr_reset(&d);
+    }
   }
 }
 
@@ -256,11 +263,11 @@ static void usage(FILE *fp)
 {
   pquis(fp, "\
 Usage:\n\
-       $ [-w] [-options] [command [args]...]\n\
-       $ [-Dl] [-f file] [-options]\n\
+       $ [-w] [-OPTIONS] [COMMAND [ARGS]...]\n\
+       $ [-Dl] [-f FILE] [-OPTIONS]\n\
 Options:\n\
-       [-s] [-d directory] [-a socket] [-P pidfile]\n\
-       [-p program] [-S arg,arg,...]\n\
+       [-s] [-d DIRECTORY] [-a SOCKET] [-P PIDFILE]\n\
+       [-p PROGRAM] [-S ARG,ARG,...]\n\
 ");
 }
 
@@ -278,8 +285,9 @@ Options in full:\n\
 -u, --usage            Show brief usage message.\n\
 \n\
 -D, --daemon           Become a background task after connecting.\n\
--d, --directory=DIR    Select current directory [default /var/lib/tripe]\n\
--a, --admin-socket=FILE        Select socket to connect to.\n\
+-d, --directory=DIR    Select current directory [default " CONFIGDIR "].\n\
+-a, --admin-socket=FILE        Select socket to connect to\n\
+                          [default " SOCKETDIR "/tripesock].\n\
 -P, --pidfile=FILE     Write process-id to FILE.\n\
 \n\
 -s, --spawn            Start server rather than connecting.\n\
@@ -294,8 +302,8 @@ Options in full:\n\
 
 int main(int argc, char *argv[])
 {
-  const char *dir = "/var/lib/tripe";
-  const char *sock = "tripesock";
+  const char *dir = CONFIGDIR;
+  const char *sock = SOCKETDIR "/tripesock";
   const char *spawnpath = "tripe";
   string_v spawnopts = DA_INIT;
   char *p;
@@ -437,6 +445,8 @@ int main(int argc, char *argv[])
       close(pfd[0]);
       if (logfp)
        fclose(logfp);
+      if (pidfp)
+       fclose(pidfp);
       closelog();
       if (f & f_daemon)
        u_detach();
@@ -468,12 +478,15 @@ int main(int argc, char *argv[])
       die(EXIT_FAILURE, "error becoming daemon: %s", strerror(errno));
   }
   if (pidfp) {
-    fprintf(pidfp, "%li", (long)getpid());
+    fprintf(pidfp, "%li\n", (long)getpid());
     fclose(pidfp);
   }
+  signal(SIGPIPE, SIG_IGN);
 
   /* --- If we're meant to be interactive, do that --- */
 
+  if (optind == argc)
+    setup("WATCH -A+tw");
   if (!(f & f_noinput) && optind == argc) {
     sel_state sel;
     selbuf bu, bs;
@@ -491,14 +504,16 @@ int main(int argc, char *argv[])
 
   if (optind < argc) {
     dstr d = DSTR_INIT;
+    setup((f & f_warn) ? "WATCH -A+w" : "WATCH -A");
     dstr_puts(&d, argv[optind++]);
     while (optind < argc) {
       dstr_putc(&d, ' ');
       dstr_puts(&d, argv[optind++]);
     }
     dstr_putc(&d, '\n');
-    write(fd, d.buf, d.len);
-    shutdown(fd, 1);
+    errno = EIO;
+    if (write(fd, d.buf, d.len) != d.len || shutdown(fd, 1))
+      die(EXIT_FAILURE, "write failed: %s", strerror(errno));
     dstr_destroy(&d);
     f |= f_command;
   }