fixes
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5ecee0b..cf1de09 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -6,4 +6,5 @@
 	fuse.c		\
 	fuse_mt.c	\
 	helper.c	\
+	mount.c
 	fuse_i.h
diff --git a/lib/fuse.c b/lib/fuse.c
index 42ab52a..1a11ae6 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -355,8 +355,8 @@
     size_t outsize;
     struct fuse_out_header *out;
 
-    if(error > 0) {
-        fprintf(stderr, "fuse: positive error code: %i\n",  error);
+    if(error <= -512 || error > 0) {
+        fprintf(stderr, "fuse: bad error value: %i\n",  error);
         error = -ERANGE;
     }
 
@@ -366,6 +366,7 @@
     outsize = sizeof(struct fuse_out_header) + argsize;
     outbuf = (char *) malloc(outsize);
     out = (struct fuse_out_header *) outbuf;
+    memset(out, 0, sizeof(struct fuse_out_header));
     out->unique = in->unique;
     out->error = error;
     if(argsize != 0)
@@ -395,7 +396,9 @@
             res = f->op.getattr(path, &buf);
         free(path);
     }
+
     if(res == 0) {
+        memset(&arg, 0, sizeof(struct fuse_lookup_out));
         convert_stat(&buf, &arg.attr);
         arg.ino = find_node(f, in->ino, name, &arg.attr, in->unique);
         if(f->flags & FUSE_DEBUG) {
@@ -431,8 +434,11 @@
             res = f->op.getattr(path, &buf);
         free(path);
     }
-    if(res == 0) 
+
+    if(res == 0) {
+        memset(&arg, 0, sizeof(struct fuse_getattr_out));
         convert_stat(&buf, &arg.attr);
+    }
 
     send_reply(f, in, res, &arg, sizeof(arg));
 }
@@ -513,8 +519,10 @@
             if(!res) {
                 struct stat buf;
                 res = f->op.getattr(path, &buf);
-                if(!res)
+                if(!res) {
+                    memset(&outarg, 0, sizeof(struct fuse_setattr_out));
                     convert_stat(&buf, &outarg.attr);
+                }
             }
         }
         free(path);
@@ -559,6 +567,8 @@
         free(path);
     }
     fflush(dh.fp);
+
+    memset(&arg, 0, sizeof(struct fuse_getdir_out));
     arg.fd = fileno(dh.fp);
     send_reply(f, in, res, &arg, sizeof(arg));
     fclose(dh.fp);
@@ -584,6 +594,7 @@
         free(path);
     }
     if(res == 0) {
+        memset(&outarg, 0, sizeof(struct fuse_mknod_out));
         convert_stat(&buf, &outarg.attr);
         outarg.ino = find_node(f, in->ino, PARAM(inarg), &outarg.attr,
                                in->unique);
@@ -751,6 +762,7 @@
             fflush(stdout);
         }
     }
+    memset(out, 0, sizeof(struct fuse_out_header));
     out->unique = in->unique;
     out->error = res;
     outsize = sizeof(struct fuse_out_header) + size;
@@ -798,8 +810,10 @@
     struct fuse_statfs_out arg;
 
     res = -ENOSYS;
-    if(f->op.statfs)
+    if(f->op.statfs) {
+        memset(&arg, 0, sizeof(struct fuse_statfs_out));
         res = f->op.statfs((struct fuse_statfs *) &arg.st);
+    }
 
     send_reply(f, in, res, &arg, sizeof(arg));
 }
@@ -916,18 +930,24 @@
     do {
         res = read(f->fd, cmd->buf, FUSE_MAX_IN);
         if(res == -1) {
+            free_cmd(cmd);
+            if(errno == EINTR)
+                return NULL;
+
             /* ENODEV means we got unmounted, so we silenty return failure */
             if(errno != ENODEV) {
-                perror("fuse: reading device");
                 /* BAD... This will happen again */
+                perror("fuse: reading device");
             }
-            free_cmd(cmd);
+
+            fuse_exit(f);
             return NULL;
         }
         if((size_t) res < sizeof(struct fuse_in_header)) {
-            fprintf(stderr, "short read on fuse device\n");
-            /* Cannot happen */
             free_cmd(cmd);
+            /* Cannot happen */
+            fprintf(stderr, "short read on fuse device\n");
+            fuse_exit(f);
             return NULL;
         }
         cmd->buflen = res;
@@ -941,18 +961,27 @@
     return cmd;
 }
 
-
 void fuse_loop(struct fuse *f)
 {
     while(1) {
-        struct fuse_cmd *cmd = __fuse_read_cmd(f);
+        struct fuse_cmd *cmd;
+
+        if(f->exited)
+            return;
+
+        cmd = __fuse_read_cmd(f);
         if(cmd == NULL)
-            exit(1);
+            continue;
 
         __fuse_process_cmd(f, cmd);
     }
 }
 
+void fuse_exit(struct fuse *f)
+{
+    f->exited = 1;
+}
+
 struct fuse_context *fuse_get_context(struct fuse *f)
 {
     if(f->getcontext)
@@ -985,6 +1014,7 @@
     f->getcontext = NULL;
     f->context.uid = 0;
     f->context.gid = 0;
+    f->exited = 0;
 
     root = (struct node *) calloc(1, sizeof(struct node));
     root->mode = 0;
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 02b28ec..52f1fdc 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -38,6 +38,7 @@
     struct fuse_context *(*getcontext)(struct fuse *);
     struct fuse_context context;
     pthread_key_t context_key;
+    volatile int exited;
 };
 
 struct fuse_dirhandle {
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c
index 42d4bad..f1a2e5c 100644
--- a/lib/fuse_mt.c
+++ b/lib/fuse_mt.c
@@ -32,9 +32,14 @@
     struct fuse *f = w->f;
 
     while(1) {
-        struct fuse_cmd *cmd = __fuse_read_cmd(w->f);
+        struct fuse_cmd *cmd;
+
+        if(f->exited)
+            break;
+
+        cmd = __fuse_read_cmd(w->f);
         if(cmd == NULL)
-            pthread_exit(NULL);
+            continue;
 
         if(f->numavail == 0 && f->numworker < FUSE_MAX_WORKERS) {
             pthread_mutex_lock(&f->lock);
diff --git a/lib/helper.c b/lib/helper.c
index 522b377..d3b8b1c 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -10,21 +10,15 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
+#include <string.h>
 #include <limits.h>
 #include <signal.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <fcntl.h>
-#include <sys/wait.h>
 
 #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 struct fuse *fuse;
 
 static void usage(char *progname)
 {
@@ -38,125 +32,10 @@
     exit(1);
 }
 
-static char umount_cmd[1024];
-static int fuse_fd;
-
-static void fuse_unmount()
-{
-    close(fuse_fd);
-    if(umount_cmd[0] != '\0')
-        system(umount_cmd);
-}
-
-/* return value:
- * >= 0  => fd
- * -1    => error
- */
-static int receive_fd(int fd)
-{
-    struct msghdr msg;
-    struct iovec iov;
-    char buf[1];
-    int rv;
-    int connfd = -1;
-    char ccmsg[CMSG_SPACE(sizeof(connfd))];
-    struct cmsghdr *cmsg;
-
-    iov.iov_base = buf;
-    iov.iov_len = 1;
-
-    msg.msg_name = 0;
-    msg.msg_namelen = 0;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    /* old BSD implementations should use msg_accrights instead of
-     * msg_control; the interface is different. */
-    msg.msg_control = ccmsg;
-    msg.msg_controllen = sizeof(ccmsg);
-
-    while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
-    if (rv == -1) {
-        perror("recvmsg");
-        return -1;
-    }
-    if(!rv) {
-        /* EOF */
-        fprintf(stderr, "got EOF\n");
-        return -1;
-    }
-    
-    cmsg = CMSG_FIRSTHDR(&msg);
-    if (!cmsg->cmsg_type == SCM_RIGHTS) {
-        fprintf(stderr, "got control message of unknown type %d\n",
-                cmsg->cmsg_type);
-        return -1;
-    }
-    return *(int*)CMSG_DATA(cmsg);
-}
-
-int fuse_mount(const char *mountpoint, const char *args[])
-{
-    const char *mountprog = FUSERMOUNT_PROG;
-    int fds[2], pid;
-    int res;
-    int rv;
-
-    snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u %s", mountprog,
-             mountpoint);
-    
-    res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
-    if(res == -1) {
-        perror("fuse: socketpair() failed");
-        return -1;
-    }
-
-    pid = fork();
-    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_COMMFD_ENV, env, 1);
-        execvp(mountprog, newargv);
-        perror("fuse: failed to exec fusermount");
-        exit(1);
-    }
-
-    close(fds[0]);
-    rv = receive_fd(fds[1]);
-    close(fds[1]);
-    waitpid(pid, NULL, 0); /* bury zombie */
-
-    return rv;
-}
-
 static void exit_handler()
 {
-    exit(0);
+    if(fuse != NULL)
+        fuse_exit(fuse);
 }
 
 static void set_signal_handlers()
@@ -188,14 +67,17 @@
     int argctr = 1;
     int flags;
     int multithreaded;
-    struct fuse *fuse;
     char *isreexec = getenv(FUSE_MOUNTED_ENV);
+    int fuse_fd;
+    char *fuse_mountpoint = NULL;
+    char umount_cmd[1024] = "";
 
     if(isreexec == NULL) {
         if(argc < 2 || argv[1][0] == '-')
             usage(argv[0]);
 
-        fuse_fd = fuse_mount(argv[1], NULL);
+        fuse_mountpoint = strdup(argv[1]);
+        fuse_fd = fuse_mount(fuse_mountpoint, NULL);
         if(fuse_fd == -1)
             exit(1);
 
@@ -217,7 +99,6 @@
             strncpy(umount_cmd, tmpstr, sizeof(umount_cmd) - 1);
     }
 
-    atexit(fuse_unmount);
     set_signal_handlers();
 
     flags = 0;
@@ -252,5 +133,11 @@
         fuse_loop_mt(fuse);
     else
         fuse_loop(fuse);
+
+    close(fuse_fd);
+    if(fuse_mountpoint != NULL)
+        fuse_unmount(fuse_mountpoint);
+    else if(umount_cmd[0] != '\0')
+        system(umount_cmd);
 }
 
diff --git a/lib/mount.c b/lib/mount.c
new file mode 100644
index 0000000..1224afa
--- /dev/null
+++ b/lib/mount.c
@@ -0,0 +1,136 @@
+/*
+    FUSE: Filesystem in Userspace
+    Copyright (C) 2001  Miklos Szeredi (mszeredi@inf.bme.hu)
+
+    This program can be distributed under the terms of the GNU LGPL.
+    See the file COPYING.LIB.
+*/
+
+#include "fuse.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#define FUSERMOUNT_PROG         "fusermount"
+#define FUSE_COMMFD_ENV         "_FUSE_COMMFD"
+
+
+/* return value:
+ * >= 0  => fd
+ * -1    => error
+ */
+static int receive_fd(int fd)
+{
+    struct msghdr msg;
+    struct iovec iov;
+    char buf[1];
+    int rv;
+    int connfd = -1;
+    char ccmsg[CMSG_SPACE(sizeof(connfd))];
+    struct cmsghdr *cmsg;
+
+    iov.iov_base = buf;
+    iov.iov_len = 1;
+
+    msg.msg_name = 0;
+    msg.msg_namelen = 0;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    /* old BSD implementations should use msg_accrights instead of
+     * msg_control; the interface is different. */
+    msg.msg_control = ccmsg;
+    msg.msg_controllen = sizeof(ccmsg);
+
+    while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
+    if (rv == -1) {
+        perror("recvmsg");
+        return -1;
+    }
+    if(!rv) {
+        /* EOF */
+        return -1;
+    }
+    
+    cmsg = CMSG_FIRSTHDR(&msg);
+    if (!cmsg->cmsg_type == SCM_RIGHTS) {
+        fprintf(stderr, "got control message of unknown type %d\n",
+                cmsg->cmsg_type);
+        return -1;
+    }
+    return *(int*)CMSG_DATA(cmsg);
+}
+
+void fuse_unmount(const char *mountpoint)
+{
+    const char *mountprog = FUSERMOUNT_PROG;
+    char umount_cmd[1024];
+    
+    snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u %s", mountprog,
+             mountpoint);
+    
+    umount_cmd[sizeof(umount_cmd) - 1] = '\0';
+    system(umount_cmd);
+}
+
+int fuse_mount(const char *mountpoint, const char *args[])
+{
+    const char *mountprog = FUSERMOUNT_PROG;
+    int fds[2], pid;
+    int res;
+    int rv;
+
+    res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
+    if(res == -1) {
+        perror("fuse: socketpair() failed");
+        return -1;
+    }
+
+    pid = fork();
+    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_COMMFD_ENV, env, 1);
+        execvp(mountprog, newargv);
+        perror("fuse: failed to exec fusermount");
+        exit(1);
+    }
+
+    close(fds[0]);
+    rv = receive_fd(fds[1]);
+    close(fds[1]);
+    waitpid(pid, NULL, 0); /* bury zombie */
+
+    return rv;
+}