1 /*
2 * Copyright © 2008-2011 Kristian Høgsberg
3 * Copyright © 2011 Intel Corporation
4 * Copyright © 2013-2015 Red Hat, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #pragma once
27
28 #include <sys/types.h>
29 #include <sys/mouse.h>
30
31 #include <assert.h>
32 #include <ctype.h>
33 #include <math.h>
34 #include <xlocale.h>
35
36 #define HAVE_LOCALE_H 1
37
38 #define MOUSED_ATTRIBUTE_PRINTF(_format, _args) \
39 __attribute__ ((format (printf, _format, _args)))
40
41 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
42 /**
43 * Iterate through the array _arr, assigning the variable elem to each
44 * element. elem only exists within the loop.
45 */
46 #define ARRAY_FOR_EACH(_arr, _elem) \
47 for (__typeof__((_arr)[0]) *_elem = _arr; \
48 _elem < (_arr) + ARRAY_LENGTH(_arr); \
49 _elem++)
50
51 #define versionsort(...) alphasort(__VA_ARGS__)
52 #define bit(x_) (1UL << (x_))
53 #define min(a, b) (((a) < (b)) ? (a) : (b))
54
55 /* Supported device interfaces */
56 enum device_if {
57 DEVICE_IF_UNKNOWN = -1,
58 DEVICE_IF_EVDEV = 0,
59 DEVICE_IF_SYSMOUSE,
60 };
61
62 /* Recognized device types */
63 enum device_type {
64 DEVICE_TYPE_UNKNOWN = -1,
65 DEVICE_TYPE_MOUSE = 0,
66 DEVICE_TYPE_POINTINGSTICK,
67 DEVICE_TYPE_TOUCHPAD,
68 DEVICE_TYPE_TOUCHSCREEN,
69 DEVICE_TYPE_TABLET,
70 DEVICE_TYPE_TABLET_PAD,
71 DEVICE_TYPE_KEYBOARD,
72 DEVICE_TYPE_JOYSTICK,
73 };
74
75 struct device {
76 char path[80];
77 enum device_if iftype;
78 enum device_type type;
79 char name[80];
80 char uniq[80];
81 struct input_id id;
82 mousemode_t mode;
83 };
84
85 /**
86 * @ingroup base
87 *
88 * Log handler type for custom logging.
89 *
90 * @param priority The priority of the current message
91 * @param format Message format in printf-style
92 * @param args Message arguments
93 */
94 typedef void moused_log_handler(int priority, int errnum,
95 const char *format, va_list args);
96
97 /* util-mem.h */
98
99 /**
100 * Use: _unref_(foo) struct foo *bar;
101 *
102 * This requires foo_unrefp() to be present, use DEFINE_UNREF_CLEANUP_FUNC.
103 */
104 #define _unref_(_type) __attribute__((cleanup(_type##_unrefp))) struct _type
105
106 /**
107 * Define a cleanup function for the struct type foo with a matching
108 * foo_unref(). Use:
109 * DEFINE_UNREF_CLEANUP_FUNC(foo)
110 * _unref_(foo) struct foo *bar;
111 */
112 #define DEFINE_UNREF_CLEANUP_FUNC(_type) \
113 static inline void _type##_unrefp(struct _type **_p) { \
114 if (*_p) \
115 _type##_unref(*_p); \
116 } \
117 struct __useless_struct_to_allow_trailing_semicolon__
118
119 static inline void*
_steal(void * ptr)120 _steal(void *ptr) {
121 void **original = (void**)ptr;
122 void *swapped = *original;
123 *original = NULL;
124 return swapped;
125 }
126
127 /**
128 * Resets the pointer content and resets the data to NULL.
129 * This circumvents _cleanup_ handling for that pointer.
130 * Use:
131 * _cleanup_free_ char *data = malloc();
132 * return steal(&data);
133 *
134 */
135 #define steal(ptr_) \
136 (typeof(*ptr_))_steal(ptr_)
137
138 /* ! util-mem.h */
139
140 /* util-strings.h */
141
142 static inline bool
streq(const char * str1,const char * str2)143 streq(const char *str1, const char *str2)
144 {
145 /* one NULL, one not NULL is always false */
146 if (str1 && str2)
147 return strcmp(str1, str2) == 0;
148 return str1 == str2;
149 }
150
151 static inline bool
strneq(const char * str1,const char * str2,int n)152 strneq(const char *str1, const char *str2, int n)
153 {
154 /* one NULL, one not NULL is always false */
155 if (str1 && str2)
156 return strncmp(str1, str2, n) == 0;
157 return str1 == str2;
158 }
159
160 static inline void *
zalloc(size_t size)161 zalloc(size_t size)
162 {
163 void *p;
164
165 /* We never need to alloc anything more than 1,5 MB so we can assume
166 * if we ever get above that something's going wrong */
167 if (size > 1536 * 1024)
168 assert(!"bug: internal malloc size limit exceeded");
169
170 p = calloc(1, size);
171 if (!p)
172 abort();
173
174 return p;
175 }
176
177 /**
178 * strdup guaranteed to succeed. If the input string is NULL, the output
179 * string is NULL. If the input string is a string pointer, we strdup or
180 * abort on failure.
181 */
182 static inline char*
safe_strdup(const char * str)183 safe_strdup(const char *str)
184 {
185 char *s;
186
187 if (!str)
188 return NULL;
189
190 s = strdup(str);
191 if (!s)
192 abort();
193 return s;
194 }
195
196 /**
197 * Simple wrapper for asprintf that ensures the passed in-pointer is set
198 * to NULL upon error.
199 * The standard asprintf() call does not guarantee the passed in pointer
200 * will be NULL'ed upon failure, whereas this wrapper does.
201 *
202 * @param strp pointer to set to newly allocated string.
203 * This pointer should be passed to free() to release when done.
204 * @param fmt the format string to use for printing.
205 * @return The number of bytes printed (excluding the null byte terminator)
206 * upon success or -1 upon failure. In the case of failure the pointer is set
207 * to NULL.
208 */
209 __attribute__ ((format (printf, 2, 3)))
210 static inline int
xasprintf(char ** strp,const char * fmt,...)211 xasprintf(char **strp, const char *fmt, ...)
212 {
213 int rc = 0;
214 va_list args;
215
216 va_start(args, fmt);
217 rc = vasprintf(strp, fmt, args);
218 va_end(args);
219 if ((rc == -1) && strp)
220 *strp = NULL;
221
222 return rc;
223 }
224
225 static inline bool
safe_atoi_base(const char * str,int * val,int base)226 safe_atoi_base(const char *str, int *val, int base)
227 {
228 assert(str != NULL);
229
230 char *endptr;
231 long v;
232
233 assert(base == 10 || base == 16 || base == 8);
234
235 errno = 0;
236 v = strtol(str, &endptr, base);
237 if (errno > 0)
238 return false;
239 if (str == endptr)
240 return false;
241 if (*str != '\0' && *endptr != '\0')
242 return false;
243
244 if (v > INT_MAX || v < INT_MIN)
245 return false;
246
247 *val = v;
248 return true;
249 }
250
251 static inline bool
safe_atoi(const char * str,int * val)252 safe_atoi(const char *str, int *val)
253 {
254 assert(str != NULL);
255 return safe_atoi_base(str, val, 10);
256 }
257
258 static inline bool
safe_atou_base(const char * str,unsigned int * val,int base)259 safe_atou_base(const char *str, unsigned int *val, int base)
260 {
261 assert(str != NULL);
262
263 char *endptr;
264 unsigned long v;
265
266 assert(base == 10 || base == 16 || base == 8);
267
268 errno = 0;
269 v = strtoul(str, &endptr, base);
270 if (errno > 0)
271 return false;
272 if (str == endptr)
273 return false;
274 if (*str != '\0' && *endptr != '\0')
275 return false;
276
277 if ((long)v < 0)
278 return false;
279
280 *val = v;
281 return true;
282 }
283
284 static inline bool
safe_atou(const char * str,unsigned int * val)285 safe_atou(const char *str, unsigned int *val)
286 {
287 assert(str != NULL);
288 return safe_atou_base(str, val, 10);
289 }
290
291 static inline bool
safe_atod(const char * str,double * val)292 safe_atod(const char *str, double *val)
293 {
294 assert(str != NULL);
295
296 char *endptr;
297 double v;
298 size_t slen = strlen(str);
299
300 /* We don't have a use-case where we want to accept hex for a double
301 * or any of the other values strtod can parse */
302 for (size_t i = 0; i < slen; i++) {
303 char c = str[i];
304
305 if (isdigit(c))
306 continue;
307 switch(c) {
308 case '+':
309 case '-':
310 case '.':
311 break;
312 default:
313 return false;
314 }
315 }
316
317 #ifdef HAVE_LOCALE_H
318 /* Create a "C" locale to force strtod to use '.' as separator */
319 locale_t c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
320 if (c_locale == (locale_t)0)
321 return false;
322
323 errno = 0;
324 v = strtod_l(str, &endptr, c_locale);
325 freelocale(c_locale);
326 #else
327 /* No locale support in provided libc, assume it already uses '.' */
328 errno = 0;
329 v = strtod(str, &endptr);
330 #endif
331 if (errno > 0)
332 return false;
333 if (str == endptr)
334 return false;
335 if (*str != '\0' && *endptr != '\0')
336 return false;
337 if (v != 0.0 && !isnormal(v))
338 return false;
339
340 *val = v;
341 return true;
342 }
343
344 char **strv_from_string(const char *in, const char *separator, size_t *num_elements);
345
346 typedef int (*strv_foreach_callback_t)(const char *str, size_t index, void *data);
347 int strv_for_each_n(const char **strv, size_t max, strv_foreach_callback_t func, void *data);
348
349 static inline void
strv_free(char ** strv)350 strv_free(char **strv) {
351 char **s = strv;
352
353 if (!strv)
354 return;
355
356 while (*s != NULL) {
357 free(*s);
358 *s = (char*)0x1; /* detect use-after-free */
359 s++;
360 }
361
362 free (strv);
363 }
364
365 /**
366 * Return true if str ends in suffix, false otherwise. If the suffix is the
367 * empty string, strendswith() always returns false.
368 */
369 static inline bool
strendswith(const char * str,const char * suffix)370 strendswith(const char *str, const char *suffix)
371 {
372 if (str == NULL)
373 return false;
374
375 size_t slen = strlen(str);
376 size_t suffixlen = strlen(suffix);
377 size_t offset;
378
379 if (slen == 0 || suffixlen == 0 || suffixlen > slen)
380 return false;
381
382 offset = slen - suffixlen;
383 return strneq(&str[offset], suffix, suffixlen);
384 }
385
386 static inline bool
strstartswith(const char * str,const char * prefix)387 strstartswith(const char *str, const char *prefix)
388 {
389 if (str == NULL)
390 return false;
391
392 size_t prefixlen = strlen(prefix);
393
394 return prefixlen > 0 ? strneq(str, prefix, strlen(prefix)) : false;
395 }
396
397 /* !util-strings.h */
398
399 /* util-prop-parsers.h */
400
401 struct input_prop {
402 unsigned int prop;
403 bool enabled;
404 };
405
406 bool parse_dimension_property(const char *prop, size_t *w, size_t *h);
407 bool parse_range_property(const char *prop, int *hi, int *lo);
408 bool parse_boolean_property(const char *prop, bool *b);
409 #define EVENT_CODE_UNDEFINED 0xffff
410 bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents);
411 bool parse_input_prop_property(const char *prop, struct input_prop *props_out, size_t *nprops);
412
413 /* !util-prop-parsers.h */
414