chiark / gitweb /
Provide MGF macros.
[tripe] / client.c
index c1abe68e0ed59daa71447dc2640964e9ccef5af2..8890f6c0682b3081b63c2146464f626793e73fac 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: client.c,v 1.6 2001/02/22 09:06:08 mdw Exp $
+ * $Id: client.c,v 1.8 2001/06/19 22:09:37 mdw Exp $
  *
  * Client for TrIPE
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: client.c,v $
+ * 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.
  *
 
 /*----- Static variables --------------------------------------------------*/
 
+static const char *pidfile = 0;
+static const char *logname = 0;
 static FILE *logfp = 0;
 static unsigned f = 0;
-static const char *logname = 0;
 static int fd;
 
 #define f_bogus 1u
@@ -117,9 +125,8 @@ static int fd;
 
 static void reap(int sig)
 {
-  int s;
   int e = errno;
-  while (waitpid(-1, &s, WNOHANG) > 0)
+  while (waitpid(-1, 0, WNOHANG) > 0)
     ;
   errno = e;
 }
@@ -226,6 +233,19 @@ static void sighup(int sig, void *v)
   logfile(logname);
 }
 
+static void cleanup(void)
+{
+  if (pidfile)
+    unlink(pidfile);
+}
+
+static void sigdie(int sig)
+{
+  cleanup();
+  signal(sig, SIG_DFL);
+  raise(sig);
+}
+
 static void version(FILE *fp)
 {
   pquis(fp, "$, TrIPE version " VERSION "\n");
@@ -238,7 +258,8 @@ Usage:\n\
        $ [-w] [-options] [command [args]...]\n\
        $ [-Dl] [-f file] [-options]\n\
 Options:\n\
-       [-s] [-d directory] [-a socket] [-p program] [-S arg,arg,...]\n\
+       [-s] [-d directory] [-a socket] [-P pidfile]\n\
+       [-p program] [-S arg,arg,...]\n\
 ");
 }
 
@@ -258,6 +279,7 @@ Options in full:\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\
+-P, --pidfile=FILE     Write process-id to FILE.\n\
 \n\
 -s, --spawn            Start server rather than connecting.\n\
 -p, --spawn-path=PATH  Specify path to executable.\n\
@@ -276,6 +298,7 @@ int main(int argc, char *argv[])
   const char *spawnpath = "tripe";
   string_v spawnopts = DA_INIT;
   char *p;
+  FILE *pidfp = 0;
 
   ego(argv[0]);
 
@@ -298,10 +321,11 @@ int main(int argc, char *argv[])
       { "syslog",      0,              0,      'l' },
       { "logfile",     OPTF_ARGREQ,    0,      'f' },
       { "warnings",    0,              0,      'w' },
+      { "pidfile",     OPTF_ARGREQ,    0,      'P' },
       { 0,             0,              0,      0 }
     };
 
-    int i = mdwopt(argc, argv, "hvuDd:a:sp:S:lwf:n", opts, 0, 0, 0);
+    int i = mdwopt(argc, argv, "+hvuDd:a:sp:S:lwf:nP:", opts, 0, 0, 0);
     if (i < 0)
       break;
     switch (i) {
@@ -343,9 +367,11 @@ int main(int argc, char *argv[])
        break;
       case 'f':
        logname = optarg;
-       logfile(logname);
        f |= f_noinput;
        break;
+      case 'P':
+       pidfile = optarg;
+       break;
       default:
        f |= f_bogus;
        break;
@@ -356,6 +382,25 @@ int main(int argc, char *argv[])
     exit(EXIT_FAILURE);
   }
 
+  /* --- Set various things up --- */
+
+  if (chdir(dir)) {
+    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) {
+    die(EXIT_FAILURE, "couldn't open `%s' for writing: %s",
+       pidfile, strerror(errno));
+  }
+  signal(SIGINT, sigdie);
+  signal(SIGQUIT, sigdie);
+  signal(SIGTERM, sigdie);
+  atexit(cleanup);
+
   /* --- Connect to the server --- */
 
   if (f & f_spawn) {
@@ -372,13 +417,10 @@ int main(int argc, char *argv[])
 #endif
     sigaction(SIGCHLD, &sa, 0);
 
+    DA_UNSHIFT(&spawnopts, (char *)sock);
+    DA_UNSHIFT(&spawnopts, "-a");
+    DA_UNSHIFT(&spawnopts, "-d.");
     DA_UNSHIFT(&spawnopts, (char *)spawnpath);
-    if (!(f & f_spawnopts)) {
-      DA_PUSH(&spawnopts, "-d");
-      DA_PUSH(&spawnopts, (char *)dir);
-      DA_PUSH(&spawnopts, "-a");
-      DA_PUSH(&spawnopts, (char *)sock);
-    }
     DA_PUSH(&spawnopts, 0);
     if (socketpair(PF_UNIX, SOCK_STREAM, 0, pfd))
       die(EXIT_FAILURE, "error from socketpair: %s", strerror(errno));
@@ -395,6 +437,8 @@ int main(int argc, char *argv[])
       if (logfp)
        fclose(logfp);
       closelog();
+      if (f & f_daemon)
+       u_detach();
       execvp(DA(&spawnopts)[0], DA(&spawnopts));
       die(127, "couldn't exec `%s': %s", spawnpath, strerror(errno));
     }
@@ -404,15 +448,12 @@ int main(int argc, char *argv[])
   } else {
     struct sockaddr_un sun;
     size_t sz = strlen(sock) + 1;
-    dstr d = DSTR_INIT;
-    dstr_putf(&d, "%s/%s", dir, sock);
-    if (d.sz + 1 > sizeof(sun.sun_path))
+    if (sz > 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, d.buf, d.sz + 1);
-    sz = d.sz + offsetof(struct sockaddr_un, sun_path) + 1;
-    dstr_destroy(&d);
+    memcpy(sun.sun_path, sock, sz);
+    sz = sz + offsetof(struct sockaddr_un, sun_path);
     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)) {
@@ -425,6 +466,10 @@ int main(int argc, char *argv[])
     if (u_daemon())
       die(EXIT_FAILURE, "error becoming daemon: %s", strerror(errno));
   }
+  if (pidfp) {
+    fprintf(pidfp, "%li", (long)getpid());
+    fclose(pidfp);
+  }
 
   /* --- If we're meant to be interactive, do that --- */