Index: neercs/trunk/src/attach.c
===================================================================
--- neercs/trunk/src/attach.c	(revision 2470)
+++ neercs/trunk/src/attach.c	(revision 2474)
@@ -1,8 +1,69 @@
+#include <errno.h>
 #include <fcntl.h>
+#include <glob.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include "neercs.h"
+
+static char * build_socket_path(char *socket_dir)
+{
+    char *path, *dir;
+    path = (char *)malloc(PATH_MAX+1);
+    dir = socket_dir;
+    if(!dir)
+        dir = getenv("NEERCSDIR");
+    if(!dir)
+        dir = getenv("TMPDIR");
+    if(!dir)
+        dir = "/tmp";
+    if(path)
+        snprintf(path, PATH_MAX+1, "%s/neercs.%d.sock", dir, getpid());
+    return path;
+}
+
+int create_socket(struct screen_list* screen_list)
+{
+    int sock;
+    struct sockaddr_un myaddr;
+
+    sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+
+    if(sock < 0)
+    {
+        perror("create_socket:socket");
+        return errno;
+    }
+
+    memset(&myaddr, 0, sizeof(struct sockaddr_un));
+
+    myaddr.sun_family = AF_UNIX;
+    screen_list->socket_path = build_socket_path(screen_list->socket_path);
+    strncpy(myaddr.sun_path, screen_list->socket_path, sizeof(myaddr.sun_path) - 1);
+    unlink(myaddr.sun_path);
+
+    if(bind(sock, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_un)) < 0)
+    {
+        free(screen_list->socket_path);
+        screen_list->socket_path = NULL;
+        close(sock);
+        perror("create_socket:bind");
+        return errno;
+    }
+    fcntl(sock, F_SETFL, O_NONBLOCK);
+
+    debug("Listening on %s (%d)", screen_list->socket_path, sock);
+
+    screen_list->socket = sock;
+
+    return 0;
+}
 
 int detach(struct screen_list* screen_list, caca_display_t * dp)
@@ -13,15 +74,10 @@
     screen_list->attached = 0;
     caca_free_display(dp);
-
-    pid = fork();
-    if (pid < 0)
-        return 1;
-    if (pid > 0)
-        exit(0);
 
     close(0);
     close(1);
     close(2);
-    fd = open("/dev/null", O_RDWR);
+
+    fd = open("/tmp/log.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
     dup2(fd, 0);
     dup2(fd, 1);
@@ -30,19 +86,159 @@
         close(fd);
 
-    setsid();
+    if(!screen_list->socket)
+    {
+        pid = fork();
+        if (pid < 0)
+            return 1;
+        if (pid > 0)
+            exit(0);
+
+        create_socket(screen_list);
+        setsid();
+    }
 
     return 0;
 }
 
-#if 0
-int attach(struct screen_list* screen_list, cucul_canvas_t * cv, caca_display_t ** dp)
-{
-    screen_list->attached = 1;
-    *dp = caca_create_display(cv);
-    if(!*dp)
+/* FIXME Is this really not defined anywhere ? */
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+
+static int handle_command(char * cmd, struct screen_list* screen_list, cucul_canvas_t * cv, caca_display_t ** dp)
+{
+    int refresh = 0;
+    debug("Received command %s", cmd);
+    if(!strncmp("ENV ", cmd, MIN(4, strlen(cmd))))
+    {
+        putenv(strdup(cmd+4));
+    }
+    else if(!strncmp("ATTACH ", cmd, MIN(7, strlen(cmd))))
+    {
+        int fd;
+        screen_list->attached = 1;
+        close(screen_list->socket);
+        screen_list->socket= 0;
+        unlink(screen_list->socket_path);
+        screen_list->socket_path = NULL;
+        close(0);
+        fd=open(cmd+7, O_RDWR);
+        dup2(fd, 0);
+        close(1);
+        fd=open(cmd+7, O_RDWR);
+        dup2(fd, 1);
+        close(2);
+        fd=open(cmd+7, O_RDWR);
+        dup2(fd, 2);
+        *dp = caca_create_display(cv);
+        if(*dp)
+        {
+            caca_set_cursor(*dp, 1);
+            refresh = 1;
+        }
+    }
+    else
+    {
+        fprintf(stderr, "Unknown command received: %s\n", cmd);
+    }
+    return refresh;
+}
+
+int read_socket(struct screen_list* screen_list, cucul_canvas_t * cv, caca_display_t ** dp) {
+    ssize_t n;
+    char buf[4097];
+    int refresh = 0;
+
+    if(!screen_list->socket)
+        return 0;
+
+    while (screen_list->socket && (n = read(screen_list->socket, buf, sizeof(buf)-1)) > 0)
+    {
+        buf[n] = 0;
+        refresh |= handle_command(buf, screen_list, cv, dp);
+    }
+    return refresh;
+}
+
+char ** list_sockets(char *socket_dir)
+{
+    char *pattern, *dir;
+    glob_t globbuf;
+
+    globbuf.gl_pathv = NULL;
+
+    pattern = (char *)malloc(PATH_MAX+1);
+
+    dir = socket_dir;
+    if(!dir)
+        dir = getenv("NEERCSDIR");
+    if(!dir)
+        dir = getenv("TMPDIR");
+    if(!dir)
+        dir = "/tmp";
+
+    if(!pattern)
+        return globbuf.gl_pathv;
+
+    snprintf(pattern, PATH_MAX, "%s/neercs.*.sock", dir);
+    pattern[PATH_MAX] = '\0';
+
+    debug("Looking for sockets in the form %s", pattern);
+
+    glob(pattern, 0, NULL, &globbuf);
+
+    return globbuf.gl_pathv;
+}
+
+
+/* FIXME Is this really not defined anywhere ? */
+extern char **environ;
+
+int request_attach(char *socket_path)
+{
+    int i;
+    int sock;
+    char fdstr[PATH_MAX], lnk[PATH_MAX];
+    char buf[4096];
+    struct sockaddr_un addr;
+
+    debug("Connecting to %s", socket_path);
+
+    /* Open the socket */
+    if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+        perror("request_attach:socket");
         return 1;
-
-    caca_set_cursor(*dp, 1);
-    return 0;
-}
-#endif
+    }
+
+    memset(&addr,0,sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    strcpy(addr.sun_path,socket_path);
+    if (connect(sock, &addr, sizeof(addr)) < 0)
+    {
+        perror("request_attach:connect");
+        return 1;
+    }
+
+    debug("Sending environment", 0);
+
+    /* Send our environment */
+    for(i=0; environ[i]; i++)
+    {
+        snprintf(buf, 4096, "ENV %s", environ[i]);
+        write(sock, buf, strlen(buf));
+    }
+
+    snprintf(fdstr, sizeof(fdstr), "/proc/%d/fd/0", getpid());
+    readlink(fdstr, lnk, sizeof(lnk)-1);
+    lnk[PATH_MAX-1] = '\0';
+
+    close(0);
+
+    debug("Requesting attach to %s", lnk);
+
+    /* Request attaching */
+    snprintf(buf, 4096, "ATTACH %s", lnk);
+    write(sock, buf, strlen(buf));
+    close(sock);
+
+    debug("Exiting", 0);
+    exit(0);
+}
