File:
src/core/linux/SDL_evdev_kbd.c
Checker name:
clang-diagnostic-sign-compare
Review status:
Unreviewed
/*
119
diacr->diacr, diacr->base, diacr->result);
120
}
121
while (i < 256) {
122
printf(" { 0x00, 0x00, 0x00 },\n");
123
++i;
124
}
125
printf(" }\n");
126
printf("};\n");
127
}
128
/* DUMP_ACCENTS */
129
130
131
static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
132
{
133
int i, j;
134
135
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
136
if (kbd->key_maps[i]) {
137
printf("static unsigned short default_key_map_%d[NR_KEYS] = {", i);
138
for (j = 0; j < NR_KEYS; ++j) {
139
if ((j % 8) == 0) {
140
printf("\n ");
141
}
142
printf("0x%.4x, ", kbd->key_maps[i][j]);
143
}
144
printf("\n};\n");
145
}
146
}
147
printf("\n");
148
printf("static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
149
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
150
if (kbd->key_maps[i]) {
151
printf(" default_key_map_%d,\n", i);
152
} else {
153
printf(" NULL,\n");
154
}
155
}
156
printf("};\n");
157
}
158
/* DUMP_KEYMAP */
159
160
static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL;
161
static int kbd_cleanup_sigactions_installed = 0;
162
static int kbd_cleanup_atexit_installed = 0;
163
164
static struct sigaction old_sigaction[NSIG];
165
166
static int fatal_signals[] = {
167
/* Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. */
168
SIGHUP, SIGQUIT, SIGILL, SIGABRT,
169
SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
170
SIGSYS
171
};
172
173
static void kbd_cleanup(void)
174
{
175
SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state;
176
if (!kbd) {
177
return;
178
}
179
kbd_cleanup_state = NULL;
180
181
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
182
}
183
184
static void SDL_EVDEV_kbd_reraise_signal(int sig)
185
{
186
(void)raise(sig);
187
}
188
189
static siginfo_t *SDL_EVDEV_kdb_cleanup_siginfo = NULL;
190
static void *SDL_EVDEV_kdb_cleanup_ucontext = NULL;
191
192
static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontext)
193
{
194
struct sigaction *old_action_p = &(old_sigaction[signum]);
195
sigset_t sigset;
196
197
/* Restore original signal handler before going any further. */
198
sigaction(signum, old_action_p, NULL);
199
200
/* Unmask current signal. */
201
sigemptyset(&sigset);
202
sigaddset(&sigset, signum);
203
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
204
205
/* Save original signal info and context for archeologists. */
206
SDL_EVDEV_kdb_cleanup_siginfo = info;
207
SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
208
209
/* Restore keyboard. */
210
kbd_cleanup();
211
212
/* Reraise signal. */
213
SDL_EVDEV_kbd_reraise_signal(signum);
214
}
215
216
static void kbd_unregister_emerg_cleanup(void)
217
{
218
int tabidx;
219
220
kbd_cleanup_state = NULL;
221
222
if (!kbd_cleanup_sigactions_installed) {
223
return;
224
}
225
kbd_cleanup_sigactions_installed = 0;
226
227
for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
228
struct sigaction *old_action_p;
229
struct sigaction cur_action;
230
int signum = fatal_signals[tabidx];
231
old_action_p = &(old_sigaction[signum]);
232
233
/* Examine current signal action */
234
if (sigaction(signum, NULL, &cur_action)) {
235
continue;
236
}
237
238
/* Check if action installed and not modified */
239
if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) {
240
continue;
241
}
242
243
/* Restore original action */
244
sigaction(signum, old_action_p, NULL);
245
}
246
}
247
248
static void kbd_cleanup_atexit(void)
249
{
250
/* Restore keyboard. */
251
kbd_cleanup();
252
253
/* Try to restore signal handlers in case shared library is being unloaded */
254
kbd_unregister_emerg_cleanup();
255
}
256
257
static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd)
258
{
259
int tabidx;
260
261
if (kbd_cleanup_state) {
262
return;
263
}
264
kbd_cleanup_state = kbd;
265
266
if (!kbd_cleanup_atexit_installed) {
267
/* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish
268
* functions that are called when the shared library is unloaded.
269
* -- man atexit(3)
270
*/
271
(void)atexit(kbd_cleanup_atexit);
272
kbd_cleanup_atexit_installed = 1;
273
}
274
275
if (kbd_cleanup_sigactions_installed) {
276
return;
277
}
278
kbd_cleanup_sigactions_installed = 1;
279
280
for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
281
struct sigaction *old_action_p;
282
struct sigaction new_action;
283
int signum = fatal_signals[tabidx];
284
old_action_p = &(old_sigaction[signum]);
285
if (sigaction(signum, NULL, old_action_p)) {
286
continue;
287
}
288
289
/* Skip SIGHUP and SIGPIPE if handler is already installed
290
* - assume the handler will do the cleanup
291
*/
292
if ((signum == SIGHUP || signum == SIGPIPE) && (old_action_p->sa_handler != SIG_DFL || (void (*)(int))old_action_p->sa_sigaction != SIG_DFL)) {
293
continue;
294
}
295
296
new_action = *old_action_p;
297
new_action.sa_flags |= SA_SIGINFO;
298
new_action.sa_sigaction = &kbd_cleanup_signal_action;
299
sigaction(signum, &new_action, NULL);
300
}
301
}
302
303
enum {
304
VT_SIGNAL_NONE,
305
VT_SIGNAL_RELEASE,
306
VT_SIGNAL_ACQUIRE,
307
};
308
static int vt_release_signal;
309
static int vt_acquire_signal;
310
static SDL_AtomicInt vt_signal_pending;
311
312
typedef void (*signal_handler)(int signum);
313
314
static void kbd_vt_release_signal_action(int signum)
315
{
316
SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_RELEASE);
317
}
318
319
static void kbd_vt_acquire_signal_action(int signum)
320
{
321
SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_ACQUIRE);
322
}
323
324
static SDL_bool setup_vt_signal(int signum, signal_handler handler)
325
{
326
struct sigaction *old_action_p;
327
struct sigaction new_action;
328
old_action_p = &(old_sigaction[signum]);
329
SDL_zero(new_action);
330
new_action.sa_handler = handler;
331
new_action.sa_flags = SA_RESTART;
332
if (sigaction(signum, &new_action, old_action_p) < 0) {
333
return SDL_FALSE;
334
}
335
if (old_action_p->sa_handler != SIG_DFL) {
336
/* This signal is already in use */
337
sigaction(signum, old_action_p, NULL);