Commit d1b4beec authored by Dan Nicholson's avatar Dan Nicholson Committed by Peter Hutterer

xfree86: Add MatchOS InputClass entry for operating system matching

Allow InputClass sections to match against the running operating system
to narrow the application of rules. An example where this could be used
is to specify that the default input driver on Linux is evdev while it's
mouse/kbd everywhere else.

The operating system name is the same as `uname -s`, and matching is
case-insensitive.
Signed-off-by: Dan Nicholson's avatarDan Nicholson <dbn.lists@gmail.com>
Reviewed-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent 9b30fa9f
......@@ -123,7 +123,7 @@ AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h])
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h sys/utsname.h])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
......
......@@ -80,6 +80,9 @@
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif
#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#endif
#include "extnsionst.h"
......@@ -496,6 +499,31 @@ AddOtherInputDevices(void)
{
}
/*
* Get the operating system name from uname and store it statically to avoid
* repeating the system call each time MatchOS is checked.
*/
static const char *
HostOS(void)
{
#ifdef HAVE_SYS_UTSNAME_H
struct utsname name;
static char host_os[sizeof(name.sysname)] = "";
if (*host_os == '\0') {
if (uname(&name) >= 0)
strcpy(host_os, name.sysname);
else {
strncpy(host_os, "unknown", sizeof(host_os));
host_os[sizeof(host_os)-1] = '\0';
}
}
return host_os;
#else
return "";
#endif
}
static int
match_substring(const char *attr, const char *pattern)
{
......@@ -558,6 +586,10 @@ InputClassMatches(const XF86ConfInputClassPtr iclass,
if (!MatchAttrToken(attrs->device, iclass->match_device, match_path_pattern))
return FALSE;
/* MatchOS case-insensitive string */
if (!MatchAttrToken(HostOS(), iclass->match_os, strcasecmp))
return FALSE;
/*
* MatchTag string
* See if any of the device's tags match any of the MatchTag tokens.
......
......@@ -1086,6 +1086,15 @@ This entry can be used to check if the device file matches the
pathname pattern. Multiple patterns can be matched by separating arguments
with a '|' character.
.TP 7
.BI "MatchOS \*q" matchos \*q
This entry can be used to check if the operating system matches the
case-insensitive
.RI \*q matchos \*q
string. This entry is only supported on platforms providing the
.BR uname (2)
system call. Multiple operating systems can be matched by separating arguments
with a '|' character.
.TP 7
.BI "MatchTag \*q" matchtag \*q
This entry can be used to check if tags assigned by the config backend
matches the
......
......@@ -47,6 +47,7 @@ xf86ConfigSymTabRec InputClassTab[] =
{MATCH_PRODUCT, "matchproduct"},
{MATCH_VENDOR, "matchvendor"},
{MATCH_DEVICE_PATH, "matchdevicepath"},
{MATCH_OS, "matchos"},
{MATCH_TAG, "matchtag"},
{MATCH_IS_KEYBOARD, "matchiskeyboard"},
{MATCH_IS_POINTER, "matchispointer"},
......@@ -108,6 +109,11 @@ xf86parseInputClassSection(void)
Error(QUOTE_MSG, "MatchDevicePath");
ptr->match_device = xstrtokenize(val.str, TOKEN_SEP);
break;
case MATCH_OS:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchOS");
ptr->match_os = xstrtokenize(val.str, TOKEN_SEP);
break;
case MATCH_TAG:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchTag");
......@@ -217,6 +223,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
*list);
fprintf(cf, "\"\n");
}
if (ptr->match_os) {
fprintf(cf, "\tMatchOS \"");
for (list = ptr->match_os; *list; list++)
fprintf(cf, "%s%s",
list == ptr->match_os ? "" : TOKEN_SEP,
*list);
fprintf(cf, "\"\n");
}
if (ptr->match_tag) {
fprintf(cf, "\tMatchTag \"");
for (list = ptr->match_tag; *list; list++)
......@@ -273,6 +287,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr)
free(*list);
free(ptr->match_device);
}
if (ptr->match_os) {
for (list = ptr->match_os; *list; list++)
free(*list);
free(ptr->match_os);
}
if (ptr->match_tag) {
for (list = ptr->match_tag; *list; list++)
free(*list);
......
......@@ -346,6 +346,7 @@ typedef struct
char **match_product;
char **match_vendor;
char **match_device;
char **match_os;
char **match_tag;
xf86TriState is_keyboard;
xf86TriState is_pointer;
......
......@@ -279,6 +279,7 @@ typedef enum {
MATCH_PRODUCT,
MATCH_VENDOR,
MATCH_DEVICE_PATH,
MATCH_OS,
MATCH_TAG,
MATCH_IS_KEYBOARD,
MATCH_IS_POINTER,
......
......@@ -222,6 +222,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <sys/vm86.h> header file. */
#undef HAVE_SYS_VM86_H
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment