fix
diff --git a/ChangeLog b/ChangeLog
index b14b6ad..89610fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12 +1,16 @@
 2006-01-06  Miklos Szeredi <miklos@szeredi.hu>
 
-	* Released 2.5.0
-
-2006-01-06  Miklos Szeredi <miklos@szeredi.hu>
-
 	* Change working directory to "/" even if running in the
 	foreground.  Patch from Jonathan Brandmeyer
 
+	* Changed lots of functions to use 'struct fuse_args' instead of
+	separate argc and argv
+
+	* Added fuse_parse_cmdline(), fuse_set_signal_handlers() and
+	fuse_remove_signal_handlers() functions, so that it's now pretty
+	easy to get all the functionality of fuse_main() with a filesystem
+	using the lowlevel API.
+
 2006-01-02  Miklos Szeredi <miklos@szeredi.hu>
 
 	* mount.fuse: the 'user' option should be ignored. Report and
diff --git a/configure.in b/configure.in
index d14db87..322d6eb 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-AC_INIT(fuse, 2.5.0)
+AC_INIT(fuse, 2.5.0-pre2)
 AC_CANONICAL_TARGET
 AM_INIT_AUTOMAKE
 AM_CONFIG_HEADER(include/config.h)
diff --git a/example/fusexmp.c b/example/fusexmp.c
index 26b2be2..172dc88 100644
--- a/example/fusexmp.c
+++ b/example/fusexmp.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c
index 787f87c..3ff6c9d 100644
--- a/example/fusexmp_fh.c
+++ b/example/fusexmp_fh.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
diff --git a/example/hello.c b/example/hello.c
index b71bcd6..8ab7181 100644
--- a/example/hello.c
+++ b/example/hello.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
diff --git a/example/hello_ll.c b/example/hello_ll.c
index d365771..7682f4e 100644
--- a/example/hello_ll.c
+++ b/example/hello_ll.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
@@ -146,32 +146,32 @@
 
 int main(int argc, char *argv[])
 {
-    const char *mountpoint;
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    char *mountpoint;
     int err = -1;
     int fd;
 
-    if (argc != 2) {
-        fprintf(stderr, "usage: %s mountpoint\n", argv[0]);
-        return 1;
-    }
-    mountpoint = argv[1];
-    fd = fuse_mount(mountpoint, NULL);
-    if (fd != -1) {
+    if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
+        (fd = fuse_mount(mountpoint, &args)) != -1) {
         struct fuse_session *se;
 
-        se = fuse_lowlevel_new("debug", &hello_ll_oper, sizeof(hello_ll_oper),
+        se = fuse_lowlevel_new(&args, &hello_ll_oper, sizeof(hello_ll_oper),
                                NULL);
         if (se != NULL) {
-            struct fuse_chan *ch = fuse_kern_chan_new(fd);
-            if (ch != NULL) {
-                fuse_session_add_chan(se, ch);
-                err = fuse_session_loop(se);
+            if (fuse_set_signal_handlers(se) != -1) {
+                struct fuse_chan *ch = fuse_kern_chan_new(fd);
+                if (ch != NULL) {
+                    fuse_session_add_chan(se, ch);
+                    err = fuse_session_loop(se);
+                }
+                fuse_remove_signal_handlers(se);
             }
             fuse_session_destroy(se);
         }
         close(fd);
     }
     fuse_unmount(mountpoint);
+    fuse_opt_free_args(&args);
 
     return err ? 1 : 0;
 }
diff --git a/example/null.c b/example/null.c
index d9539ab..82e7c45 100644
--- a/example/null.c
+++ b/example/null.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
diff --git a/include/fuse.h b/include/fuse.h
index 1cf727c..2eac635 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
@@ -420,12 +420,12 @@
  * Create a new FUSE filesystem.
  *
  * @param fd the control file descriptor
- * @param opts mount options to be used by the library
+ * @param args argument vector
  * @param op the operations
  * @param op_size the size of the fuse_operations structure
  * @return the created FUSE handle
  */
-struct fuse *fuse_new(int fd, const char *opts,
+struct fuse *fuse_new(int fd, struct fuse_args *args,
                       const struct fuse_operations *op, size_t op_size);
 
 /**
@@ -488,13 +488,7 @@
  */
 int fuse_invalidate(struct fuse *f, const char *path);
 
-/**
- * Check whether a mount option should be passed to the kernel or the
- * library
- *
- * @param opt the option to check
- * @return 1 if it is a library option, 0 otherwise
- */
+/* Deprecated, don't use */
 int fuse_is_lib_option(const char *opt);
 
 /**
@@ -513,9 +507,9 @@
 typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *);
 
 /** This is the part of fuse_main() before the event loop */
-struct fuse *fuse_setup(int argc, char *argv[],
+struct fuse *fuse_setup(struct fuse_args *args, 
                         const struct fuse_operations *op, size_t op_size,
-                          char **mountpoint, int *multithreaded, int *fd);
+                        char **mountpoint, int *multithreaded, int *fd);
 
 /** This is the part of fuse_main() after the event loop */
 void fuse_teardown(struct fuse *fuse, int fd, char *mountpoint);
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 979c092..0f35ea6 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
@@ -13,6 +13,7 @@
 #ifndef _FUSE_COMMON_H_
 #define _FUSE_COMMON_H_
 
+#include "fuse_opt.h"
 #include <stdint.h>
 
 /** Major version of FUSE library interface */
@@ -65,25 +66,50 @@
     uint64_t fh;
 };
 
-/*
+/**
  * Create a FUSE mountpoint
  *
  * Returns a control file descriptor suitable for passing to
  * fuse_new()
  *
  * @param mountpoint the mount point path
- * @param opts a comma separated list of mount options.  Can be NULL.
+ * @param args argument vector
  * @return the control file descriptor on success, -1 on failure
  */
-int fuse_mount(const char *mountpoint, const char *opts);
+int fuse_mount(const char *mountpoint, struct fuse_args *args);
 
-/*
+/**
  * Umount a FUSE mountpoint
  *
  * @param mountpoint the mount point path
  */
 void fuse_unmount(const char *mountpoint);
 
+/**
+ * Parse common options
+ *
+ * The following options are parsed:
+ *
+ *   '-f'            foreground
+ *   '-d' '-odebug'  foreground, but keep the debug option
+ *   '-s'            single threaded
+ *   '-h' '--help'   help
+ *   '-ho'           help without header
+ *   '-ofsname=..'   file system name, if not present, then set to the program
+ *                   name
+ *
+ * All parameters may be NULL
+ *
+ * @param args argument vector
+ * @param mountpoint the returned mountpoint, should be freed after use
+ * @param multithreaded set to 1 unless the '-s' option is present
+ * @param foreground set to 1 if one of the relevant options is present
+ * @return 0 on success, -1 on failure
+ */
+int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
+                       int *multithreaded, int *foreground);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/fuse_compat.h b/include/fuse_compat.h
index 1fe68ec..220ef07 100644
--- a/include/fuse_compat.h
+++ b/include/fuse_compat.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
@@ -69,6 +69,8 @@
                             const struct fuse_operations_compat22 *op,
                             size_t op_size);
 
+int fuse_mount_compat22(const char *mountpoint, const char *opts);
+
 typedef int (*fuse_dirfil_t_compat) (fuse_dirh_t h, const char *name, int type);
 struct fuse_operations_compat2 {
     int (*getattr)     (const char *, struct stat *);
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index 74c483c..e45968c 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
@@ -928,25 +928,19 @@
  * Filesystem setup                                            *
  * ----------------------------------------------------------- */
 
-/**
- * Check whether a mount option is claimed by the low level library or
- * not
- *
- * @param opt the option to check
- * @return 1 if it is a low level library option, 0 otherwise
- */
+/* Deprecated, don't use */
 int fuse_lowlevel_is_lib_option(const char *opt);
 
 /**
  * Create a low level session
  *
- * @param opts the comma separated list of options
+ * @param args argument vector
  * @param op the low level filesystem operations
  * @param op_size sizeof(struct fuse_lowlevel_ops)
  * @param userdata user data
  * @return the created session object, or NULL on failure
  */
-struct fuse_session *fuse_lowlevel_new(const char *opts,
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
                                        const struct fuse_lowlevel_ops *op,
                                        size_t op_size, void *userdata);
 
@@ -1213,6 +1207,31 @@
 void fuse_chan_destroy(struct fuse_chan *ch);
 
 /* ----------------------------------------------------------- *
+ * Signal handling                                             *
+ * ----------------------------------------------------------- */
+
+/**
+ * Exit session on HUP, TERM and INT signals and ignore PIPE signal
+ *
+ * Stores session in a global variable.  May only be called once per
+ * process until fuse_remove_signal_handlers() is called.
+ *
+ * @param se the session to exit
+ * @return 0 on success, -1 on failure
+ */
+int fuse_set_signal_handlers(struct fuse_session *se);
+
+/**
+ * Restore default signal handlers
+ *
+ * Resets global session.  After this fuse_set_signal_handlers() may
+ * be called again.
+ *
+ * @param se the same session as given in fuse_set_signal_handlers()
+ */
+void fuse_remove_signal_handlers(struct fuse_session *se);
+
+/* ----------------------------------------------------------- *
  * Compatibility stuff                                         *
  * ----------------------------------------------------------- */
 
diff --git a/include/fuse_lowlevel_compat.h b/include/fuse_lowlevel_compat.h
index c2bd3c1..ccb7d01 100644
--- a/include/fuse_lowlevel_compat.h
+++ b/include/fuse_lowlevel_compat.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
@@ -23,3 +23,7 @@
 
 int fuse_reply_open_compat(fuse_req_t req,
                            const struct fuse_file_info_compat *fi);
+
+struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
+                                              const struct fuse_lowlevel_ops *op,
+                                              size_t op_size, void *userdata);
diff --git a/include/fuse_opt.h b/include/fuse_opt.h
index f3a06dd..ceec864 100644
--- a/include/fuse_opt.h
+++ b/include/fuse_opt.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
@@ -16,12 +16,6 @@
 #endif
 
 /**
- * Special 'offset' value.  In case of a match, the processing
- * function will be called with 'value' as the key
- */
-#define FUSE_OPT_OFFSET_KEY -1U
-
-/**
  * Option description
  *
  * This structure describes a single option, and and action associated
@@ -44,7 +38,7 @@
  *
  *  - 'offsetof(struct foo, member)'  actions i) and iii)
  *
- *  - FUSE_OPT_OFFSET_KEY             action ii)
+ *  - -1                              action ii)
  *
  * The 'offsetof()' macro is defined in the <stddef.h> header.
  *
@@ -82,7 +76,7 @@
 
     /**
      * Offset of variable within 'data' parameter of fuse_opt_parse()
-     * or FUSE_OPT_OFFSET_KEY
+     * or -1
      */
     unsigned long offset;
 
@@ -94,15 +88,10 @@
 };
 
 /**
- * Argument list
+ * Key option.  In case of a match, the processing function will be
+ * called with the specified key.
  */
-struct fuse_args {
-    /** Argument count */
-    int argc;
-
-    /* Argument vector.  NULL terminated */
-    char **argv;
-};
+#define FUSE_OPT_KEY(template, key) { template, -1U, key }
 
 /**
  * Last option.  An array of 'struct fuse_opt' must end with a NULL
@@ -110,6 +99,24 @@
  */
 #define FUSE_OPT_END { .template = NULL }
 
+/**
+ * Argument list
+ */
+struct fuse_args {
+    /** Argument count */
+    int argc;
+
+    /** Argument vector.  NULL terminated */
+    char **argv;
+
+    /** Is 'argv' allocated? */
+    int allocated;
+};
+
+/**
+ * Initializer for 'struct fuse_args'
+ */
+#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
 
 /**
  * Key value passed to the processing function if an option did not
@@ -131,7 +138,7 @@
  * This function is called if
  *    - option did not match any 'struct fuse_opt'
  *    - argument is a non-option
- *    - option did match and offset was set to FUSE_OPT_OFFSET_KEY
+ *    - option did match and offset was set to -1
  *
  * The 'arg' parameter will always contain the whole argument or
  * option including the parameter if exists.  A two-argument option
@@ -156,7 +163,10 @@
 /**
  * Option parsing function
  *
- * If 'argv' is NULL, the contents of 'outargs' will be used as input
+ * If 'args' was returned from a previous call to fuse_opt_parse() or
+ * it was constructed from 
+ *
+ * A NULL 'args' is equivalent to an empty argument vector
  *
  * A NULL 'opts' is equivalent to an 'opts' array containing a single
  * end marker
@@ -164,19 +174,14 @@
  * A NULL 'proc' is equivalent to a processing function always
  * returning '1'
  *
- * If outargs is NULL, then any output arguments are discarded
- *
- * @param argc is the input argument count
- * @param argv is the input argument vector
+ * @param args is the input and output argument list
  * @param data is the user data
  * @param opts is the option description array
  * @param proc is the processing function
- * @param outargs is the output argument list
  * @return -1 on error, 0 on success
  */
-int fuse_opt_parse(int argc, char *argv[], void *data,
-                   const struct fuse_opt opts[], fuse_opt_proc_t proc,
-                   struct fuse_args *outargs);
+int fuse_opt_parse(struct fuse_args *args, void *data,
+                   const struct fuse_opt opts[], fuse_opt_proc_t proc);
 
 /**
  * Add an option to a comma separated option list
diff --git a/kernel/configure.ac b/kernel/configure.ac
index c5fde42..a0c6bab 100644
--- a/kernel/configure.ac
+++ b/kernel/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(fuse-kernel, 2.5.0)
+AC_INIT(fuse-kernel, 2.5.0-pre2)
 AC_CONFIG_HEADERS([config.h])
 
 AC_PROG_INSTALL
diff --git a/kernel/dev.c b/kernel/dev.c
index f7ccb7b..073333f 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
diff --git a/kernel/dir.c b/kernel/dir.c
index fa4857f..084946d 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
diff --git a/kernel/file.c b/kernel/file.c
index 2486e7a..14c4f7c 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 4bf9a32..335b0c8 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h
index f494aff..191b97d 100644
--- a/kernel/fuse_kernel.h
+++ b/kernel/fuse_kernel.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
@@ -13,7 +13,7 @@
     This -- and only this -- header file may also be distributed under
     the terms of the BSD Licence as follows:
 
-    Copyright (C) 2005 Miklos Szeredi. All rights reserved.
+    Copyright (C) 2001-2006 Miklos Szeredi. All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
diff --git a/kernel/inode.c b/kernel/inode.c
index 464a519..af374c8 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2af57b9..d58cfed 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,6 +18,7 @@
 	fuse_mt.c		\
 	fuse_opt.c		\
 	fuse_session.c		\
+	fuse_signals.c		\
 	helper.c		\
 	$(mount_source)
 
diff --git a/lib/fuse.c b/lib/fuse.c
index 35dc227..d68ca5d 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
@@ -32,7 +32,6 @@
 #define FUSE_UNKNOWN_INO 0xffffffff
 
 struct fuse_config {
-    char *llopts;
     unsigned int uid;
     unsigned int gid;
     unsigned int  umask;
@@ -1807,20 +1806,13 @@
     fuse_getcontext = func;
 }
 
-static int fuse_lib_opt_proc(void *data, const char *arg, int key,
-                             struct fuse_args *outargs)
-{
-    struct fuse_config *conf = data;
-    (void) key;
-    (void) outargs;
-    return fuse_opt_add_opt(&conf->llopts, arg);
-}
-
 #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
 
 static const struct fuse_opt fuse_lib_opts[] = {
-    { "debug", FUSE_OPT_OFFSET_KEY, 0 },
+    FUSE_OPT_KEY("debug", 0),
+    FUSE_OPT_KEY("-d", 0),
     FUSE_LIB_OPT("debug",                 debug, 1),
+    FUSE_LIB_OPT("-d",                    debug, 1),
     FUSE_LIB_OPT("hard_remove",           hard_remove, 1),
     FUSE_LIB_OPT("use_ino",               use_ino, 1),
     FUSE_LIB_OPT("readdir_ino",           readdir_ino, 1),
@@ -1844,7 +1836,7 @@
         fuse_opt_match(fuse_lib_opts, opt);
 }
 
-struct fuse *fuse_new_common(int fd, const char *opts,
+struct fuse *fuse_new_common(int fd, struct fuse_args *args,
                              const struct fuse_operations *op,
                              size_t op_size, int compat)
 {
@@ -1867,12 +1859,8 @@
     f->conf.attr_timeout = 1.0;
     f->conf.negative_timeout = 0.0;
 
-    if (opts) {
-        const char *argv[] = { "", "-o", opts, NULL };
-        if (fuse_opt_parse(3, (char **) argv, &f->conf,
-                           fuse_lib_opts, fuse_lib_opt_proc, NULL) == -1)
+    if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, NULL) == -1)
             goto out_free;
-    }
 
 #ifdef __FreeBSD__
     /*
@@ -1882,9 +1870,7 @@
     f->conf.readdir_ino = 1;
 #endif
 
-    f->se = fuse_lowlevel_new(f->conf.llopts, &fuse_path_ops,
-                              sizeof(fuse_path_ops), f);
-    free(f->conf.llopts);
+    f->se = fuse_lowlevel_new(args, &fuse_path_ops, sizeof(fuse_path_ops), f);
     if (f->se == NULL)
         goto out_free;
 
@@ -1952,10 +1938,10 @@
     return NULL;
 }
 
-struct fuse *fuse_new(int fd, const char *opts,
+struct fuse *fuse_new(int fd, struct fuse_args *args,
                       const struct fuse_operations *op, size_t op_size)
 {
-    return fuse_new_common(fd, opts, op, op_size, 0);
+    return fuse_new_common(fd, args, op, op_size, 0);
 }
 
 void fuse_destroy(struct fuse *f)
@@ -2080,19 +2066,39 @@
     return err;
 }
 
+static struct fuse *fuse_new_common_compat(int fd, const char *opts,
+                                           const struct fuse_operations *op,
+                                           size_t op_size, int compat)
+{
+    struct fuse *f;
+    struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+
+    if (opts &&
+        (fuse_opt_add_arg(&args, "") == -1 ||
+         fuse_opt_add_arg(&args, "-o") == -1 ||
+         fuse_opt_add_arg(&args, opts) == -1)) {
+        fuse_opt_free_args(&args);
+        return NULL;
+    }
+    f = fuse_new_common(fd, &args, op, op_size, compat);
+    fuse_opt_free_args(&args);
+
+    return f;
+}
+
 struct fuse *fuse_new_compat22(int fd, const char *opts,
                                const struct fuse_operations_compat22 *op,
                                size_t op_size)
 {
-    return fuse_new_common(fd, opts, (struct fuse_operations *) op,
-                           op_size, 22);
+    return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
+                                  op_size, 22);
 }
 
 struct fuse *fuse_new_compat2(int fd, const char *opts,
                               const struct fuse_operations_compat2 *op)
 {
-    return fuse_new_common(fd, opts, (struct fuse_operations *) op,
-                           sizeof(struct fuse_operations_compat2), 21);
+    return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
+                                  sizeof(struct fuse_operations_compat2), 21);
 }
 
 struct fuse *fuse_new_compat1(int fd, int flags,
@@ -2101,8 +2107,8 @@
     const char *opts = NULL;
     if (flags & FUSE_DEBUG_COMPAT1)
         opts = "debug";
-    return fuse_new_common(fd, opts, (struct fuse_operations *) op,
-                           sizeof(struct fuse_operations_compat1), 11);
+    return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
+                                  sizeof(struct fuse_operations_compat1), 11);
 }
 
 __asm__(".symver fuse_exited,__fuse_exited@");
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 281ddc4..ea1eefe 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
@@ -19,6 +19,6 @@
 
 struct fuse_session *fuse_get_session(struct fuse *f);
 
-struct fuse *fuse_new_common(int fd, const char *opts,
+struct fuse *fuse_new_common(int fd, struct fuse_args *args, 
                              const struct fuse_operations *op,
                              size_t op_size, int compat);
diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c
index fbe3943..d58c8b2 100644
--- a/lib/fuse_kern_chan.c
+++ b/lib/fuse_kern_chan.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c
index f9a05d8..1609bfc 100644
--- a/lib/fuse_loop.c
+++ b/lib/fuse_loop.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c
index 3566c60..540607b 100644
--- a/lib/fuse_loop_mt.c
+++ b/lib/fuse_loop_mt.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 6913d63..d1b4b36 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
@@ -895,6 +895,7 @@
 
 static struct fuse_opt fuse_ll_opts[] = {
     { "debug", offsetof(struct fuse_ll, debug), 1 },
+    { "-d", offsetof(struct fuse_ll, debug), 1 },
     { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
     FUSE_OPT_END
 };
@@ -924,7 +925,7 @@
     free(f);
 }
 
-struct fuse_session *fuse_lowlevel_new(const char *opts,
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
                                        const struct fuse_lowlevel_ops *op,
                                        size_t op_size, void *userdata)
 {
@@ -946,12 +947,8 @@
         goto out;
     }
 
-    if (opts) {
-        const char *argv[] = { "", "-o", opts, NULL };
-        if (fuse_opt_parse(3, (char **) argv, f, fuse_ll_opts,
-                           fuse_ll_opt_proc, NULL) == -1)
-            goto out_free;
-    }
+    if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
+        goto out_free;
 
     memcpy(&f->op, op, op_size);
     f->owner = getuid();
@@ -1015,8 +1012,28 @@
     return fuse_reply_statfs(req, &newbuf);
 }
 
+struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
+                                              const struct fuse_lowlevel_ops *op,
+                                              size_t op_size, void *userdata)
+{
+    struct fuse_session *se;
+    struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+
+    if (opts &&
+        (fuse_opt_add_arg(&args, "") == -1 ||
+         fuse_opt_add_arg(&args, "-o") == -1 ||
+         fuse_opt_add_arg(&args, opts) == -1)) {
+        fuse_opt_free_args(&args);
+        return NULL;
+    }
+    se = fuse_lowlevel_new(&args, op, op_size, userdata);
+    fuse_opt_free_args(&args);
+
+    return se;
+}
 
 __asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
 __asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
+__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
 
 #endif /* __FreeBSD__ */
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c
index f56fe62..8a8964f 100644
--- a/lib/fuse_mt.c
+++ b/lib/fuse_mt.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index d1b3259..2ac499c 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
@@ -27,12 +27,13 @@
 
 void fuse_opt_free_args(struct fuse_args *args)
 {
-    if (args && args->argv) {
+    if (args && args->argv && args->allocated) {
         int i;
         for (i = 0; i < args->argc; i++)
             free(args->argv[i]);
         free(args->argv);
         args->argv = NULL;
+        args->allocated = 0;
     }
 }
 
@@ -44,12 +45,18 @@
 
 int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
 {
-    char **newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
-    char *newarg = newargv ? strdup(arg) : NULL;
+    char **newargv;
+    char *newarg;
+
+    assert(!args->argv || args->allocated);
+
+    newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
+    newarg = newargv ? strdup(arg) : NULL;
     if (!newargv || !newarg)
         return alloc_failed();
 
     args->argv = newargv;
+    args->allocated = 1;
     args->argv[args->argc++] = newarg;
     args->argv[args->argc] = NULL;
     return 0;
@@ -183,7 +190,7 @@
                        const struct fuse_opt *opt, unsigned sep,
                        const char *arg, int iso)
 {
-    if (opt->offset == FUSE_OPT_OFFSET_KEY) {
+    if (opt->offset == -1U) {
         if (call_proc(ctx, arg, opt->value, iso) == -1)
             return -1;
     } else {
@@ -324,27 +331,29 @@
     return 0;
 }
 
-int fuse_opt_parse(int argc, char *argv[], void *data,
-                   const struct fuse_opt opts[], fuse_opt_proc_t proc,
-                   struct fuse_args *outargs)
+int fuse_opt_parse(struct fuse_args *args, void *data,
+                   const struct fuse_opt opts[], fuse_opt_proc_t proc)
 {
     int res;
     struct fuse_opt_context ctx = {
-        .argc = argv ? argc : outargs->argc,
-        .argv = argv ? argv : outargs->argv,
         .data = data,
         .opt = opts,
         .proc = proc,
     };
 
-    res = opt_parse(&ctx);
-    if (!argv)
-        fuse_opt_free_args(outargs);
-    free(ctx.opts);
-    if (res != -1 && outargs)
-        *outargs = ctx.outargs;
-    else
-        fuse_opt_free_args(&ctx.outargs);
+    if (!args || !args->argv || !args->argc)
+        return 0;
 
+    ctx.argc = args->argc;
+    ctx.argv = args->argv;
+
+    res = opt_parse(&ctx);
+    if (res != -1) {
+        struct fuse_args tmp = *args;
+        *args = ctx.outargs;
+        ctx.outargs = tmp;
+    }
+    free(ctx.opts);
+    fuse_opt_free_args(&ctx.outargs);
     return res;
 }
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index f88d6e5..4ea792a 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB
diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c
new file mode 100644
index 0000000..38f407d
--- /dev/null
+++ b/lib/fuse_signals.c
@@ -0,0 +1,72 @@
+/*
+    FUSE: Filesystem in Userspace
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
+
+    This program can be distributed under the terms of the GNU LGPL.
+    See the file COPYING.LIB
+*/
+
+#include "fuse_lowlevel.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static struct fuse_session *fuse_instance;
+
+static void exit_handler(int sig)
+{
+    (void) sig;
+    if (fuse_instance)
+        fuse_session_exit(fuse_instance);
+}
+
+static int set_one_signal_handler(int sig, void (*handler)(int))
+{
+    struct sigaction sa;
+    struct sigaction old_sa;
+
+    memset(&sa, 0, sizeof(struct sigaction));
+    sa.sa_handler = handler;
+    sigemptyset(&(sa.sa_mask));
+    sa.sa_flags = 0;
+
+    if (sigaction(sig, NULL, &old_sa) == -1) {
+        perror("FUSE: cannot get old signal handler");
+        return -1;
+    }
+
+    if (old_sa.sa_handler == SIG_DFL &&
+        sigaction(sig, &sa, NULL) == -1) {
+        perror("Cannot set signal handler");
+        return -1;
+    }
+    return 0;
+}
+
+int fuse_set_signal_handlers(struct fuse_session *se)
+{
+    if (set_one_signal_handler(SIGHUP, exit_handler) == -1 ||
+        set_one_signal_handler(SIGINT, exit_handler) == -1 ||
+        set_one_signal_handler(SIGTERM, exit_handler) == -1 ||
+        set_one_signal_handler(SIGPIPE, SIG_IGN) == -1)
+        return -1;
+
+    fuse_instance = se;
+    return 0;
+}
+
+void fuse_remove_signal_handlers(struct fuse_session *se)
+{
+    if (fuse_instance != se)
+        fprintf(stderr,
+                "fuse: fuse_remove_signal_handlers: unknown session\n");
+    else
+        fuse_instance = NULL;
+
+    set_one_signal_handler(SIGHUP, SIG_DFL);
+    set_one_signal_handler(SIGINT, SIG_DFL);
+    set_one_signal_handler(SIGTERM, SIG_DFL);
+    set_one_signal_handler(SIGPIPE, SIG_DFL);
+}
+
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index e610b88..9927158 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -12,7 +12,6 @@
 		fuse_main;
 		fuse_main_compat1;
 		fuse_main_compat2;
-		fuse_mount;
 		fuse_mount_compat1;
 		fuse_new_compat1;
 		fuse_new_compat2;
@@ -38,7 +37,6 @@
 		fuse_dirent_size;
 		fuse_kern_chan_new;
 		fuse_lowlevel_is_lib_option;
-		fuse_lowlevel_new;
 		fuse_reply_attr;
 		fuse_reply_buf;
 		fuse_reply_entry;
@@ -63,8 +61,12 @@
 
 FUSE_2.5 {
 	global:
+		fuse_lowlevel_new;
+		fuse_lowlevel_new_compat;
 		fuse_main_real;
 		fuse_main_real_compat22;
+		fuse_mount;
+		fuse_mount_compat22;
 		fuse_new;
 		fuse_new_compat22;
 		fuse_opt_parse;
@@ -72,6 +74,8 @@
 		fuse_opt_add_arg;
 		fuse_opt_free_args;
 		fuse_opt_match;
+		fuse_parse_cmdline;
+		fuse_remove_signal_handlers;
 		fuse_reply_create;
 		fuse_reply_open;
 		fuse_reply_open_compat;
@@ -79,6 +83,7 @@
 		fuse_reply_statfs_compat;
 		fuse_setup;
 		fuse_setup_compat22;
+		fuse_set_signal_handlers;
 
 	local:
 		 *;
diff --git a/lib/helper.c b/lib/helper.c
index 38f048b..82be718 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
@@ -8,6 +8,7 @@
 
 #include "fuse_i.h"
 #include "fuse_opt.h"
+#include "fuse_lowlevel.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -15,9 +16,6 @@
 #include <unistd.h>
 #include <string.h>
 #include <limits.h>
-#include <signal.h>
-
-static struct fuse *fuse_instance;
 
 static void usage(const char *progname)
 {
@@ -54,105 +52,33 @@
             );
 }
 
-static void exit_handler(int sig)
-{
-    (void) sig;
-    if (fuse_instance != NULL)
-        fuse_exit(fuse_instance);
-}
-
-static int set_one_signal_handler(int sig, void (*handler)(int))
-{
-    struct sigaction sa;
-    struct sigaction old_sa;
-
-    memset(&sa, 0, sizeof(struct sigaction));
-    sa.sa_handler = handler;
-    sigemptyset(&(sa.sa_mask));
-    sa.sa_flags = 0;
-
-    if (sigaction(sig, NULL, &old_sa) == -1) {
-        perror("FUSE: cannot get old signal handler");
-        return -1;
-    }
-
-    if (old_sa.sa_handler == SIG_DFL &&
-        sigaction(sig, &sa, NULL) == -1) {
-        perror("Cannot set signal handler");
-        return -1;
-    }
-    return 0;
-}
-
-static int set_signal_handlers(void)
-{
-    if (set_one_signal_handler(SIGHUP, exit_handler) == -1 ||
-        set_one_signal_handler(SIGINT, exit_handler) == -1 ||
-        set_one_signal_handler(SIGTERM, exit_handler) == -1 ||
-        set_one_signal_handler(SIGPIPE, SIG_IGN) == -1)
-        return -1;
-
-    return 0;
-}
-
 enum  {
     KEY_HELP,
     KEY_HELP_NOHEADER,
-    KEY_DEBUG,
-    KEY_KERN,
-    KEY_ALLOW_ROOT,
-    KEY_RO,
+    KEY_KEEP,
 };
 
 struct helper_opts {
-    const char *progname;
     int singlethread;
     int foreground;
-    int allow_other;
-    int allow_root;
     int fsname;
-    char *kernel_opts;
-    char *lib_opts;
     char *mountpoint;
 };
 
 #define FUSE_HELPER_OPT(t, p) { t, offsetof(struct helper_opts, p), 1 }
-#define FUSE_HELPER_KEY(t, k)    { t, FUSE_OPT_OFFSET_KEY, k }
 
 static const struct fuse_opt fuse_helper_opts[] = {
-    FUSE_HELPER_OPT("-d",                       foreground),
-    FUSE_HELPER_OPT("debug",                    foreground),
-    FUSE_HELPER_OPT("-f",			foreground),
-    FUSE_HELPER_OPT("-s",			singlethread),
-    FUSE_HELPER_OPT("allow_other",              allow_other),
-    FUSE_HELPER_OPT("allow_root",               allow_root),
-    FUSE_HELPER_OPT("fsname=",                  fsname),
+    FUSE_HELPER_OPT("-d",          foreground),
+    FUSE_HELPER_OPT("debug",       foreground),
+    FUSE_HELPER_OPT("-f",	   foreground),
+    FUSE_HELPER_OPT("-s",	   singlethread),
+    FUSE_HELPER_OPT("fsname=",     fsname),
 
-    FUSE_HELPER_KEY("-h",                       KEY_HELP),
-    FUSE_HELPER_KEY("--help",                   KEY_HELP),
-    FUSE_HELPER_KEY("-ho",                      KEY_HELP_NOHEADER),
-    FUSE_HELPER_KEY("-d",                       KEY_DEBUG),
-    FUSE_HELPER_KEY("debug",                    KEY_DEBUG),
-    FUSE_HELPER_KEY("allow_other",              KEY_KERN),
-    FUSE_HELPER_KEY("allow_root",               KEY_ALLOW_ROOT),
-    FUSE_HELPER_KEY("nonempty",                 KEY_KERN),
-    FUSE_HELPER_KEY("default_permissions",      KEY_KERN),
-    FUSE_HELPER_KEY("fsname=",                  KEY_KERN),
-    FUSE_HELPER_KEY("large_read",               KEY_KERN),
-    FUSE_HELPER_KEY("max_read=",                KEY_KERN),
-    FUSE_HELPER_KEY("-r",                       KEY_RO),
-    FUSE_HELPER_KEY("ro",                       KEY_KERN),
-    FUSE_HELPER_KEY("rw",                       KEY_KERN),
-    FUSE_HELPER_KEY("suid",                     KEY_KERN),
-    FUSE_HELPER_KEY("nosuid",                   KEY_KERN),
-    FUSE_HELPER_KEY("dev",                      KEY_KERN),
-    FUSE_HELPER_KEY("nodev",                    KEY_KERN),
-    FUSE_HELPER_KEY("exec",                     KEY_KERN),
-    FUSE_HELPER_KEY("noexec",                   KEY_KERN),
-    FUSE_HELPER_KEY("async",                    KEY_KERN),
-    FUSE_HELPER_KEY("sync",                     KEY_KERN),
-    FUSE_HELPER_KEY("atime",                    KEY_KERN),
-    FUSE_HELPER_KEY("noatime",                  KEY_KERN),
+    FUSE_OPT_KEY("-h",          KEY_HELP),
+    FUSE_OPT_KEY("--help",      KEY_HELP),
+    FUSE_OPT_KEY("-ho",         KEY_HELP_NOHEADER),
+    FUSE_OPT_KEY("-d",          KEY_KEEP),
+    FUSE_OPT_KEY("debug",       KEY_KEEP),
     FUSE_OPT_END
 };
 
@@ -161,83 +87,78 @@
 {
     struct helper_opts *hopts = data;
 
-    (void) outargs;
-
     switch (key) {
     case KEY_HELP:
     case KEY_HELP_NOHEADER:
-        usage(key == KEY_HELP ? hopts->progname : NULL);
+        usage(key == KEY_HELP ? outargs->argv[0] : NULL);
         exit(1);
 
-    case FUSE_OPT_KEY_OPT:
-        return fuse_opt_add_opt(&hopts->lib_opts, arg);
-
     case FUSE_OPT_KEY_NONOPT:
-        if (hopts->mountpoint)
-            break;
+        if (!hopts->mountpoint)
+            return fuse_opt_add_opt(&hopts->mountpoint, arg);
 
-        return fuse_opt_add_opt(&hopts->mountpoint, arg);
-
-    case KEY_DEBUG:
-        return fuse_opt_add_opt(&hopts->lib_opts, "debug");
-
-    case KEY_ALLOW_ROOT:
-        if (fuse_opt_add_opt(&hopts->kernel_opts, "allow_other") == -1 ||
-            fuse_opt_add_opt(&hopts->lib_opts, "allow_root") == -1)
-            return -1;
-        return 0;
-
-    case KEY_RO:
-        arg = "ro";
         /* fall through */
 
-    case KEY_KERN:
-        return fuse_opt_add_opt(&hopts->kernel_opts, arg);
+    default:
+    case KEY_KEEP:
+        return 1;
     }
-
-    fprintf(stderr, "fuse: invalid option `%s'\n", arg);
-    return -1;
 }
 
-static int fuse_parse_cmdline(int argc, const char *argv[],
-                              struct helper_opts *hopts)
+static int add_default_fsname(const char *progname, struct fuse_args *args)
 {
     int res;
+    char *fsname_opt;
+    const char *basename = strrchr(progname, '/');
+    if (basename == NULL)
+        basename = progname;
+    else if (basename[1] != '\0')
+        basename++;
 
-    hopts->progname = argv[0];
-    res = fuse_opt_parse(argc, (char **) argv, hopts, fuse_helper_opts,
-                         fuse_helper_opt_proc, NULL);
+    fsname_opt = (char *) malloc(strlen(basename) + 64);
+    if (fsname_opt == NULL) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        return -1;
+    }
+    sprintf(fsname_opt, "-ofsname=%s", basename);
+    res = fuse_opt_add_arg(args, fsname_opt);
+    free(fsname_opt);
+    return res;
+}
+
+int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
+                       int *multithreaded, int *foreground)
+{
+    int res;
+    struct helper_opts hopts;
+
+    memset(&hopts, 0, sizeof(hopts));
+    res = fuse_opt_parse(args, &hopts, fuse_helper_opts, fuse_helper_opt_proc);
     if (res == -1)
         return -1;
 
-    if (hopts->allow_other && hopts->allow_root) {
-        fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
-        return -1;
-    }
-
-    if (!hopts->fsname) {
-        char *fsname_opt;
-        const char *basename = strrchr(argv[0], '/');
-        if (basename == NULL)
-            basename = argv[0];
-        else if (basename[1] != '\0')
-            basename++;
-
-        fsname_opt = (char *) malloc(strlen(basename) + 64);
-        if (fsname_opt == NULL) {
-            fprintf(stderr, "fuse: memory allocation failed\n");
-            return -1;
-        }
-        sprintf(fsname_opt, "fsname=%s", basename);
-        res = fuse_opt_add_opt(&hopts->kernel_opts, fsname_opt);
-        free(fsname_opt);
+    if (!hopts.fsname) {
+        res = add_default_fsname(args->argv[0], args);
         if (res == -1)
-            return -1;
+            goto err;
     }
+    if (mountpoint)
+        *mountpoint = hopts.mountpoint;
+    else
+        free(hopts.mountpoint);
+
+    if (multithreaded)
+        *multithreaded = !hopts.singlethread;
+    if (foreground)
+        *foreground = hopts.foreground;
     return 0;
+
+ err:
+    free(hopts.mountpoint);
+    return -1;
 }
 
-static struct fuse *fuse_setup_common(int argc, char *argv[],
+static struct fuse *fuse_setup_common(struct fuse_args *args,
                                       const struct fuse_operations *op,
                                       size_t op_size,
                                       char **mountpoint,
@@ -246,28 +167,22 @@
                                       int compat)
 {
     struct fuse *fuse;
-    struct helper_opts hopts;
+    int foreground;
     int res;
 
-    if (fuse_instance != NULL) {
-        fprintf(stderr, "fuse: fuse_setup() called twice\n");
-        return NULL;
-    }
-
-    memset(&hopts, 0, sizeof(hopts));
-    res = fuse_parse_cmdline(argc, (const char **) argv, &hopts);
+    res = fuse_parse_cmdline(args, mountpoint, multithreaded, &foreground);
     if (res == -1)
-        goto err_free;
+        return NULL;
 
-    *fd = fuse_mount(hopts.mountpoint, hopts.kernel_opts);
+    *fd = fuse_mount(*mountpoint, args);
     if (*fd == -1)
         goto err_free;
 
-    fuse = fuse_new_common(*fd, hopts.lib_opts, op, op_size, compat);
+    fuse = fuse_new_common(*fd, args, op, op_size, compat);
     if (fuse == NULL)
         goto err_unmount;
 
-    if (!hopts.foreground) {
+    if (!foreground) {
         res = daemon(0, 0);
         if (res == -1) {
             perror("fuse: failed to daemonize program\n");
@@ -282,52 +197,41 @@
         }
     }
 
-    res = set_signal_handlers();
+    res = fuse_set_signal_handlers(fuse_get_session(fuse));
     if (res == -1)
         goto err_destroy;
 
-    *mountpoint = hopts.mountpoint;
-    *multithreaded = !hopts.singlethread;
-    fuse_instance = fuse;
-    free(hopts.kernel_opts);
-    free(hopts.lib_opts);
     return fuse;
 
  err_destroy:
     fuse_destroy(fuse);
  err_unmount:
-    fuse_unmount(hopts.mountpoint);
+    fuse_unmount(*mountpoint);
  err_free:
-    free(hopts.mountpoint);
-    free(hopts.kernel_opts);
-    free(hopts.lib_opts);
+    free(*mountpoint);
     return NULL;
 }
 
-struct fuse *fuse_setup(int argc, char *argv[],
-                          const struct fuse_operations *op,
-                          size_t op_size, char **mountpoint,
-                          int *multithreaded, int *fd)
+struct fuse *fuse_setup(struct fuse_args *args,
+                        const struct fuse_operations *op,
+                        size_t op_size, char **mountpoint,
+                        int *multithreaded, int *fd)
 {
-    return fuse_setup_common(argc, argv, op, op_size, mountpoint,
-                             multithreaded, fd, 0);
+    return fuse_setup_common(args, op, op_size, mountpoint, multithreaded, fd,
+                             0);
 }
 
 void fuse_teardown(struct fuse *fuse, int fd, char *mountpoint)
 {
     (void) fd;
 
-    if (fuse_instance != fuse)
-        fprintf(stderr, "fuse: fuse_teardown() with unknown fuse object\n");
-    else
-        fuse_instance = NULL;
-
+    fuse_remove_signal_handlers(fuse_get_session(fuse));
     fuse_unmount(mountpoint);
     fuse_destroy(fuse);
     free(mountpoint);
 }
 
-static int fuse_main_common(int argc, char *argv[],
+static int fuse_main_common(struct fuse_args *args,
                             const struct fuse_operations *op, size_t op_size,
                             int compat)
 {
@@ -337,8 +241,8 @@
     int res;
     int fd;
 
-    fuse = fuse_setup_common(argc, argv, op, op_size, &mountpoint,
-                             &multithreaded, &fd, compat);
+    fuse = fuse_setup_common(args, op, op_size, &mountpoint, &multithreaded,
+                             &fd, compat);
     if (fuse == NULL)
         return 1;
 
@@ -357,7 +261,10 @@
 int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
                    size_t op_size)
 {
-    return fuse_main_common(argc, argv, op, op_size, 0);
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    int res = fuse_main_common(&args, op, op_size, 0);
+    fuse_opt_free_args(&args);
+    return res;
 }
 
 #undef fuse_main
@@ -376,8 +283,12 @@
                                  size_t op_size, char **mountpoint,
                                  int *multithreaded, int *fd)
 {
-    return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
-                             op_size, mountpoint, multithreaded, fd, 22);
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    struct fuse *f =
+        fuse_setup_common(&args, (struct fuse_operations *) op,
+                          op_size, mountpoint, multithreaded, fd, 22);
+    fuse_opt_free_args(&args);
+    return f;
 }
 
 struct fuse *fuse_setup_compat2(int argc, char *argv[],
@@ -385,31 +296,44 @@
                                  char **mountpoint, int *multithreaded,
                                  int *fd)
 {
-    return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
-                             sizeof(struct fuse_operations_compat2),
-                             mountpoint, multithreaded, fd, 21);
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    struct fuse *f =
+        fuse_setup_common(&args, (struct fuse_operations *) op,
+                          sizeof(struct fuse_operations_compat2),
+                          mountpoint, multithreaded, fd, 21);
+    fuse_opt_free_args(&args);
+    return f;
 }
 
 int fuse_main_real_compat22(int argc, char *argv[],
                             const struct fuse_operations_compat22 *op,
                             size_t op_size)
 {
-    return fuse_main_common(argc, argv, (struct fuse_operations *) op,
-                            op_size, 22);
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    int res =
+        fuse_main_common(&args, (struct fuse_operations *) op, op_size, 22);
+    fuse_opt_free_args(&args);
+    return res;
 }
 
 void fuse_main_compat1(int argc, char *argv[],
                       const struct fuse_operations_compat1 *op)
 {
-    fuse_main_common(argc, argv, (struct fuse_operations *) op,
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    fuse_main_common(&args, (struct fuse_operations *) op,
                      sizeof(struct fuse_operations_compat1), 11);
+    fuse_opt_free_args(&args);
 }
 
 int fuse_main_compat2(int argc, char *argv[],
                       const struct fuse_operations_compat2 *op)
 {
-    return fuse_main_common(argc, argv, (struct fuse_operations *) op,
-                            sizeof(struct fuse_operations_compat2), 21);
+    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+    int res =
+        fuse_main_common(&args, (struct fuse_operations *) op,
+                         sizeof(struct fuse_operations_compat2), 21);
+    fuse_opt_free_args(&args);
+    return res;
 }
 
 __asm__(".symver fuse_setup_compat2,__fuse_setup@");
diff --git a/lib/mount.c b/lib/mount.c
index 787c448..bd1b66f 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -1,17 +1,19 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU LGPL.
     See the file COPYING.LIB.
 */
 
 #include "fuse.h"
+#include "fuse_opt.h"
 #include "fuse_compat.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <stddef.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/socket.h>
@@ -21,6 +23,64 @@
 #define FUSERMOUNT_PROG         "fusermount"
 #define FUSE_COMMFD_ENV         "_FUSE_COMMFD"
 
+enum {
+    KEY_KERN,
+    KEY_ALLOW_ROOT,
+    KEY_RO,
+};
+
+struct mount_opts {
+    int allow_other;
+    int allow_root;
+    char *kernel_opts;
+};
+
+static const struct fuse_opt fuse_mount_opts[] = {
+    { "allow_other", offsetof(struct mount_opts, allow_other), 1 },
+    { "allow_root", offsetof(struct mount_opts, allow_root), 1 },
+    FUSE_OPT_KEY("allow_other",         KEY_KERN),
+    FUSE_OPT_KEY("allow_root",          KEY_ALLOW_ROOT),
+    FUSE_OPT_KEY("nonempty",            KEY_KERN),
+    FUSE_OPT_KEY("default_permissions", KEY_KERN),
+    FUSE_OPT_KEY("fsname=",             KEY_KERN),
+    FUSE_OPT_KEY("large_read",          KEY_KERN),
+    FUSE_OPT_KEY("max_read=",           KEY_KERN),
+    FUSE_OPT_KEY("-r",                  KEY_RO),
+    FUSE_OPT_KEY("ro",                  KEY_KERN),
+    FUSE_OPT_KEY("rw",                  KEY_KERN),
+    FUSE_OPT_KEY("suid",                KEY_KERN),
+    FUSE_OPT_KEY("nosuid",              KEY_KERN),
+    FUSE_OPT_KEY("dev",                 KEY_KERN),
+    FUSE_OPT_KEY("nodev",               KEY_KERN),
+    FUSE_OPT_KEY("exec",                KEY_KERN),
+    FUSE_OPT_KEY("noexec",              KEY_KERN),
+    FUSE_OPT_KEY("async",               KEY_KERN),
+    FUSE_OPT_KEY("sync",                KEY_KERN),
+    FUSE_OPT_KEY("atime",               KEY_KERN),
+    FUSE_OPT_KEY("noatime",             KEY_KERN),
+};
+
+static int fuse_mount_opt_proc(void *data, const char *arg, int key,
+                               struct fuse_args *outargs)
+{
+    struct mount_opts *mo = data;
+
+    switch (key) {
+    case KEY_ALLOW_ROOT:
+        if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 ||
+            fuse_opt_add_arg(outargs, "-oallow_root") == -1)
+            return -1;
+        return 0;
+
+    case KEY_RO:
+        arg = "ro";
+        /* fall through */
+
+    case KEY_KERN:
+        return fuse_opt_add_opt(&mo->kernel_opts, arg);
+    }
+    return 1;
+}
 
 /* return value:
  * >= 0  => fd
@@ -98,7 +158,7 @@
     waitpid(pid, NULL, 0);
 }
 
-int fuse_mount(const char *mountpoint, const char *opts)
+int fuse_mount_compat22(const char *mountpoint, const char *opts)
 {
     const char *mountprog = FUSERMOUNT_PROG;
     int fds[2], pid;
@@ -159,9 +219,33 @@
     return rv;
 }
 
+int fuse_mount(const char *mountpoint, struct fuse_args *args)
+{
+    struct mount_opts mo;
+    int res = -1;
+
+    memset(&mo, 0, sizeof(mo));
+
+    if (args &&
+        fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
+        return -1;
+
+    if (mo.allow_other && mo.allow_root) {
+        fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
+        goto out;
+    }
+
+    res = fuse_mount_compat22(mountpoint, mo.kernel_opts);
+ out:
+    free(mo.kernel_opts);
+    return res;
+}
+
 int fuse_mount_compat1(const char *mountpoint, const char *args[])
 {
     /* just ignore mount args for now */
     (void) args;
-    return fuse_mount(mountpoint, NULL);
+    return fuse_mount_compat22(mountpoint, NULL);
 }
+
+__asm__(".symver fuse_mount_compat22,fuse_mount@");
diff --git a/util/fusermount.c b/util/fusermount.c
index 13305d1..63a6068 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.