Remove old logging leftovers
[platform/upstream/libxkbcommon.git] / src / context.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Author: Daniel Stone <daniel@fooishbar.org>
24  */
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <syslog.h>
34
35 #include "xkb-priv.h"
36 #include "atom.h"
37
38 struct xkb_context {
39     int refcnt;
40
41     ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx, int priority,
42                                      const char *fmt, va_list args);
43     int log_priority;
44     int log_verbosity;
45     void *user_data;
46
47     darray(char *) includes;
48
49     /* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */
50     unsigned file_id;
51
52     struct atom_table *atom_table;
53 };
54
55 /**
56  * Append one directory to the context's include path.
57  */
58 XKB_EXPORT int
59 xkb_context_include_path_append(struct xkb_context *ctx, const char *path)
60 {
61     struct stat stat_buf;
62     int err;
63     char *tmp;
64
65     err = stat(path, &stat_buf);
66     if (err != 0)
67         return 0;
68     if (!S_ISDIR(stat_buf.st_mode))
69         return 0;
70
71 #if defined(HAVE_EACCESS)
72     if (eaccess(path, R_OK | X_OK) != 0)
73         return 0;
74 #elif defined(HAVE_EUIDACCESS)
75     if (euidaccess(path, R_OK | X_OK) != 0)
76         return 0;
77 #endif
78
79     tmp = strdup(path);
80     if (!tmp)
81         return 0;
82
83     darray_append(ctx->includes, tmp);
84     return 1;
85 }
86
87 /**
88  * Append the default include directories to the context.
89  */
90 XKB_EXPORT int
91 xkb_context_include_path_append_default(struct xkb_context *ctx)
92 {
93     const char *home;
94     char *user_path;
95     int err;
96
97     (void) xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
98
99     home = getenv("HOME");
100     if (!home)
101         return 1;
102     err = asprintf(&user_path, "%s/.xkb", home);
103     if (err <= 0)
104         return 1;
105     (void) xkb_context_include_path_append(ctx, user_path);
106     free(user_path);
107
108     return 1;
109 }
110
111 /**
112  * Remove all entries in the context's include path.
113  */
114 XKB_EXPORT void
115 xkb_context_include_path_clear(struct xkb_context *ctx)
116 {
117     char **path;
118
119     darray_foreach(path, ctx->includes)
120     free(*path);
121
122     darray_free(ctx->includes);
123 }
124
125 /**
126  * xkb_context_include_path_clear() + xkb_context_include_path_append_default()
127  */
128 XKB_EXPORT int
129 xkb_context_include_path_reset_defaults(struct xkb_context *ctx)
130 {
131     xkb_context_include_path_clear(ctx);
132     return xkb_context_include_path_append_default(ctx);
133 }
134
135 /**
136  * Returns the number of entries in the context's include path.
137  */
138 XKB_EXPORT unsigned int
139 xkb_context_num_include_paths(struct xkb_context *ctx)
140 {
141     return darray_size(ctx->includes);
142 }
143
144 /**
145  * Returns the given entry in the context's include path, or NULL if an
146  * invalid index is passed.
147  */
148 XKB_EXPORT const char *
149 xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx)
150 {
151     if (idx >= xkb_context_num_include_paths(ctx))
152         return NULL;
153
154     return darray_item(ctx->includes, idx);
155 }
156
157 unsigned
158 xkb_context_take_file_id(struct xkb_context *ctx)
159 {
160     return ctx->file_id++;
161 }
162
163 /**
164  * Take a new reference on the context.
165  */
166 XKB_EXPORT struct xkb_context *
167 xkb_context_ref(struct xkb_context *ctx)
168 {
169     ctx->refcnt++;
170     return ctx;
171 }
172
173 /**
174  * Drop an existing reference on the context, and free it if the refcnt is
175  * now 0.
176  */
177 XKB_EXPORT void
178 xkb_context_unref(struct xkb_context *ctx)
179 {
180     if (--ctx->refcnt > 0)
181         return;
182
183     xkb_context_include_path_clear(ctx);
184     atom_table_free(ctx->atom_table);
185     free(ctx);
186 }
187
188 static const char *
189 priority_to_prefix(int priority)
190 {
191     switch (priority) {
192     case LOG_DEBUG:
193         return "Debug:";
194     case LOG_INFO:
195         return "Info:";
196     case LOG_WARNING:
197         return "Warning:";
198     case LOG_ERR:
199         return "Error:";
200     case LOG_CRIT:
201     case LOG_ALERT:
202     case LOG_EMERG:
203         return "Internal error:";
204     default:
205         return NULL;
206     }
207 }
208
209 ATTR_PRINTF(3, 0) static void
210 default_log_fn(struct xkb_context *ctx, int priority,
211                const char *fmt, va_list args)
212 {
213     const char *prefix = priority_to_prefix(priority);
214
215     if (prefix)
216         fprintf(stderr, "%-15s", prefix);
217     vfprintf(stderr, fmt, args);
218 }
219
220 static int
221 log_priority(const char *priority) {
222     char *endptr;
223     int prio;
224
225     errno = 0;
226     prio = strtol(priority, &endptr, 10);
227     if (errno == 0 && (endptr[0] == '\0' || isspace(endptr[0])))
228         return prio;
229     if (strncasecmp(priority, "err", 3) == 0)
230         return LOG_ERR;
231     if (strncasecmp(priority, "warn", 4) == 0)
232         return LOG_WARNING;
233     if (strncasecmp(priority, "info", 4) == 0)
234         return LOG_INFO;
235     if (strncasecmp(priority, "debug", 5) == 0)
236         return LOG_DEBUG;
237
238     return LOG_ERR;
239 }
240
241 static int
242 log_verbosity(const char *verbosity) {
243     char *endptr;
244     int v;
245
246     errno = 0;
247     v = strtol(verbosity, &endptr, 10);
248     if (errno == 0)
249         return v;
250
251     return 0;
252 }
253
254 /**
255  * Create a new context.
256  */
257 XKB_EXPORT struct xkb_context *
258 xkb_context_new(enum xkb_context_flags flags)
259 {
260     const char *env;
261     struct xkb_context *ctx = calloc(1, sizeof(*ctx));
262
263     if (!ctx)
264         return NULL;
265
266     ctx->refcnt = 1;
267     ctx->log_fn = default_log_fn;
268     ctx->log_priority = LOG_ERR;
269     ctx->log_verbosity = 0;
270
271     /* Environment overwrites defaults. */
272     env = getenv("XKB_LOG");
273     if (env)
274         xkb_set_log_priority(ctx, log_priority(env));
275
276     env = getenv("XKB_VERBOSITY");
277     if (env)
278         xkb_set_log_verbosity(ctx, log_verbosity(env));
279
280     if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) &&
281         !xkb_context_include_path_append_default(ctx)) {
282         xkb_context_unref(ctx);
283         return NULL;
284     }
285
286     ctx->atom_table = atom_table_new();
287     if (!ctx->atom_table) {
288         xkb_context_unref(ctx);
289         return NULL;
290     }
291
292     return ctx;
293 }
294
295 xkb_atom_t
296 xkb_atom_intern(struct xkb_context *ctx, const char *string)
297 {
298     return atom_intern(ctx->atom_table, string);
299 }
300
301 char *
302 xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom)
303 {
304     return atom_strdup(ctx->atom_table, atom);
305 }
306
307 const char *
308 xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom)
309 {
310     return atom_text(ctx->atom_table, atom);
311 }
312
313 void
314 xkb_log(struct xkb_context *ctx, int priority, const char *fmt, ...)
315 {
316     va_list args;
317
318     va_start(args, fmt);
319     ctx->log_fn(ctx, priority, fmt, args);
320     va_end(args);
321 }
322
323 XKB_EXPORT void
324 xkb_set_log_fn(struct xkb_context *ctx,
325                void (*log_fn)(struct xkb_context *ctx, int priority,
326                               const char *fmt, va_list args))
327 {
328     ctx->log_fn = log_fn;
329 }
330
331 XKB_EXPORT int
332 xkb_get_log_priority(struct xkb_context *ctx)
333 {
334     return ctx->log_priority;
335 }
336
337 XKB_EXPORT void
338 xkb_set_log_priority(struct xkb_context *ctx, int priority)
339 {
340     ctx->log_priority = priority;
341 }
342
343 XKB_EXPORT int
344 xkb_get_log_verbosity(struct xkb_context *ctx)
345 {
346     return ctx->log_verbosity;
347 }
348
349 XKB_EXPORT void
350 xkb_set_log_verbosity(struct xkb_context *ctx, int verbosity)
351 {
352     ctx->log_verbosity = verbosity;
353 }
354
355 XKB_EXPORT void *
356 xkb_get_user_data(struct xkb_context *ctx)
357 {
358     if (ctx)
359         return ctx->user_data;
360     return NULL;
361 }
362
363 XKB_EXPORT void
364 xkb_set_user_data(struct xkb_context *ctx, void *user_data)
365 {
366     ctx->user_data = user_data;
367 }