]> git.ipfire.org Git - thirdparty/util-linux.git/blame - include/debug.h
tests: make sure TS_HELPER_MBSENCODE compiled
[thirdparty/util-linux.git] / include / debug.h
CommitLineData
db08389d
OO
1/*
2 * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
ef316a27 3 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
db08389d
OO
4 *
5 * This file may be distributed under the terms of the
6 * GNU Lesser General Public License.
7 */
8#ifndef UTIL_LINUX_DEBUG_H
9#define UTIL_LINUX_DEBUG_H
10
ef316a27
KZ
11
12/*
13 * util-linux debug macros
14 *
15 * The debug stuff is based on <name>_debug_mask that controls what outputs is
16 * expected. The mask is usually initialized by <NAME>_DEBUG= env.variable
17 *
18 * After successful initialization the flag <PREFIX>_DEBUG_INIT is always set
19 * to the mask (this flag is required). The <PREFIX> is usually library API
20 * prefix (e.g. MNT_) or program name (e.g. CFDISK_)
21 *
22 * In the code is possible to use
23 *
24 * DBG(FOO, ul_debug("this is output for foo"));
25 *
26 * where for the FOO has to be defined <PREFIX>_DEBUG_FOO.
27 *
28 * It's possible to initialize the mask by comma delimited strings with
29 * subsystem names (e.g. "LIBMOUNT_DEBUG=options,tab"). In this case is
30 * necessary to define mask names array. This functionality is optional.
31 *
9e930041 32 * It's strongly recommended to use UL_* macros to define/declare/use
ef316a27
KZ
33 * the debug stuff.
34 *
35 * See disk-utils/cfdisk.c: cfdisk_init_debug() for programs debug
36 * or libmount/src/init.c: mnt_init_debug() for library debug
37 *
38 */
39
db08389d 40#include <stdarg.h>
14ad2353 41#include <string.h>
db08389d 42
ef316a27
KZ
43struct ul_debug_maskname {
44 const char *name;
45 int mask;
46 const char *help;
47};
48#define UL_DEBUG_EMPTY_MASKNAMES {{ NULL, 0, NULL }}
49#define UL_DEBUG_DEFINE_MASKNAMES(m) static const struct ul_debug_maskname m ## _masknames[]
50#define UL_DEBUG_MASKNAMES(m) m ## _masknames
1e063303 51
6d00cfb2
KZ
52#define UL_DEBUG_MASK(m) m ## _debug_mask
53#define UL_DEBUG_DEFINE_MASK(m) int UL_DEBUG_MASK(m)
cb3fa847
OO
54#define UL_DEBUG_DECLARE_MASK(m) extern UL_DEBUG_DEFINE_MASK(m)
55
6d00cfb2
KZ
56/*
57 * Internal mask flags (above 0xffffff)
58 */
59#define __UL_DEBUG_FL_NOADDR (1 << 24) /* Don't print object address */
60
cb3fa847
OO
61
62/* l - library name, p - flag prefix, m - flag postfix, x - function */
e7b49879 63#define __UL_DBG(l, p, m, x) \
d282c88d
KZ
64 do { \
65 if ((p ## m) & l ## _debug_mask) { \
66 fprintf(stderr, "%d: %s: %8s: ", getpid(), # l, # m); \
67 x; \
68 } \
69 } while (0)
db08389d 70
e7b49879
KZ
71#define __UL_DBG_CALL(l, p, m, x) \
72 do { \
73 if ((p ## m) & l ## _debug_mask) { \
74 x; \
75 } \
76 } while (0)
77
78#define __UL_DBG_FLUSH(l, p) \
79 do { \
80 if (l ## _debug_mask && \
81 l ## _debug_mask != p ## INIT) { \
82 fflush(stderr); \
83 } \
84 } while (0)
85
a15dca2f 86#define __UL_INIT_DEBUG_FROM_STRING(lib, pref, mask, str) \
d282c88d
KZ
87 do { \
88 if (lib ## _debug_mask & pref ## INIT) \
89 ; \
a15dca2f
KZ
90 else if (!mask && str) { \
91 lib ## _debug_mask = ul_debug_parse_mask(lib ## _masknames, str); \
d282c88d
KZ
92 } else \
93 lib ## _debug_mask = mask; \
6d00cfb2 94 if (lib ## _debug_mask) { \
66643f31 95 if (getuid() != geteuid() || getgid() != getegid()) { \
6d00cfb2 96 lib ## _debug_mask |= __UL_DEBUG_FL_NOADDR; \
7bd0c1ae 97 fprintf(stderr, "%d: %s: don't print memory addresses (SUID executable).\n", getpid(), # lib); \
66643f31 98 } \
6d00cfb2 99 } \
d282c88d 100 lib ## _debug_mask |= pref ## INIT; \
d282c88d 101 } while (0)
db08389d 102
14ad2353 103
a15dca2f
KZ
104#define __UL_INIT_DEBUG_FROM_ENV(lib, pref, mask, env) \
105 do { \
106 const char *envstr = mask ? NULL : getenv(# env); \
107 __UL_INIT_DEBUG_FROM_STRING(lib, pref, mask, envstr); \
108 } while (0)
109
110
111
db08389d
OO
112static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
113ul_debug(const char *mesg, ...)
114{
115 va_list ap;
116 va_start(ap, mesg);
117 vfprintf(stderr, mesg, ap);
118 va_end(ap);
119 fputc('\n', stderr);
120}
121
a15dca2f 122static inline int ul_debug_parse_mask(
ef316a27
KZ
123 const struct ul_debug_maskname flagnames[],
124 const char *mask)
14ad2353
OO
125{
126 int res;
127 char *ptr;
128
129 /* let's check for a numeric mask first */
130 res = strtoul(mask, &ptr, 0);
131
132 /* perhaps it's a comma-separated string? */
ef316a27 133 if (ptr && *ptr && flagnames && flagnames[0].name) {
14ad2353
OO
134 char *msbuf, *ms, *name;
135 res = 0;
136
137 ms = msbuf = strdup(mask);
138 if (!ms)
139 return res;
140
141 while ((name = strtok_r(ms, ",", &ptr))) {
ef316a27 142 const struct ul_debug_maskname *d;
14ad2353
OO
143 ms = ptr;
144
ef316a27
KZ
145 for (d = flagnames; d && d->name; d++) {
146 if (strcmp(name, d->name) == 0) {
147 res |= d->mask;
14ad2353
OO
148 break;
149 }
14ad2353
OO
150 }
151 /* nothing else we can do by OR-ing the mask */
152 if (res == 0xffff)
153 break;
154 }
155 free(msbuf);
ef316a27
KZ
156 } else if (ptr && strcmp(ptr, "all") == 0)
157 res = 0xffff;
158
14ad2353
OO
159 return res;
160}
ef316a27
KZ
161
162static inline void ul_debug_print_masks(
163 const char *env,
164 const struct ul_debug_maskname flagnames[])
165{
166 const struct ul_debug_maskname *d;
167
168 if (!flagnames)
169 return;
170
171 fprintf(stderr, "Available \"%s=<name>[,...]|<mask>\" debug masks:\n",
172 env);
173 for (d = flagnames; d && d->name; d++) {
174 if (!d->help)
175 continue;
176 fprintf(stderr, " %-8s [0x%04x] : %s\n",
177 d->name, d->mask, d->help);
178 }
179}
180
db08389d 181#endif /* UTIL_LINUX_DEBUG_H */