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