xfree86: Allow multiple arguments to InputClass matches
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@gmail.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
a378e361a5
commit
9b369f7127
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user