0e0a242
diff -ur afuse-0.2.orig/src/afuse.c afuse-0.2/src/afuse.c
0e0a242
--- afuse-0.2.orig/src/afuse.c	2008-02-18 17:16:32.000000000 -0500
0e0a242
+++ afuse-0.2/src/afuse.c	2008-07-10 21:50:06.000000000 -0400
0e0a242
@@ -280,14 +280,19 @@
0e0a242
 }
0e0a242
 
0e0a242
 
0e0a242
-// !!FIXME!! allow escaping of %'s
0e0a242
 // Note: this method strips out quotes and applies them itself as should be appropriate
0e0a242
-char *expand_template(const char *template, const char *mount_point, const char *root_name)
0e0a242
+bool run_template(const char *template, const char *mount_point, const char *root_name)
0e0a242
 {
0e0a242
 	int len = 0;
0e0a242
+	int nargs = 1;
0e0a242
 	int i;
0e0a242
-	char *expanded_name;
0e0a242
-	char *expanded_name_start;
0e0a242
+	char *buf;
0e0a242
+	char *p;
0e0a242
+	char **args;
0e0a242
+	char **arg;
0e0a242
+	bool quote = false;
0e0a242
+	pid_t pid;
0e0a242
+	int status;
0e0a242
 
0e0a242
 	// calculate length
0e0a242
 	for(i = 0; template[i]; i++)
0e0a242
@@ -295,53 +300,100 @@
0e0a242
 			switch(template[i + 1])
0e0a242
 			{
0e0a242
 				case 'm':
0e0a242
-					len += strlen(mount_point) + 2;
0e0a242
+					len += strlen(mount_point);
0e0a242
 					i++;
0e0a242
 					break;
0e0a242
 				case 'r':
0e0a242
-					len += strlen(root_name) + 2;
0e0a242
+					len += strlen(root_name);
0e0a242
+					i++;
0e0a242
+					break;
0e0a242
+				case '%':
0e0a242
+					len++;
0e0a242
 					i++;
0e0a242
 					break;
0e0a242
 			}
0e0a242
-		} else if(template[i] != '"')
0e0a242
+		} else if(template[i] == ' ' && !quote) {
0e0a242
+			len++;
0e0a242
+			nargs++;
0e0a242
+		} else if(template[i] == '"')
0e0a242
+			quote = !quote;
0e0a242
+		else if(template[i] == '\\' && template[i + 1])
0e0a242
+			len++, i++;
0e0a242
+		else
0e0a242
 			len++;
0e0a242
 
0e0a242
-	expanded_name_start = expanded_name = my_malloc(len + 1);
0e0a242
+	buf = my_malloc(len + 1);
0e0a242
+	args = my_malloc((nargs + 1) * sizeof(*args));
0e0a242
+
0e0a242
+	p = buf;
0e0a242
+	arg = args;
0e0a242
+	*arg++ = p;
0e0a242
 
0e0a242
 	for(i = 0; template[i]; i++)
0e0a242
 		if(template[i] == '%') {
0e0a242
-			int j = 0;
0e0a242
 			switch(template[i + 1])
0e0a242
 			{
0e0a242
 				case 'm':
0e0a242
-					*expanded_name++ = '"';
0e0a242
-					while(mount_point[j])
0e0a242
-						*expanded_name++ = mount_point[j++];
0e0a242
-					*expanded_name++ = '"';
0e0a242
+					strcpy(p, mount_point);
0e0a242
+					p += strlen(mount_point);
0e0a242
 					i++;
0e0a242
 					break;
0e0a242
 				case 'r':
0e0a242
-					*expanded_name++ = '"';
0e0a242
-					while(root_name[j])
0e0a242
-						*expanded_name++ = root_name[j++];
0e0a242
-					*expanded_name++ = '"';
0e0a242
+					strcpy(p, root_name);
0e0a242
+					p += strlen(root_name);
0e0a242
+					i++;
0e0a242
+					break;
0e0a242
+				case '%':
0e0a242
+					*p++ = '%';
0e0a242
 					i++;
0e0a242
 					break;
0e0a242
 			}
0e0a242
-		} else if(template[i] != '"')
0e0a242
-			*expanded_name++ = template[i];
0e0a242
-
0e0a242
-	*expanded_name = '\0';
0e0a242
-
0e0a242
-	return expanded_name_start;
0e0a242
+		} else if(template[i] == ' ' && !quote) {
0e0a242
+			*p++ = '\0';
0e0a242
+			*arg++ = p;
0e0a242
+		} else if(template[i] == '"')
0e0a242
+			quote = !quote;
0e0a242
+		else if(template[i] == '\\' && template[i + 1])
0e0a242
+			*p++ = template[++i];
0e0a242
+		else
0e0a242
+			*p++ = template[i];
0e0a242
+
0e0a242
+	*p = '\0';
0e0a242
+	*arg = NULL;
0e0a242
+
0e0a242
+	pid = fork();
0e0a242
+	if(pid == -1) {
0e0a242
+		fprintf(stderr, "Failed to fork (%s)\n", strerror(errno));
0e0a242
+		free(args);
0e0a242
+		free(buf);
0e0a242
+		return false;
0e0a242
+	}
0e0a242
+	if(pid == 0) {
0e0a242
+		execvp(args[0], args);
0e0a242
+		abort();
0e0a242
+	}
0e0a242
+	pid = waitpid(pid, &status, 0);
0e0a242
+	if(pid == -1) {
0e0a242
+		fprintf(stderr, "Failed to waitpid (%s)\n", strerror(errno));
0e0a242
+		free(args);
0e0a242
+		free(buf);
0e0a242
+		return false;
0e0a242
+	}
0e0a242
+	if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
0e0a242
+		fprintf(stderr, "Failed to invoke command: %s\n", args[0]);
0e0a242
+		free(args);
0e0a242
+		free(buf);
0e0a242
+		return false;
0e0a242
+	}
0e0a242
+	free(args);
0e0a242
+	free(buf);
0e0a242
+	return true;
0e0a242
 }
0e0a242
 
0e0a242
 mount_list_t *do_mount(const char *root_name)
0e0a242
 {
0e0a242
 	char *mount_point;
0e0a242
-	char *mount_command;
0e0a242
 	mount_list_t *mount;
0e0a242
-	int sysret;
0e0a242
 
0e0a242
 	fprintf(stderr, "Mounting: %s\n", root_name);
0e0a242
 
0e0a242
@@ -351,57 +403,33 @@
0e0a242
 		return NULL;
0e0a242
 	}
0e0a242
 
0e0a242
-	mount_command = expand_template(user_options.mount_command_template,
0e0a242
-	                                mount_point, root_name);
0e0a242
-	sysret = system(mount_command);
0e0a242
-
0e0a242
-	fprintf(stderr, "sysret: %.8x\n", sysret);
0e0a242
-
0e0a242
-	if(sysret) {
0e0a242
-		fprintf(stderr, "Failed to invoke mount command: '%s' (%s)\n",
0e0a242
-			mount_command, sysret != -1 ?
0e0a242
-				"Error executing mount" :
0e0a242
-				strerror(errno));
0e0a242
-
0e0a242
+	if(!run_template(user_options.mount_command_template,
0e0a242
+			 mount_point, root_name)) {
0e0a242
 		// remove the now unused directory
0e0a242
 		if( rmdir(mount_point) == -1 )
0e0a242
 			fprintf(stderr, "Failed to remove mount point dir: %s (%s)",
0e0a242
 				mount_point, strerror(errno));
0e0a242
 
0e0a242
-		free(mount_command);
0e0a242
 		free(mount_point);
0e0a242
 		return NULL;
0e0a242
 	}
0e0a242
 
0e0a242
 	mount = add_mount(root_name, mount_point);
0e0a242
-
0e0a242
-	free(mount_command);
0e0a242
 	return mount;
0e0a242
 }
0e0a242
 
0e0a242
 int do_umount(mount_list_t *mount)
0e0a242
 {
0e0a242
-	char *unmount_command;
0e0a242
-	int sysret;
0e0a242
-
0e0a242
 	fprintf(stderr, "Unmounting: %s\n", mount->root_name);
0e0a242
 
0e0a242
-	unmount_command = expand_template(user_options.unmount_command_template,
0e0a242
-	                                  mount->mount_point, mount->root_name);
0e0a242
-	sysret = system(unmount_command);
0e0a242
-	if(sysret) {
0e0a242
-		fprintf(stderr, "Failed to invoke unmount command: '%s' (%s)\n",
0e0a242
-		        unmount_command, sysret != -1 ?
0e0a242
-			               "Error executing mount" :
0e0a242
-				       strerror(errno));
0e0a242
-		/* Still unmount anyway */
0e0a242
-	}
0e0a242
+	run_template(user_options.unmount_command_template,
0e0a242
+		     mount->mount_point, mount->root_name);
0e0a242
+	/* Still unmount anyway */
0e0a242
 
0e0a242
 	if( rmdir(mount->mount_point) == -1 )
0e0a242
 		fprintf(stderr, "Failed to remove mount point dir: %s (%s)",
0e0a242
 				mount->mount_point, strerror(errno));
0e0a242
 	remove_mount(mount);
0e0a242
-	free(unmount_command);
0e0a242
 	return 1;
0e0a242
 }
0e0a242
 
0e0a242
0e0a242