chiark / gitweb /
*** empty log message ***
[sympathy.git] / apps / sympathy.c
index b5bf326..2339853 100644 (file)
@@ -11,6 +11,9 @@ static char rcsid[] =
 
 /*
  * $Log$
 
 /*
  * $Log$
+ * Revision 1.24  2008/02/28 22:00:42  james
+ * *** empty log message ***
+ *
  * Revision 1.23  2008/02/28 16:57:51  james
  * *** empty log message ***
  *
  * Revision 1.23  2008/02/28 16:57:51  james
  * *** empty log message ***
  *
@@ -269,6 +272,9 @@ main (int argc, char *argv[])
   extern int optind, opterr, optopt;
   CRT_Pos size = { VT102_COLS_80, VT102_ROWS_24 };
 
   extern int optind, opterr, optopt;
   CRT_Pos size = { VT102_COLS_80, VT102_ROWS_24 };
 
+  int csnok_pipe[2] = { 0 };
+  int csnok = 0;
+
   int oflags[128];
   char *oargs[128];
 
   int oflags[128];
   char *oargs[128];
 
@@ -278,7 +284,7 @@ main (int argc, char *argv[])
   Log *log = NULL;
 
   int history = 200;
   Log *log = NULL;
 
   int history = 200;
-
+  int pid;
 
   get_hostname ();
 
 
   get_hostname ();
 
@@ -386,43 +392,35 @@ main (int argc, char *argv[])
   if (oflags['p'] && oflags['d'])
     fatal_moan ("-p incompatible with -d");
 
   if (oflags['p'] && oflags['d'])
     fatal_moan ("-p incompatible with -d");
 
-  /*implement server and client by opening the server socket to prevent */
-  /*a race condition, and then forking and munging the cmd line options */
-  /*in the parent and child so that the child is the server and the */
-  /*parent becomes its client */
 
   if (oflags['c'] && oflags['s'] && oflags['F'])
     fatal_moan ("-F is incompatible with -c -s");
 
 
   if (oflags['c'] && oflags['s'] && oflags['F'])
     fatal_moan ("-F is incompatible with -c -s");
 
-  if (oflags['s'] && !oflags['k'])
-    {
-      char *path;
-      path = mome ("/.sympathy");
-      mkdir (path, 0700);
-      free (path);
-
-      oargs['k'] = mome ("/.sympathy/%s%d", hostname, getpid ());
-      oflags['k']++;
-    }
-
-  if (oflags['s'])
-    {
-      server_socket = socket_listen (oargs['k']);
-      if (!server_socket)
-        fatal_moan ("failed to create socket %s for listening", oargs['k']);
-    }
+  /*implement server and client: this process forks. The parent */
+  /*becomes the client and the child forks again to become the */
+  /*server. If there's no -k argument the client (parent) needs */
+  /*to find out the pid of the server, we use a pipe */
 
   if (oflags['s'] && oflags['c'])
     {
 
   if (oflags['s'] && oflags['c'])
     {
-      switch (fork ())
+      if (!oflags['k'])
+        {
+          csnok++;
+          pipe (csnok_pipe);
+        }
+
+      switch (pid = fork ())
         {
         case 0:                /*child becomes the server */
           oflags['c'] = 0;
           oflags['H'] = 0;
         {
         case 0:                /*child becomes the server */
           oflags['c'] = 0;
           oflags['H'] = 0;
+
+          if (csnok)
+            close (csnok_pipe[0]);
           break;
         case -1:
           fatal_moan ("fork failed");
           break;
         case -1:
           fatal_moan ("fork failed");
-        default:
+        default:             /*parent becomes client*/
           oflags['s'] = 0;
           oflags['K'] = 0;
           oflags['d'] = 0;
           oflags['s'] = 0;
           oflags['K'] = 0;
           oflags['d'] = 0;
@@ -432,10 +430,26 @@ main (int argc, char *argv[])
           oflags['L'] = 0;
           oflags['n'] = 0;
           oflags['w'] = 0;
           oflags['L'] = 0;
           oflags['n'] = 0;
           oflags['w'] = 0;
-          if (server_socket)
+
+         /*Collect the child*/
+          waitpid (pid, NULL, 0);
+
+          /*if there was no k argument we need to find the*/
+          /*pid of the server process so that we can work out*/
+          /*what the socket is called. The server tells us on*/
+         /*a pipe*/
+
+          if (csnok)
             {
             {
-              socket_free_parent (server_socket);
-              server_socket = NULL;
+              close (csnok_pipe[1]);
+
+              if (read (csnok_pipe[0], &pid, sizeof (pid)) != sizeof (pid))
+                fatal_moan ("Failed to receive pid of server process");
+
+              close (csnok_pipe[0]);
+
+              oargs['k'] = mome ("/.sympathy/%s%d", hostname, pid);
+              oflags['k']++;
             }
         }
     }
             }
         }
     }
@@ -478,10 +492,41 @@ main (int argc, char *argv[])
 
   if (oflags['s'] && !oflags['F'])
     {
 
   if (oflags['s'] && !oflags['F'])
     {
-      daemon (1, 0);            /*incase socket is relative path, unlink then will fail */
+      /*nochdir incase socket is relative path, unlink then will fail */
+      daemon (1, 0);
+
+      /*Tell our parent's parent what our pid is */
+      if (csnok)
+        {
+          pid = getpid ();
+
+          write (csnok_pipe[1], &pid, sizeof (pid));
+          close (csnok_pipe[1]);
+        }
     }
 
 
     }
 
 
+  if (oflags['s'] )
+    {
+      char *path;
+      path = mome ("/.sympathy");
+      mkdir (path, 0700);
+      free (path);
+
+
+      if (!oflags['k']) {
+      pid = getpid ();
+       
+      oargs['k'] = mome ("/.sympathy/%s%d", hostname, pid);
+      oflags['k']++;
+       }
+
+      server_socket = socket_listen (oargs['k']);
+      if (!server_socket)
+        fatal_moan ("failed to create socket %s for listening", oargs['k']);
+
+    }
+
   if (oflags['s'] || oflags['t'])
     {
 
   if (oflags['s'] || oflags['t'])
     {