[patch] fix for "refuse options" ignored due to popt

Wayne Davison wayned at samba.org
Sat Feb 21 06:37:30 GMT 2004


On Fri, Feb 20, 2004 at 11:56:59PM +0100, Fabrice Bellet wrote:
> I found the reason why "refuse options" is ignored on the server
> side. When then 5th argument (int val) in the poptOption struct is 
> set to zero, the parsing function poptGetNextOpt() just continues
> with the next arg, without returning.

Good catch!  I took a look at this code, and figured out a better way
to implement the functionality that will let the user refuse any option
in the list.  The patch is attached.

Unfortunately, the error message that gets generated by this failure
doesn't get back to the user because of the wacky mode the daemon socket
is in at the point these options are parsed.  But that's a fix for
another time.

..wayne..
-------------- next part --------------
--- options.c	11 Feb 2004 04:30:41 -0000	1.136
+++ options.c	21 Feb 2004 06:21:41 -0000
@@ -303,7 +303,7 @@ void usage(enum logcode F)
 enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
       OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
-      OPT_READ_BATCH, OPT_WRITE_BATCH};
+      OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_REFUSE_OPTION};
 
 static struct poptOption long_options[] = {
   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
@@ -414,35 +414,28 @@ void option_error(void)
 
 
 /**
- * Check to see if we should refuse this option
+ * Tweak the option table to disable all options that the rsyncd.conf
+ * file has told us to refuse.
  **/
-static int check_refuse_options(char *ref, int opt)
+static void set_refuse_options(char *bp)
 {
-	int i, len;
-	char *p;
-	const char *name;
+	struct poptOption *opt;
+	char *cp;
 
-	for (i = 0; long_options[i].longName; i++) {
-		if (long_options[i].val == opt)
-			break;
-	}
-
-	if (!long_options[i].longName)
-		return 0;
-
-	name = long_options[i].longName;
-	len = strlen(name);
-
-	while ((p = strstr(ref,name))) {
-		if ((p==ref || p[-1]==' ') &&
-		    (p[len] == ' ' || p[len] == 0)) {
-			snprintf(err_buf, sizeof err_buf,
-				 "The '%s' option is not supported by this server\n", name);
-			return 1;
+	while (1) {
+		if ((cp = strchr(bp, ' ')) != NULL)
+			*cp= '\0';
+		for (opt = long_options; opt->longName; opt++) {
+			if (strcmp(bp, opt->longName) == 0) {
+				opt->val = OPT_REFUSE_OPTION;
+				break;
+			}
 		}
-		ref += len;
+		if (!cp)
+			break;
+		*cp = ' ';
+		bp = cp + 1;
 	}
-	return 0;
 }
 
 
@@ -471,6 +464,9 @@ int parse_arguments(int *argc, const cha
 	char *ref = lp_refuse_options(module_id);
 	poptContext pc;
 
+	if (ref && *ref)
+		set_refuse_options(ref);
+
 	/* TODO: Call poptReadDefaultConfig; handle errors. */
 
 	/* The context leaks in case of an error, but if there's a
@@ -478,9 +474,6 @@ int parse_arguments(int *argc, const cha
 	pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
 
 	while ((opt = poptGetNextOpt(pc)) != -1) {
-		if (ref && check_refuse_options(ref, opt))
-			return 0;
-
 		/* most options are handled automatically by popt;
 		 * only special cases are returned and listed here. */
 
@@ -577,6 +570,19 @@ int parse_arguments(int *argc, const cha
 			return 0;
 #endif
 
+		case OPT_REFUSE_OPTION: {
+			const char *op = poptBadOption(pc, POPT_BADOPTION_NOALIAS);
+			if (*op == '-' && op[1] == '-') {
+				snprintf(err_buf, sizeof err_buf,
+				    "The '%s' option is not supported by this server\n",
+				    op);
+			} else {
+				snprintf(err_buf, sizeof err_buf,
+				    "One option in '%s' is not supported by this server\n",
+				    op);
+			}
+			return 0;
+		}
 
 		default:
 			snprintf(err_buf, sizeof err_buf,


More information about the rsync mailing list