+
+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. */
+}