#include <fcntl.h>
 #include <sys/wait.h>
 
-#define FUSE_MOUNTED_ENV     "_FUSE_MOUNTED"
-#define FUSE_UMOUNT_CMD_ENV  "_FUSE_UNMOUNT_CMD"
+#define FUSE_MOUNTED_ENV        "_FUSE_MOUNTED"
+#define FUSE_UMOUNT_CMD_ENV     "_FUSE_UNMOUNT_CMD"
+#define FUSE_COMMFD_ENV         "_FUSE_COMMFD"
+
+#define FUSERMOUNT_PROG         "fusermount"
 
 static void usage(char *progname)
 {
     exit(1);
 }
 
-static void fuse_unmount()
-{
-    close(0);
-    system(getenv(FUSE_UMOUNT_CMD_ENV));
-}
+static char umount_cmd[1024];
+static int fuse_fd;
 
-static int fuse_mount_obsolete(int *argcp, char **argv)
+static void fuse_unmount()
 {
-    char *isreexec = getenv(FUSE_MOUNTED_ENV);
-
-    if(isreexec == NULL) {
-        int i;
-        int argc = *argcp;
-        char *mountprog = "fusermount";
-        char **newargv = (char **) malloc((1 + argc + 1) * sizeof(char *));
-
-        if(argc < 2 || argv[1][0] == '-')
-            usage(argv[0]);
-        
-        /* oldargs: "PROG MOUNTPOINT ARGS..."
-           newargs: "fusermount MOUNTPOINT PROG ARGS..." */
-
-        newargv[0] = mountprog;
-        newargv[1] = argv[1];
-        newargv[2] = argv[0];
-        for(i = 2; i < argc; i++)
-            newargv[i+1] = argv[i];
-        newargv[i+1] = NULL;
-
-        execvp(mountprog, newargv);
-        fprintf(stderr, "fuse: failed to exec %s: %s\n", mountprog,
-                strerror(errno));
-        return -1;
-    }
-    unsetenv(FUSE_MOUNTED_ENV);
-    
-    /* The actual file descriptor is stdin */
-    return 0;
+    close(fuse_fd);
+    if(umount_cmd[0] != '\0')
+        system(umount_cmd);
 }
 
 /* return value:
  * >= 0  => fd
  * -1    => error
  */
-int receive_fd(int fd) {
+static int receive_fd(int fd)
+{
     struct msghdr msg;
     struct iovec iov;
     char buf[1];
     return *(int*)CMSG_DATA(cmsg);
 }
 
-int fuse_mount(const char *mountpoint, const char *mount_args)
+int fuse_mount(const char *mountpoint, const char *args[])
 {
+    const char *mountprog = FUSERMOUNT_PROG;
     int fds[2], pid;
-    int rv, fd;
-    char env[10];
+    int res;
+    int rv;
+
+    snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u %s", mountprog,
+             mountpoint);
     
-    /* FIXME: parse mount_args (or just pass it to fusermount ???) */
-    mount_args = mount_args;
-
-    /* make sure the socket fds are greater than 0 */
-    fd = open("/dev/null",O_RDONLY); 
-    rv = socketpair(PF_UNIX,SOCK_STREAM,0,fds);
-    close(fd);
-    if(rv) {
-        fprintf(stderr,"fuse: failed to socketpair()\n");
-        close(fd);
+    res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
+    if(res == -1) {
+        perror("fuse: socketpair() failed");
         return -1;
     }
+
     pid = fork();
-    if(pid < 0) {
-        fprintf(stderr,"fuse: failed to fork()\n");
+    if(pid == -1) {
+        perror("fuse: fork() failed");
         close(fds[0]);
         close(fds[1]);
         return -1;
     }
+
     if(pid == 0) {
+        char env[10];
+        char **newargv;
+        int numargs = 0;
+        int actr;
+        int i;
+
+        if(args != NULL) 
+            while(args[numargs] != NULL)
+                numargs ++;
+
+        newargv = (char **) malloc((1 + numargs + 2) * sizeof(char *));
+        actr = 0;
+        newargv[actr++] = strdup(mountprog);
+        for(i = 0; i < numargs; i++)
+            newargv[actr++] = strdup(args[i]);
+        newargv[actr++] = strdup(mountpoint);
+        newargv[actr++] = NULL;
+
         close(fds[1]);
-        fcntl(fds[0],F_SETFD,0);
-        snprintf(env,sizeof(env),"%i",fds[0]);
-        setenv("_FUSE_IOSLAVE_FD",env,1);
-        execlp("fusermount","fusermount",mountpoint,"fuse_ioslave",NULL);
-        fprintf(stderr,"fuse: failed to exec fusermount\n");
+        fcntl(fds[0], F_SETFD, 0);
+        snprintf(env, sizeof(env), "%i", fds[0]);
+        setenv(FUSE_COMMFD_ENV, env, 1);
+        execvp(mountprog, newargv);
+        perror("fuse: failed to exec fusermount");
         exit(1);
     }
 
-    fd = fds[1];
     close(fds[0]);
-    rv = receive_fd(fd);
-    close(fd);
-    waitpid(pid,NULL,0); /* bury zombie */
+    rv = receive_fd(fds[1]);
+    close(fds[1]);
+    waitpid(pid, NULL, 0); /* bury zombie */
+
     return rv;
 }
 
 
 void fuse_main(int argc, char *argv[], const struct fuse_operations *op)
 {
-    int fd;
-    int argctr;
+    int argctr = 1;
     int flags;
     int multithreaded;
     struct fuse *fuse;
+    char *isreexec = getenv(FUSE_MOUNTED_ENV);
 
-    fd = fuse_mount_obsolete(&argc, argv);
-    if(fd == -1)
-        exit(1);
+    if(isreexec == NULL) {
+        if(argc < 2 || argv[1][0] == '-')
+            usage(argv[0]);
+
+        fuse_fd = fuse_mount(argv[1], NULL);
+        if(fuse_fd == -1)
+            exit(1);
+
+        argctr++;
+    }
+    else {
+        char *tmpstr;
+
+        /* Old (obsolescent) way of doing the mount: 
+           
+             fusermount [options] mountpoint [program [args ...]]
+
+           fusermount execs this program and passes the control file
+           descriptor dup()-ed to stdin */
+        fuse_fd = 0;
+        
+        tmpstr = getenv(FUSE_UMOUNT_CMD_ENV);
+        if(tmpstr != NULL)
+            strncpy(umount_cmd, tmpstr, sizeof(umount_cmd) - 1);
+    }
 
     atexit(fuse_unmount);
     set_signal_handlers();
 
-    argctr = 1;
     flags = 0;
     multithreaded = 1;
     for(; argctr < argc && argv[argctr][0] == '-'; argctr ++) {
         exit(1);
     }
 
-    fuse = fuse_new(fd, flags, op);
+    fuse = fuse_new(fuse_fd, flags, op);
 
     if(multithreaded)
         fuse_loop_mt(fuse);
 
+++ /dev/null
-#include <stdio.h>                 /* fprintf */
-#include <errno.h>                 /* errno */
-#include <string.h>                /* strerror */
-#include <unistd.h>                /* read,write,close */
-#include <stdlib.h>                /* getenv,strtol */
-#include <sys/select.h>            /* select */
-#include <sys/socket.h>            /* send, recv */
-#include <sys/un.h>                /* struct sockaddr_un */
-#define BUFSIZE (2<<16)
-#undef IOSLAVE_DEBUG
-char *scratch;
-
-/* return values:
- * 0  => success
- * -1 => error condition
- */
-int send_fd(int sock_fd, int send_fd) {
-    int retval;
-    struct msghdr msg;
-    struct cmsghdr *p_cmsg;
-    struct iovec vec;
-    char cmsgbuf[CMSG_SPACE(sizeof(send_fd))];
-    int *p_fds;
-    char sendchar = 0;
-    msg.msg_control = cmsgbuf;
-    msg.msg_controllen = sizeof(cmsgbuf);
-    p_cmsg = CMSG_FIRSTHDR(&msg);
-    p_cmsg->cmsg_level = SOL_SOCKET;
-    p_cmsg->cmsg_type = SCM_RIGHTS;
-    p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
-    p_fds = (int *) CMSG_DATA(p_cmsg);
-    *p_fds = send_fd;
-    msg.msg_controllen = p_cmsg->cmsg_len;
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
-    msg.msg_iov = &vec;
-    msg.msg_iovlen = 1;
-    msg.msg_flags = 0;
-    /* "To pass file descriptors or credentials you need to send/read at
-     * least one byte" (man 7 unix)
-     */
-    vec.iov_base = &sendchar;
-    vec.iov_len = sizeof(sendchar);
-    while((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
-    if (retval != 1) {
-        perror("sendmsg");
-        return -1;
-    }
-    return 0;
-}
-
-int main() {
-    char *env = getenv("_FUSE_IOSLAVE_FD");
-    int fd;
-    if (!env)
-        exit(fprintf(stderr, "fuse_ioslave: do not run me directly\n"));
-    fd = strtol(env, NULL, 0);
-    if(send_fd(fd, 0) == -1)
-       fprintf(stderr,"failed to send fd\n");
-    return 0;
-}
 
 #include <sys/stat.h>
 #include <sys/mount.h>
 #include <sys/fsuid.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include <linux/fuse.h>
 
 #define CHECK_PERMISSION 1
 #define FUSE_MOUNTED_ENV        "_FUSE_MOUNTED"
 #define FUSE_UMOUNT_CMD_ENV     "_FUSE_UNMOUNT_CMD"
 #define FUSE_KERNEL_VERSION_ENV "_FUSE_KERNEL_VERSION"
+#define FUSE_COMMFD_ENV         "_FUSE_COMMFD"
 
 const char *progname;
 
     return strdup(buf);
 }
 
+static int send_fd(int sock_fd, int fd) 
+{
+    int retval;
+    struct msghdr msg;
+    struct cmsghdr *p_cmsg;
+    struct iovec vec;
+    char cmsgbuf[CMSG_SPACE(sizeof(fd))];
+    int *p_fds;
+    char sendchar = 0;
+
+    msg.msg_control = cmsgbuf;
+    msg.msg_controllen = sizeof(cmsgbuf);
+    p_cmsg = CMSG_FIRSTHDR(&msg);
+    p_cmsg->cmsg_level = SOL_SOCKET;
+    p_cmsg->cmsg_type = SCM_RIGHTS;
+    p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+    p_fds = (int *) CMSG_DATA(p_cmsg);
+    *p_fds = fd;
+    msg.msg_controllen = p_cmsg->cmsg_len;
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = &vec;
+    msg.msg_iovlen = 1;
+    msg.msg_flags = 0;
+    /* "To pass file descriptors or credentials you need to send/read at
+     * least one byte" (man 7 unix) */
+    vec.iov_base = &sendchar;
+    vec.iov_len = sizeof(sendchar);
+    while((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
+    if (retval != 1) {
+        perror("sending file descriptor");
+        return -1;
+    }
+    return 0;
+}
+
 static void usage()
 {
     fprintf(stderr,
     int numargs;
     char mypath[PATH_MAX];
     char *unmount_cmd;
+    char *commfd;
     char verstr[128];
     int flags = 0;
 
         return 0;
     }
 
-    if(a == argc) {
+    commfd = getenv(FUSE_COMMFD_ENV);
+
+    if(a == argc && commfd == NULL) {
         fprintf(stderr, "%s: Missing program argument\n", progname);
         exit(1);
     }
     if(fd == -1)
         exit(1);
 
+    if(commfd != NULL) {
+        int cfd = atoi(commfd);
+        res = send_fd(cfd, fd);
+        if(res == -1)
+            exit(1);
+        exit(0);
+    }
+
     /* Dup the file descriptor to stdin */
     if(fd != 0) {
         dup2(fd, 0);