? compile
? gnome-vfs-zip
? po
? stamp-h1.in
? stamp-h2.in
? imported/fnmatch/Makefile
? imported/fnmatch/Makefile.in
Index: INSTALL
===================================================================
RCS file: /cvs/gnome/gnome-vfs/INSTALL,v
retrieving revision 1.2
diff -U5 -r1.2 INSTALL
--- INSTALL	16 Nov 2004 09:26:35 -0000	1.2
+++ INSTALL	11 Aug 2005 03:46:00 -0000
@@ -1,6 +1,6 @@
-Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
 Foundation, Inc.
 
    This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-vfs/configure.in,v
retrieving revision 1.384
diff -U5 -r1.384 configure.in
--- configure.in	25 Jul 2005 21:20:20 -0000	1.384
+++ configure.in	11 Aug 2005 03:46:00 -0000
@@ -155,10 +155,11 @@
 	AC_MSG_ERROR([Your Gettext installation doesn't seem to support ngettext to handle translation of plural forms. Please install GNU Gettext])
 fi;
 
 AC_SEARCH_LIBS(gethostent, nsl)
 AC_SEARCH_LIBS(setsockopt, socket)
+AC_SEARCH_LIBS(openpty, util)
 
 AC_FUNC_ALLOCA
 AC_CHECK_FUNCS(getdtablesize open64 lseek64 statfs statvfs seteuid setegid setresuid setresgid readdir_r mbrtowc inet_pton getdelim sysctlbyname poll posix_fadvise fchmod)
 
 dnl Volume monitor stuff			     
Index: libgnomevfs/gnome-vfs-mime.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-mime.c,v
retrieving revision 1.57
diff -U5 -r1.57 gnome-vfs-mime.c
--- libgnomevfs/gnome-vfs-mime.c	23 Jun 2005 11:21:03 -0000	1.57
+++ libgnomevfs/gnome-vfs-mime.c	11 Aug 2005 03:46:01 -0000
@@ -34,10 +34,12 @@
 #include "gnome-vfs-mime-info.h"
 #include "gnome-vfs-module-shared.h"
 #include "gnome-vfs-ops.h"
 #include "gnome-vfs-result.h"
 #include "gnome-vfs-uri.h"
+#include "gnome-vfs-utils.h"
+#include "gnome-vfs-volume-monitor-private.h"
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 
 #include <glib/gstdio.h>
@@ -53,18 +55,18 @@
 	time_t last_checked;
 	guint check_interval;
 	GHashTable *records;
 };
 
-
 #ifdef G_THREADS_ENABLED
 
 /* We lock this mutex whenever we modify global state in this module.  */
 G_LOCK_DEFINE_STATIC (mime_mutex);
 
 #endif /* G_LOCK_DEFINE_STATIC */
 
+GnomeVFSVolumeMonitor *volume_monitor = NULL;
 
 /**
  * gnome_vfs_mime_shutdown:
  *
  * Deprecated: This function doesn't have to be called as the
@@ -365,10 +367,30 @@
 	}
 
 	/* single out special file types */
 	if (optional_stat_info && !S_ISREG(optional_stat_info->st_mode)) {
 		if (S_ISDIR(optional_stat_info->st_mode)) {
+
+			/* Check for mount points */
+			if (!suffix_only) {
+				GnomeVFSDrive *drive = NULL;
+				GnomeVFSVolume *volume = NULL;
+				gchar *uri;
+
+				if (!volume_monitor)
+					volume_monitor = gnome_vfs_get_volume_monitor ();
+
+				uri = gnome_vfs_get_uri_from_local_path (path);
+				drive = _gnome_vfs_volume_monitor_find_fstab_drive_by_activation_uri (volume_monitor, uri);
+				if (drive)
+					volume = _gnome_vfs_volume_monitor_find_mtab_volume_by_activation_uri (volume_monitor, uri);
+				g_free (uri);
+
+				if (drive && !volume)
+					return "x-special/device-char"; /* TODO: Eventually return appropriate */
+			}
+
 			return "x-directory/normal";
 		} else if (S_ISCHR(optional_stat_info->st_mode)) {
 			return "x-special/device-char";
 		} else if (S_ISBLK(optional_stat_info->st_mode)) {
 			return "x-special/device-block";
@@ -841,5 +863,7 @@
 gnome_vfs_mime_reload (void)
 {
         gnome_vfs_mime_info_cache_reload (NULL);
         gnome_vfs_mime_info_reload ();
 }
+
+
Index: libgnomevfs/gnome-vfs-volume-monitor-daemon.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume-monitor-daemon.c,v
retrieving revision 1.19
diff -U5 -r1.19 gnome-vfs-volume-monitor-daemon.c
--- libgnomevfs/gnome-vfs-volume-monitor-daemon.c	30 Jun 2005 09:17:20 -0000	1.19
+++ libgnomevfs/gnome-vfs-volume-monitor-daemon.c	11 Aug 2005 03:46:01 -0000
@@ -638,15 +638,12 @@
 {
 	GnomeVFSDrive *drive;
 	GnomeVFSVolume *mounted_volume;
 	char *uri;
 	
-	if (mount->is_loopback ||
-	    !(mount->is_user_mountable ||
-	      g_str_has_prefix (mount->device_path, "/vol/"))) {
+	if (!(mount->is_user_mountable || g_str_has_prefix (mount->device_path, "/vol/")))
 		return NULL;
-	}
 
 	fixup_mountpoint (mount);
 	
 	drive = g_object_new (GNOME_VFS_TYPE_DRIVE, NULL);
 
@@ -682,10 +679,12 @@
 		   (strcmp (mount->filesystem_type, "msdos") == 0) ||
 		   (strcmp (mount->filesystem_type, "msdosfs") == 0)) {
 		if (drive->priv->device_type == GNOME_VFS_DEVICE_TYPE_UNKNOWN) {
 			drive->priv->device_type = GNOME_VFS_DEVICE_TYPE_WINDOWS;
 		}
+	} else if (mount->is_loopback) {
+		drive->priv->device_type = GNOME_VFS_DEVICE_TYPE_LOOPBACK;
 	}
 
 	drive->priv->icon = get_drive_icon_from_type (drive->priv->device_type, mount->mount_path);
 
 	drive->priv->display_name = get_drive_name (volume_monitor, drive, mount);
Index: libgnomevfs/gnome-vfs-volume-ops.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-volume-ops.c,v
retrieving revision 1.22
diff -U5 -r1.22 gnome-vfs-volume-ops.c
--- libgnomevfs/gnome-vfs-volume-ops.c	30 Jun 2005 09:17:20 -0000	1.22
+++ libgnomevfs/gnome-vfs-volume-ops.c	11 Aug 2005 03:46:01 -0000
@@ -21,10 +21,15 @@
    Author: Alexander Larsson <alexl@redhat.com>
 */
 
 #include <config.h>
 
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pty.h>
+#include <utmp.h>
+#include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 #include <glib.h>
 #include <glib/gi18n-lib.h>
 #ifndef G_OS_WIN32
@@ -37,10 +42,13 @@
 #include "gnome-vfs-volume.h"
 #include "gnome-vfs-utils.h"
 #include "gnome-vfs-drive.h"
 #include "gnome-vfs-client.h"
 #include "gnome-vfs-private.h"
+#include "gnome-vfs-standard-callbacks.h"
+#include "gnome-vfs-module-callback-module-api.h"
+#include "gnome-vfs-module-callback-private.h"
 
 #ifdef USE_HAL
 #include "gnome-vfs-hal-mounts.h"
 #endif
 
@@ -65,20 +73,28 @@
 	"/usr/sbin/mount", "/usr/bin/mount",
 	NULL
 };
 
 static const char *umount_known_locations [] = {
+	"/sbin/umount", "/bin/umount",
+	"/usr/sbin/umount", "/usr/bin/umount",
+	NULL
+};
+
+static const char *pumount_known_locations [] = {
 	"/usr/bin/pumount", "/bin/pumount",
 	"/sbin/umount", "/bin/umount",
 	"/usr/sbin/umount", "/usr/bin/umount",
 	NULL
 };
 
 #define MOUNT_COMMAND mount_known_locations
 #define MOUNT_SEPARATOR " "
 #define UMOUNT_COMMAND umount_known_locations
 #define UMOUNT_SEPARATOR " "
+#define PUMOUNT_COMMAND pumount_known_locations
+#define PUMOUNT_SEPARATOR " "
 
 #endif /* USE_VOLRMMOUNT */
 
 /* Returns the full path to the queried command */
 static const char *
@@ -109,12 +125,26 @@
 	gboolean succeeded;
 	char *error_message;
 	char *detailed_error_message;
 } MountThreadInfo;
 
+/* Since we're not a module handling jobs, we need to do our own marshalling
+   of the authentication callbacks */
+typedef struct _MountThreadAuth {
+	const gchar *callback;
+	gconstpointer in_args;
+	gsize in_size;
+	gpointer out_args;
+	gsize out_size;
+	gboolean invoked;
+
+	GCond *cond;
+	GMutex *mutex;
+} MountThreadAuth;
+
 static char *
-generate_mount_error_message (char *standard_error,
+generate_mount_error_message (char *standard_error, 
 			      GnomeVFSDeviceType device_type)
 {
 	char *message;
 	
 	if ((strstr (standard_error, "is not a valid block device") != NULL) ||
@@ -132,10 +162,14 @@
 	} else if (strstr (standard_error, "wrong fs type, bad option, bad superblock on") != NULL) {
 		/* Unknown filesystem */
 		if (device_type == GNOME_VFS_DEVICE_TYPE_FLOPPY) {
 			message = g_strdup_printf (_("Unable to mount the floppy drive. "
 						     "The floppy is probably in a format that cannot be mounted."));
+		} else if (device_type == GNOME_VFS_DEVICE_TYPE_LOOPBACK) {
+			/* Probably a wrong password */
+			message = g_strdup_printf (_("Unable to mount the volume. "
+						     "If this is an encrypted drive, then the wrong password or key was used."));
 		} else {
 			message = g_strdup_printf (_("Unable to mount the selected volume. "
 						     "The volume is probably in a format that cannot be mounted."));
 		}
 	} else {
@@ -152,11 +186,17 @@
 generate_unmount_error_message (char *standard_error,
 				GnomeVFSDeviceType device_type)
 {
 	char *message;
 	
-	message = g_strdup (_("Unable to unmount the selected volume."));
+	if ((strstr (standard_error, "busy") != NULL)) {
+		message = g_strdup_printf (_("Unable to unmount the selected volume. "
+					     "The volume is in use by one or more programs."));
+	} else {
+		message = g_strdup (_("Unable to unmount the selected volume."));
+	}	
+
 	return message;
 }
 
 static void
 force_probe (void)
@@ -220,10 +260,381 @@
 	g_free (info);
 	
 	return FALSE;
 }
 
+static gboolean
+invoke_async_auth_cb (MountThreadAuth *auth)
+{
+	g_mutex_lock (auth->mutex);
+	auth->invoked = gnome_vfs_module_callback_invoke (auth->callback, 
+					auth->in_args, auth->in_size, 
+					auth->out_args, auth->out_size);
+	g_cond_signal (auth->cond);
+	g_mutex_unlock (auth->mutex);
+	return FALSE;
+}
+
+static gboolean
+invoke_async_auth (const gchar *callback_name, gconstpointer in,
+		   gsize in_size, gpointer out, gsize out_size)
+{
+	MountThreadAuth auth;
+	memset (&auth, 0, sizeof(auth));
+	auth.callback = callback_name;
+	auth.in_args = in;
+	auth.in_size = in_size;
+	auth.out_args = out;
+	auth.out_size = out_size;
+	auth.invoked = FALSE;
+	auth.mutex = g_mutex_new ();
+	auth.cond = g_cond_new ();
+
+g_printerr("invoking %s\n", callback_name);
+
+	g_mutex_lock (auth.mutex);
+	g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)invoke_async_auth_cb, &auth, NULL);
+	g_cond_wait (auth.cond, auth.mutex);
+
+	g_mutex_unlock (auth.mutex);
+	g_mutex_free (auth.mutex);
+	g_cond_free (auth.cond);
+
+g_printerr("invoked %s %d\n", callback_name, auth.invoked);
+	
+	return auth.invoked;
+}
+
+static gboolean
+invoke_fill_auth (MountThreadInfo *info, char **password_out)
+{
+	gboolean invoked;
+	GnomeVFSModuleCallbackFillAuthenticationIn in_args;
+	GnomeVFSModuleCallbackFillAuthenticationOut out_args;
+
+	*password_out = NULL;
+
+	memset (&in_args, 0, sizeof (in_args));
+	in_args.protocol = "file";
+	in_args.uri = (gchar*)info->mount_point;
+	in_args.object = NULL;
+	in_args.authtype = "password";
+	in_args.domain = NULL;
+	in_args.port = 0;
+	in_args.server = (gchar*)info->device_path;
+	in_args.username = NULL;
+
+	memset (&out_args, 0, sizeof (out_args));
+
+	invoked = invoke_async_auth (GNOME_VFS_MODULE_CALLBACK_FILL_AUTHENTICATION,
+				     &in_args, sizeof (in_args), &out_args, sizeof (out_args));
+
+	if (invoked && out_args.valid) {
+		*password_out = g_strdup (out_args.password);
+		out_args.password = NULL;
+	} 
+
+	g_free (out_args.username);
+	g_free (out_args.domain);
+	g_free (out_args.password);
+
+	return invoked && out_args.valid;
+}
+
+static gboolean
+invoke_full_auth (MountThreadInfo *info, char **password_out, char **keyring_out,
+		  gboolean *save_password_out)
+{
+	GnomeVFSModuleCallbackFullAuthenticationIn in_args;
+	GnomeVFSModuleCallbackFullAuthenticationOut out_args;
+	gboolean invoked;
+
+	*password_out = NULL;
+	*keyring_out = NULL;
+	*save_password_out = FALSE;
+
+	memset (&in_args, 0, sizeof (in_args));
+	in_args.flags = GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD /*|
+			GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_SAVING_SUPPORTED*/;
+	in_args.uri = (gchar*)info->mount_point;
+	in_args.protocol = "file";
+	in_args.object = NULL;
+	in_args.authtype = "password";
+	in_args.domain = NULL;
+	in_args.port = 0;
+	in_args.server = (gchar*)info->device_path;
+	in_args.username = NULL;
+
+	memset (&out_args, 0, sizeof (out_args));
+
+	invoked = invoke_async_auth (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION,
+				     &in_args, sizeof (in_args), &out_args, sizeof (out_args));
+
+	if (invoked && !out_args.abort_auth) {
+		*password_out = out_args.password;
+		out_args.password = NULL;
+
+		if (out_args.save_password) {
+			*save_password_out = TRUE;
+			*keyring_out = out_args.keyring;
+			out_args.keyring = NULL;
+		}
+	}
+
+	g_free (out_args.username);
+	g_free (out_args.password);
+	g_free (out_args.keyring);
+	g_free (out_args.domain);
+
+	return invoked && !out_args.abort_auth;
+}
+
+static void
+invoke_save_auth (MountThreadInfo *info, char *keyring, char *password)
+{
+	GnomeVFSModuleCallbackSaveAuthenticationIn in_args;
+	GnomeVFSModuleCallbackSaveAuthenticationOut out_args;
+
+	memset (&in_args, 0, sizeof (in_args));
+	in_args.uri = (char*)info->mount_point;
+	in_args.server = (char*)info->device_path;
+	in_args.port = 0;
+	in_args.protocol = "file";
+	in_args.keyring = keyring;
+	in_args.username = NULL;
+	in_args.object = NULL;
+	in_args.authtype = "password";
+	in_args.password = password;
+
+	memset (&out_args, 0, sizeof (out_args));
+
+	invoke_async_auth (GNOME_VFS_MODULE_CALLBACK_SAVE_AUTHENTICATION,
+			   &in_args, sizeof (in_args), &out_args, sizeof (out_args));
+}
+
+static gint
+read_data (GString *str, gint fd, GError **error)
+{
+  	gssize bytes;        
+  	gchar buf[4096];    
+	
+again:
+  
+  	bytes = read (fd, buf, 4096);
+	if (bytes < 0) {
+  		if (errno == EINTR)
+			goto again;
+		else if (errno == EIO) /* This seems to occur on a tty */
+			return 0;
+		else {
+      		g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
+            	       _("Failed to read data from child process %d (%s)"), fd, g_strerror (errno));
+			return -1;
+		}
+	}
+
+	str = g_string_append_len (str, buf, bytes);
+	return bytes;
+}
+
+static void
+mount_child_setup (gint *tty)
+{
+	gint err = dup (2);
+	
+	/* Close other end of socket */
+	close (tty[0]);
+	
+	/* This sets stdin, stdout, stderr to the socket */	
+	if (login_tty (tty[1]) == -1)
+		fprintf (stderr, "login_tty failed: %s\n", strerror (errno));
+	
+	/* Now set stderr back */
+	else if (err >= 0)
+		dup2 (err, 2);
+}
+
+static gboolean
+spawn_mount (MountThreadInfo *info, gchar **envp, gchar **standard_error, 
+	     gint *exit_status, GError **error)
+{
+	gint tty[2] = { -1, -1 };
+  	gint errpipe = -1;
+	GPid pid;
+	fd_set rfds;
+	fd_set wfds;
+	gint ret;
+	GString *outstr = NULL;
+	GString *errstr = NULL;
+	gboolean failed = FALSE;
+	gboolean with_password = info->should_mount;
+	gboolean need_password = FALSE;
+	gboolean save_password = FALSE;
+	gchar* password = NULL;
+	gchar* keyring = NULL;
+	gint status;
+
+gchar **t = info->argv;
+while(*t) g_print ("%s\n", *(t++));
+	
+	if (with_password && openpty (&(tty[0]), &(tty[1]), NULL, NULL, NULL) == -1) {
+		g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ, 
+			     _("Unexpected error in socketpair() (%s)"), g_strerror (errno));
+		return FALSE;
+	}	
+	
+	if (!g_spawn_async_with_pipes (NULL, info->argv, envp, G_SPAWN_DO_NOT_REAP_CHILD,
+				       with_password ? (GSpawnChildSetupFunc)mount_child_setup : NULL, 
+				       tty, &pid, NULL, NULL, 
+				       standard_error ? &errpipe : NULL, error))
+		return FALSE;
+	
+	/* Close other end of socket */
+	if (tty[1] >= 0)
+		close(tty[1]);
+	
+	outstr = g_string_new (NULL);
+	
+	if (errpipe >= 0)
+		errstr = g_string_new (NULL);
+
+	/* Read data until we get EOF on both pipes. */
+  	while (!failed && (tty[0] >= 0 || errpipe >= 0)) {
+		ret = 0;
+          
+		FD_ZERO (&rfds);
+		FD_ZERO (&wfds);
+		
+		if (tty[0] >= 0)
+			FD_SET (tty[0], &rfds);
+		if (tty[0] >= 0 && need_password)
+			FD_SET (tty[0], &wfds);
+		if (errpipe >= 0)
+			FD_SET (errpipe, &rfds);
+          
+		ret = select (FD_SETSIZE, &rfds, &wfds, NULL, NULL /* no timeout */);
+		if (ret < 0 && errno != EINTR) {
+			failed = TRUE;
+			g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ, _("Unexpected error in select() reading data from a child process (%s)"),
+                         	     g_strerror (errno));
+			break;
+		}
+		
+		if (tty[0] >= 0 && FD_ISSET (tty[0], &rfds)) {
+			switch (read_data (outstr, tty[0], error)) {
+			case -1:
+				failed = TRUE;
+				break;
+			case 0:
+				close (tty[0]);
+				tty[0] = -1;
+				break;
+			}	
+
+			if (failed)
+				break;
+
+			g_string_ascii_down (outstr);
+	
+			if (g_strstr_len (outstr->str, outstr->len, "password")) {
+g_printerr("need password\n");
+				g_string_erase (outstr, 0, -1);
+				need_password = TRUE;
+			}
+		}
+			
+		if (tty[0] >= 0 && need_password && FD_ISSET (tty[0], &wfds)) {
+
+			g_free (password);
+			password = NULL;
+
+			if ((!invoke_fill_auth (info, &password) || password == NULL) &&
+			    (!invoke_full_auth (info, &password, &keyring, &save_password) || password == NULL)) {
+g_printerr("user cancelled\n");
+				/* User cancelled, empty string returned */
+				g_string_erase (errstr, 0, -1);
+				kill (pid, SIGTERM);
+				break;
+			} else {
+g_printerr("got password: %s\n", password);
+				if (write(tty[0], password, strlen(password)) == -1 || 
+				    write(tty[0], "\n", 1) == -1)
+				{
+g_printerr("error writing password %s\n", g_strerror(errno));
+					g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ, 
+						     _("Couldn't send password to mount process."));
+					failed = TRUE;
+				}
+			} 
+
+			need_password = FALSE;
+		}
+	
+		if (errpipe >= 0 && FD_ISSET (errpipe, &rfds)) {
+			switch (read_data (errstr, errpipe, error)) {
+			case -1:
+				failed = TRUE;
+				break;
+			case 0:
+				close (errpipe);
+				errpipe = -1;
+				break;
+			default:
+				break;
+            		}
+			
+			fprintf(stderr, "error says: %s", errstr->str);
+
+          		if (failed)
+            			break;
+		}
+	}
+g_printerr("done\n");
+	
+  	if (tty[0] >= 0)
+		close (tty[0]);
+  	if (errpipe >= 0)
+		close (errpipe);
+
+	g_string_free (outstr, TRUE);
+	
+	/* Wait for child to exit, even if we have
+	 * an error pending.
+	 */
+again:
+      
+  	ret = waitpid (pid, &status, 0);
+
+  	if (ret < 0) {
+		if (errno == EINTR)
+			goto again;
+		else if (!failed) {
+			failed = TRUE;
+			g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
+                        	     _("Unexpected error in waitpid() (%s)"), g_strerror (errno));
+        	}
+    	}
+
+	if (!failed && status == 0 && save_password)
+		invoke_save_auth (info, password, keyring);
+
+	g_free (keyring);
+	g_free (password);
+	
+  	if (failed) {
+      		if (errstr)
+        		g_string_free (errstr, TRUE);
+      		return FALSE;
+	} else {
+      		if (exit_status)
+        		*exit_status = status;
+      		if (standard_error)
+        		*standard_error = g_string_free (errstr, FALSE);
+      		return TRUE;
+    	}
+}
+
 static void *
 mount_unmount_thread (void *arg)
 {
 	MountThreadInfo *info;
 	char *standard_error;
@@ -240,25 +651,21 @@
 	info->error_message = NULL;
 	info->detailed_error_message = NULL;
 
 	if (info->should_mount || info->should_unmount) {
 		error = NULL;
-		if (g_spawn_sync (NULL,
-				  info->argv,
+		if (spawn_mount (info, 
 #if defined(USE_HAL) && defined(HAL_MOUNT) && defined(HAL_UMOUNT)
-				  /* do pass our environment when using hal mount progams */
-				  ((strcmp (info->argv[0], HAL_MOUNT) == 0) ||
-				   (strcmp (info->argv[0], HAL_UMOUNT) == 0)) ? NULL : envp,
+				 /* do pass our environment when using hal mount progams */
+				 ((strcmp (info->argv[0], HAL_MOUNT) == 0) ||
+				  (strcmp (info->argv[0], HAL_UMOUNT) == 0)) ? NULL : envp,
 #else
-				   envp,
+				 envp,
 #endif
-				   G_SPAWN_STDOUT_TO_DEV_NULL,
-				   NULL, NULL,
-				   NULL,
-				   &standard_error,
-				   &exit_status,
-				   &error)) {
+				 &standard_error, 
+				 &exit_status, 
+				 &error)) {
 			if (exit_status != 0) {
 				info->succeeded = FALSE;
 				if (strlen (standard_error) > 0) {
 					if (info->should_mount) {
 						info->error_message = generate_mount_error_message (standard_error,
@@ -360,11 +767,11 @@
 			g_error_free (error);
 		}
 	}
 
 	g_idle_add (report_mount_result, info);	
-	
+
 	pthread_exit (NULL); 	
 	
 	return NULL;
 }
 
@@ -385,10 +792,11 @@
 	const char *command = NULL;
 	const char *argument = NULL;
 	MountThreadInfo *mount_info;
 	pthread_t mount_thread;
 	const char *name;
+	const char **cmds;
 	int i;
 
 	
 #ifdef USE_VOLRMMOUNT
 	name = strrchr (mount_point, '/');
@@ -423,17 +831,19 @@
 	       argument = MOUNT_ARGUMENT;
 #endif
        }
 
        if (should_unmount) {
+		cmds = g_str_has_prefix (mount_point, "/media") ?
+		 	  PUMOUNT_COMMAND : UMOUNT_COMMAND;
 #if defined(USE_HAL) && defined(HAL_UMOUNT)
 	       if (hal_udi != NULL && g_file_test (HAL_UMOUNT, G_FILE_TEST_IS_EXECUTABLE))
 		       command = HAL_UMOUNT;
 	       else
-		       command = find_command (UMOUNT_COMMAND);
+		       command = find_command (cmds);
 #else
-	       command = find_command (UMOUNT_COMMAND);
+	       command = find_command (cmds);
 #endif
 #ifdef  UNMOUNT_ARGUMENT
 		argument = UNMOUNT_ARGUMENT;
 #endif
        }
