Andreas Krennmair:
[apps/madmutt.git] / init.c
diff --git a/init.c b/init.c
index cbc9645..d566add 100644 (file)
--- a/init.c
+++ b/init.c
@@ -43,6 +43,8 @@
 #include <string.h>
 #include <sys/utsname.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <sys/wait.h>
 
 void toggle_quadoption (int opt)
@@ -2175,3 +2177,131 @@ int mutt_get_hook_type (const char *name)
       return c->data;
   return 0;
 }
+
+void mutt_start_slrnface(void)
+{
+  char *fifo;
+  int pathlen, status;
+  pid_t pid, pidst;
+  struct utsname u;
+
+  if (!option(OPTXFACE))
+    return;
+
+  /*
+   * If we don't have display, there's no point. The user probably knows,
+   * so fail silently.
+   */
+  if (!getenv("DISPLAY"))
+    return;
+  /* If there is no WINDOWID, complain. */
+  if (!getenv ("WINDOWID"))
+  {
+    mutt_error (_("Cannot run slrnface: WINDOWID not found in environment."));
+    return;
+  }
+
+  uname (&u);
+  pathlen = strlen (Homedir) + sizeof("/.slrnfaces/")
+            + strlen (u.nodename) + 30;
+  fifo = safe_malloc (pathlen);
+  sprintf (fifo, "%s/.slrnfaces", Homedir);
+  if (mkdir (fifo, 0700))
+  {
+    if (errno != EEXIST)
+    {
+      mutt_error (_("Cannot run slrnface: failed to create %s: %s."),
+                 fifo, strerror(errno));
+      return;
+    }
+  }
+  else
+  {
+    FILE *fp;
+
+    /* We'll abuse fifo filename memory here. It's long enough. */
+    sprintf (fifo, "%s/.slrnfaces/README", Homedir);
+    if ((fp = fopen (fifo, "w")) != NULL)
+    {
+      fputs (_(
+"This directory is used to create named pipes for communication between\n"
+"slrnface and its parent process. It should normally be empty because\n"
+"the pipe is deleted right after it has been opened by both processes.\n\n"
+"File names generated by slrnface have the form \"hostname.pid\". It is\n"
+"probably an error if they linger here longer than a fraction of a second.\n\n"
+"However, if the directory is mounted from an NFS server, you might see\n"
+"special files created by your NFS server while slrnface is running.\n"
+"Do not try to remove them.\n"), fp);
+      fclose (fp);
+    }
+  }
+
+  status = snprintf (fifo, pathlen, "%s/.slrnfaces/%s.%ld", Homedir,
+                    u.nodename, (long)getpid());
+  if (status < 0)
+    goto clean_face;
+
+  unlink (fifo);
+  if (mkfifo (fifo, 0600) < 0)
+  {
+    mutt_error (_("Cannot run slrnface, failed to create %s: %s."), fifo,
+               strerror(errno));
+    goto clean_face;
+  }
+
+  pid = fork();
+  switch (pid)
+  {
+    case -1: break;
+    case 0:  execlp ("slrnface", "slrnface", fifo, (char *)0);
+            /* This is child, exit on error. */
+            _exit (10);
+    default: do {
+              pidst = waitpid (pid, &status, 0);
+            } while (pidst == -1 && errno == EINTR);
+
+            if (!WIFEXITED (status))
+              mutt_error (_("Slrnface abnormaly exited, code %d."), status);
+            else
+            {
+              char *message;
+
+              switch (WEXITSTATUS (status))
+              {
+                case 0: /* All fine, open the pipe */
+                        slrnface_fd = open (fifo, O_WRONLY, 0600);
+                        write (slrnface_fd, "start\n", sizeof "start");
+                        goto clean_face;
+                case 1: message = "couldn't connect to display";
+                        break;
+                case 2: message = "WINDOWID not found in environment";
+                        break;
+                case 3: message = "couldn't find controlling terminal";
+                        break;
+                case 4: message = "terminal doesn't export width and height";
+                        break;
+                case 5: message = "cannot open FIFO";
+                        break;
+                case 6: message = "fork() failed";
+                        break;
+                case 10: message = "executable not found";
+                         break;
+                default: message = "unknown error";
+              }
+              mutt_error (_("Slrnface failed: %s."), message);
+            }
+  }
+
+clean_face:
+  unlink (fifo);
+  free (fifo);
+}
+
+void mutt_stop_slrnface(void)
+{
+  if (slrnface_fd >= 0)
+    close(slrnface_fd);
+  slrnface_fd = -1;
+
+  /* FIFO has been unlinked in the startup function. */
+}