[PATCH 4/7] xfree86: Allow multiple arguments to InputClass matches

Peter Hutterer peter.hutterer at who-t.net
Tue Feb 9 21:36:47 PST 2010


From: Dan Nicholson <dbn.lists at gmail.com>

In order to keep the number of InputClass sections manageable, allow
matches to contain multiple arguments. The arguments will be separated
by the '|' character. This allows a policy to apply to multiple types of
devices. For example:

    Section "InputClass"
        Identifier "Inverted Mice"
        MatchProduct "Crazy Mouse|Silly Mouse"
        Option "InvertX" "yes"
    EndSection

This applies to the MatchProduct, MatchVendor and MatchDevicePath
entries. Currently there is no way to escape characters, so names or
patterns cannot contain '|'.

Signed-off-by: Dan Nicholson <dbn.lists at gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 hw/xfree86/common/xf86Xinput.c       |   51 ++++++++++++++----
 hw/xfree86/doc/man/xorg.conf.man.pre |    9 ++-
 hw/xfree86/parser/InputClass.c       |   99 +++++++++++++++++++++++++++++----
 hw/xfree86/parser/xf86Parser.h       |    6 +-
 4 files changed, 136 insertions(+), 29 deletions(-)

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index b37dae6..8ac9d26 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -502,20 +502,49 @@ AddOtherInputDevices(void)
 static Bool
 InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
 {
-    if (iclass->match_product &&
-        (!attrs->product || !strstr(attrs->product, iclass->match_product)))
-        return FALSE;
-    if (iclass->match_vendor &&
-        (!attrs->vendor || !strstr(attrs->vendor, iclass->match_vendor)))
-        return FALSE;
-    if (iclass->match_device &&
+    char **cur;
+    Bool match;
+
+    if (iclass->match_product) {
+        if (!attrs->product)
+            return FALSE;
+        /* see if any of the values match */
+        for (cur = iclass->match_product, match = FALSE; *cur; cur++)
+            if (strstr(attrs->product, *cur)) {
+                match = TRUE;
+                break;
+            }
+        if (!match)
+            return FALSE;
+    }
+    if (iclass->match_vendor) {
+        if (!attrs->vendor)
+            return FALSE;
+        /* see if any of the values match */
+        for (cur = iclass->match_vendor, match = FALSE; *cur; cur++)
+            if (strstr(attrs->vendor, *cur)) {
+                match = TRUE;
+                break;
+            }
+        if (!match)
+            return FALSE;
+    }
+    if (iclass->match_device) {
+        if (!attrs->device)
+            return FALSE;
+        /* see if any of the values match */
+        for (cur = iclass->match_device, match = FALSE; *cur; cur++)
 #ifdef HAVE_FNMATCH_H
-        (!attrs->device ||
-         fnmatch(iclass->match_device, attrs->device, 0) != 0))
+            if (fnmatch(*cur, attrs->device, 0) == 0) {
 #else
-        (!attrs->device || !strstr(attrs->device, iclass->match_device)))
+            if (strstr(attrs->device, *cur)) {
 #endif
-        return FALSE;
+                match = TRUE;
+                break;
+            }
+        if (!match)
+            return FALSE;
+    }
     if (iclass->is_keyboard.set &&
         iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
         return FALSE;
diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre
index ee91b9a..69f4751 100644
--- a/hw/xfree86/doc/man/xorg.conf.man.pre
+++ b/hw/xfree86/doc/man/xorg.conf.man.pre
@@ -1039,17 +1039,20 @@ The allowed matching entries are shown below.
 .BI "MatchProduct  \*q" matchproduct \*q
 This entry can be used to check if the substring
 .RI \*q matchproduct \*q
-occurs in the device's product name.
+occurs in the device's product name. Multiple substrings can be matched by
+separating arguments with a '|' character.
 .TP 7
 .BI "MatchVendor  \*q" matchvendor \*q
 This entry can be used to check if the substring
 .RI \*q matchvendor \*q
-occurs in the device's vendor name.
+occurs in the device's vendor name. Multiple substrings can be matched by
+separating arguments with a '|' character.
 .TP 7
 .BI "MatchDevicePath \*q" matchdevice \*q
 This entry can be used to check if the device file matches the
 .RI \*q matchdevice \*q
-pathname pattern.
+pathname pattern. Multiple patterns can be matched by separating arguments
+with a '|' character.
 .TP 7
 .BI "MatchIsKeyboard     \*q" bool \*q
 .TP 7
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index 1c98160..8041740 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -29,6 +29,8 @@
 #include <xorg-config.h>
 #endif
 
+#include <string.h>
+#include "os.h"
 #include "xf86Parser.h"
 #include "xf86tokens.h"
 #include "Configint.h"
@@ -56,6 +58,46 @@ xf86ConfigSymTabRec InputClassTab[] =
 
 #define CLEANUP xf86freeInputClassList
 
+#define TOKEN_SEP "|"
+
+/*
+ * Tokenize a string into a NULL terminated array of strings. Always returns
+ * an allocated array unless an error occurs.
+ */
+static char **
+tokenize(const char *str)
+{
+    char **list, **nlist;
+    char *tok, *tmp;
+    unsigned num = 0, n;
+
+    list = calloc(1, sizeof(*list));
+    if (!list)
+        return NULL;
+    tmp = strdup(str);
+    if (!tmp)
+        goto error;
+    for (tok = strtok(tmp, TOKEN_SEP); tok; tok = strtok(NULL, TOKEN_SEP)) {
+        nlist = realloc(list, (num + 2) * sizeof(*list));
+        if (!nlist)
+            goto error;
+        list = nlist;
+        list[num] = strdup(tok);
+        if (!list[num])
+            goto error;
+        list[++num] = NULL;
+    }
+    free(tmp);
+    return list;
+
+error:
+    TestFree(tmp);
+    for (n = 0; n < num; n++)
+        free(list[n]);
+    TestFree(list);
+    return NULL;
+}
+
 XF86ConfInputClassPtr
 xf86parseInputClassSection(void)
 {
@@ -91,17 +133,17 @@ xf86parseInputClassSection(void)
         case MATCH_PRODUCT:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchProduct");
-            ptr->match_product = val.str;
+            ptr->match_product = tokenize(val.str);
             break;
         case MATCH_VENDOR:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchVendor");
-            ptr->match_vendor = val.str;
+            ptr->match_vendor = tokenize(val.str);
             break;
         case MATCH_DEVICE_PATH:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "MatchDevicePath");
-            ptr->match_device = val.str;
+            ptr->match_device = tokenize(val.str);
             break;
         case MATCH_IS_KEYBOARD:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
@@ -173,6 +215,8 @@ xf86parseInputClassSection(void)
 void
 xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
 {
+    char **list;
+
     while (ptr) {
         fprintf(cf, "Section \"InputClass\"\n");
         if (ptr->comment)
@@ -181,12 +225,30 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
             fprintf(cf, "\tIdentifier      \"%s\"\n", ptr->identifier);
         if (ptr->driver)
             fprintf(cf, "\tDriver          \"%s\"\n", ptr->driver);
-        if (ptr->match_product)
-            fprintf(cf, "\tMatchProduct    \"%s\"\n", ptr->match_product);
-        if (ptr->match_vendor)
-            fprintf(cf, "\tMatchVendor     \"%s\"\n", ptr->match_vendor);
-        if (ptr->match_device)
-            fprintf(cf, "\tMatchDevicePath \"%s\"\n", ptr->match_device);
+        if (ptr->match_product) {
+            fprintf(cf, "\tMatchProduct    \"");
+            for (list = ptr->match_product; *list; list++)
+                fprintf(cf, "%s%s",
+                        list == ptr->match_product ? "" : TOKEN_SEP,
+                        *list);
+            fprintf(cf, "\"\n");
+        }
+        if (ptr->match_vendor) {
+            fprintf(cf, "\tMatchVendor     \"");
+            for (list = ptr->match_vendor; *list; list++)
+                fprintf(cf, "%s%s",
+                        list == ptr->match_vendor ? "" : TOKEN_SEP,
+                        *list);
+            fprintf(cf, "\"\n");
+        }
+        if (ptr->match_device) {
+            fprintf(cf, "\tMatchDevicePath \"");
+            for (list = ptr->match_device; *list; list++)
+                fprintf(cf, "%s%s",
+                        list == ptr->match_device ? "" : TOKEN_SEP,
+                        *list);
+            fprintf(cf, "\"\n");
+        }
         if (ptr->is_keyboard.set)
             fprintf(cf, "\tIsKeyboard      \"%s\"\n",
                     ptr->is_keyboard.val ? "yes" : "no");
@@ -215,13 +277,26 @@ void
 xf86freeInputClassList (XF86ConfInputClassPtr ptr)
 {
     XF86ConfInputClassPtr prev;
+    char **list;
 
     while (ptr) {
         TestFree(ptr->identifier);
         TestFree(ptr->driver);
-        TestFree(ptr->match_product);
-        TestFree(ptr->match_vendor);
-        TestFree(ptr->match_device);
+        if (ptr->match_product) {
+            for (list = ptr->match_product; *list; list++)
+                free(*list);
+            free(ptr->match_product);
+        }
+        if (ptr->match_vendor) {
+            for (list = ptr->match_vendor; *list; list++)
+                free(*list);
+            free(ptr->match_vendor);
+        }
+        if (ptr->match_device) {
+            for (list = ptr->match_device; *list; list++)
+                free(*list);
+            free(ptr->match_device);
+        }
         TestFree(ptr->comment);
         xf86optionListFree(ptr->option_lst);
 
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index 5e8351f..b6d40a1 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -343,9 +343,9 @@ typedef struct
 	GenericListRec list;
 	char *identifier;
 	char *driver;
-	char *match_product;
-	char *match_vendor;
-	char *match_device;
+	char **match_product;
+	char **match_vendor;
+	char **match_device;
 	xf86TriState is_keyboard;
 	xf86TriState is_pointer;
 	xf86TriState is_joystick;
-- 
1.6.6



More information about the xorg-devel mailing list