Skip to content

Latest commit

 

History

History
1202 lines (1018 loc) · 25.6 KB

mce.c

File metadata and controls

1202 lines (1018 loc) · 25.6 KB
 
Dec 16, 2010
Dec 16, 2010
1
2
3
4
/**
* @file mce.c
* Mode Control Entity - main file
* <p>
May 12, 2011
May 12, 2011
5
* Copyright © 2004-2011 Nokia Corporation and/or its subsidiary(-ies).
Jan 23, 2017
Jan 23, 2017
6
* Copyright (C) 2012-2017 Jolla Ltd.
Dec 16, 2010
Dec 16, 2010
7
8
* <p>
* @author David Weinehall <david.weinehall@nokia.com>
Jan 23, 2017
Jan 23, 2017
9
10
11
* @author Tapio Rantala <ext-tapio.rantala@nokia.com>
* @author Santtu Lakkala <ext-santtu.1.lakkala@nokia.com>
* @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
Dec 16, 2010
Dec 16, 2010
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*
* mce is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* mce is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mce. If not, see <http://www.gnu.org/licenses/>.
*/
May 27, 2014
May 27, 2014
26
#include "mce.h"
Oct 17, 2018
Oct 17, 2018
27
#include "mce-io.h"
May 27, 2014
May 27, 2014
28
#include "mce-log.h"
Jan 23, 2017
Jan 23, 2017
29
#include "mce-common.h"
May 27, 2014
May 27, 2014
30
#include "mce-conf.h"
Feb 10, 2015
Feb 10, 2015
31
#include "mce-fbdev.h"
May 19, 2015
May 19, 2015
32
#include "mce-hbtimer.h"
Oct 9, 2015
Oct 9, 2015
33
#include "mce-wltimer.h"
Mar 31, 2016
Mar 31, 2016
34
#include "mce-setting.h"
May 27, 2014
May 27, 2014
35
36
37
38
#include "mce-dbus.h"
#include "mce-dsme.h"
#include "mce-modules.h"
#include "mce-command-line.h"
Mar 15, 2015
Mar 15, 2015
39
#include "mce-sensorfw.h"
Oct 9, 2015
Oct 9, 2015
40
#include "mce-wakelock.h"
Nov 10, 2015
Nov 10, 2015
41
#include "mce-worker.h"
May 27, 2014
May 27, 2014
42
43
44
45
46
47
48
49
#include "tklock.h"
#include "powerkey.h"
#include "event-input.h"
#include "event-switches.h"
#include "modetransition.h"
#ifdef ENABLE_WAKELOCKS
# include "libwakelock.h"
#endif
Sep 16, 2013
Sep 16, 2013
50
May 27, 2014
May 27, 2014
51
52
53
54
55
56
57
58
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
May 12, 2014
May 12, 2014
59
Aug 29, 2013
Aug 29, 2013
60
61
#include <systemd/sd-daemon.h>
Dec 16, 2010
Dec 16, 2010
62
63
64
65
66
67
68
/** Path to the lockfile */
#define MCE_LOCKFILE "/var/run/mce.pid"
/** Name shown by --help etc. */
#define PRG_NAME "mce"
static const gchar *progname; /**< Used to store the name of the program */
Dec 21, 2012
Dec 21, 2012
69
70
71
/** The GMainLoop used by MCE */
static GMainLoop *mainloop = 0;
Dec 11, 2012
Dec 11, 2012
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/** Wrapper for write() for use when we do not care if it works or not
*
* Main purpose is to stop static analyzers from nagging us when
* we really do not care whether the data gets written or not
*
* @param fd file descriptor to write to
* @param data data to write
* @param size amount of data to write
*/
static void no_error_check_write(int fd, const void *data, size_t size)
{
// do the write, then ...
ssize_t rc = TEMP_FAILURE_RETRY(write(fd, data, size));
// try to silence static analyzers by doing /something/ with rc
if( rc == -1 )
rc = rc;
}
Dec 21, 2012
Dec 21, 2012
90
91
void mce_quit_mainloop(void)
{
Jan 11, 2013
Jan 11, 2013
92
#ifdef ENABLE_WAKELOCKS
Dec 21, 2012
Dec 21, 2012
93
94
/* We are on exit path -> block suspend for good */
wakelock_block_suspend_until_exit();
Jan 11, 2013
Jan 11, 2013
95
#endif
Dec 21, 2012
Dec 21, 2012
96
97
98
/* Exit immediately if there is no mainloop to terminate */
if( !mainloop ) {
Aug 18, 2014
Aug 18, 2014
99
exit(EXIT_FAILURE);
Dec 21, 2012
Dec 21, 2012
100
101
102
103
104
105
}
/* Terminate mainloop */
g_main_loop_quit(mainloop);
}
Dec 11, 2012
Dec 11, 2012
106
107
108
109
110
111
112
113
#ifdef ENABLE_WAKELOCKS
/** Disable automatic suspend and remove wakelocks mce might hold
*
* This function should be called just before mce process terminates
* so that we do not leave the system in a non-functioning state
*/
static void mce_cleanup_wakelocks(void)
{
Dec 21, 2012
Dec 21, 2012
114
115
116
/* We are on exit path -> block suspend for good */
wakelock_block_suspend_until_exit();
Dec 11, 2012
Dec 11, 2012
117
118
wakelock_unlock("mce_display_on");
wakelock_unlock("mce_input_handler");
Sep 4, 2013
Sep 4, 2013
119
wakelock_unlock("mce_cpu_keepalive");
Sep 4, 2013
Sep 4, 2013
120
wakelock_unlock("mce_display_stm");
Feb 4, 2014
Feb 4, 2014
121
wakelock_unlock("mce_powerkey_stm");
Mar 11, 2014
Mar 11, 2014
122
wakelock_unlock("mce_proximity_stm");
Apr 24, 2014
Apr 24, 2014
123
wakelock_unlock("mce_bluez_wait");
Apr 29, 2014
Apr 29, 2014
124
wakelock_unlock("mce_led_breathing");
May 8, 2014
May 8, 2014
125
wakelock_unlock("mce_lpm_off");
Oct 28, 2014
Oct 28, 2014
126
wakelock_unlock("mce_tklock_notify");
May 19, 2015
May 19, 2015
127
wakelock_unlock("mce_hbtimer_dispatch");
Sep 2, 2015
Sep 2, 2015
128
wakelock_unlock("mce_inactivity_notify");
Dec 11, 2012
Dec 11, 2012
129
130
131
132
133
134
135
136
137
138
}
#endif // ENABLE_WAKELOCKS
/** Disable autosuspend then exit via default signal handler
*
* @param signr the signal to exit through
*/
static void mce_exit_via_signal(int signr) __attribute__((noreturn));
static void mce_exit_via_signal(int signr)
{
Jan 3, 2013
Jan 3, 2013
139
140
141
142
143
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGALRM);
Dec 11, 2012
Dec 11, 2012
144
145
146
/* Give us N seconds to exit */
signal(SIGALRM, SIG_DFL);
alarm(3);
Jan 3, 2013
Jan 3, 2013
147
sigprocmask(SIG_UNBLOCK, &ss, 0);
Dec 11, 2012
Dec 11, 2012
148
Jan 3, 2013
Jan 3, 2013
149
150
151
#ifdef ENABLE_WAKELOCKS
/* Cancel auto suspend */
mce_cleanup_wakelocks();
Oct 9, 2015
Oct 9, 2015
152
mce_wakelock_abort();
Jan 3, 2013
Jan 3, 2013
153
154
#endif
/* Try to exit via default handler */
Dec 11, 2012
Dec 11, 2012
155
signal(signr, SIG_DFL);
Jan 3, 2013
Jan 3, 2013
156
157
sigaddset(&ss, signr);
sigprocmask(SIG_UNBLOCK, &ss, 0);
Dec 11, 2012
Dec 11, 2012
158
raise(signr);
Jan 3, 2013
Jan 3, 2013
159
160
/* Or just abort as the last resort*/
Dec 11, 2012
Dec 11, 2012
161
162
163
164
165
166
167
168
169
170
abort();
}
/** Suspend safe replacement for _exit(1), abort() etc
*/
void mce_abort(void)
{
mce_exit_via_signal(SIGABRT);
}
Dec 11, 2012
Dec 11, 2012
171
172
static void mce_tx_signal_cb(int sig);
Dec 16, 2010
Dec 16, 2010
173
174
175
176
177
178
179
180
181
/**
* Signal handler
*
* @param signr Signal type
*/
static void signal_handler(const gint signr)
{
switch (signr) {
case SIGUSR1:
Jan 16, 2014
Jan 16, 2014
182
183
184
185
186
187
188
189
190
191
/* switch to debug verbosity */
mce_log_set_verbosity(LL_DEBUG);
mce_log(LL_DEBUG, "switching to DEBUG verbosity level");
break;
case SIGUSR2:
/* switch to normal verbosity */
mce_log_set_verbosity(LL_DEBUG);
mce_log(LL_DEBUG, "switching to WARNING verbosity level");
mce_log_set_verbosity(LL_WARN);
Dec 16, 2010
Dec 16, 2010
192
193
194
195
196
197
break;
case SIGHUP:
/* Possibly for re-reading configuration? */
break;
Dec 11, 2012
Dec 11, 2012
198
199
case SIGINT:
case SIGQUIT:
Dec 16, 2010
Dec 16, 2010
200
case SIGTERM:
Dec 11, 2012
Dec 11, 2012
201
202
203
204
205
206
/* Just die if we somehow get here without having a mainloop */
if( !mainloop ) {
mce_exit_via_signal(signr);
}
/* Terminate mainloop */
Dec 21, 2012
Dec 21, 2012
207
mce_quit_mainloop();
Dec 16, 2010
Dec 16, 2010
208
209
210
211
break;
default:
/* Should never happen */
May 10, 2017
May 10, 2017
212
mce_log(LL_WARN, "stray signal %d received in mainloop", signr);
Dec 16, 2010
Dec 16, 2010
213
214
215
216
break;
}
}
May 10, 2017
May 10, 2017
217
218
/** Array of signals that should be ignored */
static const int mce_signals_to_ignore[] =
Dec 11, 2012
Dec 11, 2012
219
{
May 10, 2017
May 10, 2017
220
221
/* We want error return from write() & co, not a signal */
SIGPIPE,
Dec 11, 2012
Dec 11, 2012
222
May 10, 2017
May 10, 2017
223
224
225
226
227
228
/* Ignore tty signals even if mce is run from terminal */
SIGTSTP,
SIGTTOU,
SIGTTIN,
-1
};
Dec 11, 2012
Dec 11, 2012
229
May 10, 2017
May 10, 2017
230
231
232
/** Array of signals that should terminate mce */
static const int mce_signals_to_exit_on[] =
{
Dec 11, 2012
Dec 11, 2012
233
#ifdef ENABLE_WAKELOCKS
Mar 4, 2015
Mar 4, 2015
234
235
236
237
238
239
240
SIGABRT,
SIGILL,
SIGFPE,
SIGSEGV,
SIGALRM,
SIGBUS,
SIGTSTP,
Dec 11, 2012
Dec 11, 2012
241
#endif
May 10, 2017
May 10, 2017
242
243
-1
};
Dec 11, 2012
Dec 11, 2012
244
May 10, 2017
May 10, 2017
245
246
247
248
249
250
251
252
253
/** Array of signals that should be trapped */
static const int mce_signals_to_trap[] =
{
SIGUSR1,
SIGUSR2,
SIGHUP,
SIGINT,
SIGQUIT,
SIGTERM,
Mar 4, 2015
Mar 4, 2015
254
255
256
257
258
259
260
-1
};
/** Install handlers for signals we need to trap
*/
static void mce_signal_handlers_install(void)
{
May 10, 2017
May 10, 2017
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
struct sigaction sa;
/* Signals that are completely ignored */
for( size_t i = 0; mce_signals_to_ignore[i] != -1; ++i )
signal(mce_signals_to_ignore[i], SIG_IGN);
/* Unrecoverable situations that require immediate exit,
* but we should still attempt to disable autosuspend
* and clean up wakelocks: Reset default behavior when
* triggered and do not block while attempting to handle.
*/
memset(&sa, 0, sizeof sa);
sigemptyset(&sa.sa_mask);
sa.sa_handler = mce_tx_signal_cb;
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
for( size_t i = 0; mce_signals_to_exit_on[i] != -1; ++i )
sigaction(mce_signals_to_exit_on[i], &sa, 0);
/* Signals that should be ok to handle via mainloop */
memset(&sa, 0, sizeof sa);
sigemptyset(&sa.sa_mask);
sa.sa_handler = mce_tx_signal_cb;
sa.sa_flags = SA_RESTART;
for( size_t i = 0; mce_signals_to_trap[i] != -1; ++i )
sigaction(mce_signals_to_trap[i], &sa, 0);
Mar 4, 2015
Mar 4, 2015
290
}
Dec 11, 2012
Dec 11, 2012
291
Mar 4, 2015
Mar 4, 2015
292
293
294
295
/** Restore default handlers for trapped signals
*/
void mce_signal_handlers_remove(void)
{
May 10, 2017
May 10, 2017
296
297
298
299
300
301
302
for( size_t i = 0; mce_signals_to_ignore[i] != -1; ++i )
signal(mce_signals_to_ignore[i], SIG_DFL);
for( size_t i = 0; mce_signals_to_exit_on[i] != -1; ++i )
signal(mce_signals_to_exit_on[i], SIG_DFL);
for( size_t i = 0; mce_signals_to_trap[i] != -1; ++i )
Mar 4, 2015
Mar 4, 2015
303
signal(mce_signals_to_trap[i], SIG_DFL);
Dec 11, 2012
Dec 11, 2012
304
305
306
307
308
}
/** Pipe used for transferring signals out of signal handler context */
static int signal_pipe[2] = {-1, -1};
Aug 27, 2014
Aug 27, 2014
309
310
311
/** I/O watch id for signal_pipe */
static guint signal_pipe_id = 0;
Dec 11, 2012
Dec 11, 2012
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/** GIO callback for reading signals from pipe
*
* @param channel io channel for signal pipe
* @param condition call reason
* @param data user data
*
* @return TRUE (or aborts on error)
*/
static gboolean mce_rx_signal_cb(GIOChannel *channel,
GIOCondition condition, gpointer data)
{
// we just want the cb ...
(void)channel; (void)condition; (void)data;
int sig = 0;
int got = TEMP_FAILURE_RETRY(read(signal_pipe[0], &sig, sizeof sig));
if( got != sizeof sig ) {
mce_abort();
}
/* handle the signal */
signal_handler(sig);
/* keep the io watch */
return TRUE;
}
/** Signal handler callback for writing signals to pipe
*
* @param sig the signal number to pass to mainloop via pipe
*/
static void mce_tx_signal_cb(int sig)
{
/* NOTE: this function must be kept async-signal-safe! */
static volatile int exit_tries = 0;
static const char msg[] = "\n*** BREAK ***\n";
Jan 3, 2013
Jan 3, 2013
351
static const char die[] = "\n*** UNRECOVERABLE FAILURE ***\n";
Dec 11, 2012
Dec 11, 2012
352
353
354
switch( sig )
{
May 10, 2017
May 10, 2017
355
356
357
358
359
360
case SIGUSR1:
case SIGUSR2:
case SIGHUP:
/* Just pass to mainloop */
break;
Dec 11, 2012
Dec 11, 2012
361
362
363
case SIGINT:
case SIGQUIT:
case SIGTERM:
Jan 3, 2013
Jan 3, 2013
364
365
366
367
/* Make sure that a stuck or non-existing mainloop does
* not stop us from handling at least repeated terminating
signals ... */
Jan 11, 2013
Jan 11, 2013
368
#ifdef ENABLE_WAKELOCKS
Dec 21, 2012
Dec 21, 2012
369
370
/* We are on exit path -> block suspend for good */
wakelock_block_suspend_until_exit();
Jan 11, 2013
Jan 11, 2013
371
#endif
Dec 21, 2012
Dec 21, 2012
372
Dec 11, 2012
Dec 11, 2012
373
374
375
376
377
378
no_error_check_write(STDERR_FILENO, msg, sizeof msg - 1);
if( !mainloop || ++exit_tries >= 2 ) {
mce_abort();
}
break;
Jan 3, 2013
Jan 3, 2013
379
May 10, 2017
May 10, 2017
380
381
382
383
default:
/* Assume unrecoverable failure that can't be handled in
* the mainloop - disable autosuspend and then terminate
* via default signal handler. */
Jan 3, 2013
Jan 3, 2013
384
385
386
no_error_check_write(STDERR_FILENO, die, sizeof die - 1);
mce_exit_via_signal(sig);
break;
Dec 11, 2012
Dec 11, 2012
387
388
389
390
391
392
393
394
395
396
}
/* transfer the signal to mainloop via pipe */
int did = TEMP_FAILURE_RETRY(write(signal_pipe[1], &sig, sizeof sig));
if( did != (int)sizeof sig ) {
mce_abort();
}
}
Aug 27, 2014
Aug 27, 2014
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/** Remove pipe and io watch for handling signals
*/
static void mce_quit_signal_pipe(void)
{
if( signal_pipe_id )
g_source_remove(signal_pipe_id), signal_pipe_id = 0;
if( signal_pipe[0] != -1 )
close(signal_pipe[0]), signal_pipe[0] = -1;
if( signal_pipe[1] != -1 )
close(signal_pipe[1]), signal_pipe[1] = -1;
}
Dec 11, 2012
Dec 11, 2012
411
412
413
414
415
416
417
418
419
420
421
422
423
/** Create a pipe and io watch for handling signal from glib mainloop
*/
static gboolean mce_init_signal_pipe(void)
{
int result = FALSE;
GIOChannel *channel = 0;
if( pipe(signal_pipe) == -1 )
goto EXIT;
if( (channel = g_io_channel_unix_new(signal_pipe[0])) == 0 )
goto EXIT;
Aug 27, 2014
Aug 27, 2014
424
425
426
427
428
signal_pipe_id =
g_io_add_watch(channel,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
mce_rx_signal_cb, 0);
if( !signal_pipe_id )
Dec 11, 2012
Dec 11, 2012
429
430
431
432
433
434
435
436
437
438
goto EXIT;
result = TRUE;
EXIT:
if( channel != 0 ) g_io_channel_unref(channel);
return result;
}
Dec 16, 2010
Dec 16, 2010
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
/**
* Daemonize the program
*
* @return TRUE if MCE is started during boot, FALSE otherwise
*/
static gboolean daemonize(void)
{
gint retries = 0;
gint i = 0;
gchar str[10];
if (getppid() == 1)
goto EXIT; /* Already daemonized */
/* Detach from process group */
switch (fork()) {
case -1:
Dec 11, 2012
Dec 11, 2012
456
/* Parent - Failure */
Dec 16, 2010
Dec 16, 2010
457
458
459
460
461
462
463
464
465
mce_log(LL_CRIT, "daemonize: fork failed: %s",
g_strerror(errno));
exit(EXIT_FAILURE);
case 0:
/* Child */
break;
default:
Dec 11, 2012
Dec 11, 2012
466
467
468
469
470
/* Parent -- Success */
/* One main() one exit() - in this case the parent
* must not call atexit handlers etc */
_exit(EXIT_SUCCESS);
Dec 16, 2010
Dec 16, 2010
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
}
/* Detach TTY */
setsid();
/* Close all file descriptors and redirect stdio to /dev/null */
if ((i = getdtablesize()) == -1)
i = 256;
while (--i >= 0) {
if (close(i) == -1) {
if (retries > 10) {
mce_log(LL_CRIT,
"close() was interrupted more than "
"10 times. Exiting.");
exit(EXIT_FAILURE);
}
if (errno == EINTR) {
mce_log(LL_INFO,
"close() was interrupted; retrying.");
errno = 0;
i++;
retries++;
} else if (errno == EBADF) {
May 12, 2011
May 12, 2011
496
/* Ignore invalid file descriptors */
Dec 16, 2010
Dec 16, 2010
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
errno = 0;
} else {
mce_log(LL_CRIT,
"Failed to close() fd %d; %s. "
"Exiting.",
i + 1, g_strerror(errno));
exit(EXIT_FAILURE);
}
} else {
retries = 0;
}
}
if ((i = open("/dev/null", O_RDWR)) == -1) {
mce_log(LL_CRIT,
"Cannot open `/dev/null'; %s. Exiting.",
g_strerror(errno));
exit(EXIT_FAILURE);
}
if ((dup(i) == -1)) {
mce_log(LL_CRIT,
"Failed to dup() `/dev/null'; %s. Exiting.",
g_strerror(errno));
exit(EXIT_FAILURE);
}
if ((dup(i) == -1)) {
mce_log(LL_CRIT,
"Failed to dup() `/dev/null'; %s. Exiting.",
g_strerror(errno));
exit(EXIT_FAILURE);
}
/* Set umask */
umask(022);
/* Set working directory */
if ((chdir("/tmp") == -1)) {
mce_log(LL_CRIT,
"Failed to chdir() to `/tmp'; %s. Exiting.",
g_strerror(errno));
exit(EXIT_FAILURE);
}
/* Single instance */
if ((i = open(MCE_LOCKFILE, O_RDWR | O_CREAT, 0640)) == -1) {
mce_log(LL_CRIT,
"Cannot open lockfile; %s. Exiting.",
g_strerror(errno));
exit(EXIT_FAILURE);
}
if (lockf(i, F_TLOCK, 0) == -1) {
mce_log(LL_CRIT, "Already running. Exiting.");
exit(EXIT_FAILURE);
}
sprintf(str, "%d\n", getpid());
Dec 11, 2012
Dec 11, 2012
556
no_error_check_write(i, str, strlen(str));
Dec 16, 2010
Dec 16, 2010
557
558
559
560
561
562
563
564
565
566
567
568
569
570
close(i);
/* Ignore TTY signals */
signal(SIGTSTP, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
/* Ignore child terminate signal */
signal(SIGCHLD, SIG_IGN);
EXIT:
return 0;
}
Jan 11, 2013
Jan 11, 2013
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
/** Helper for determining how long common prefix two strings have
*
* @param str1 non null string
* @param str2 non null string
*
* @return length of common prefix strings share
*/
static size_t common_length(const char *str1, const char *str2)
{
size_t i;
for( i = 0; str1[i] && str1[i] == str2[i]; ++i ) {}
return i;
}
/** Handle --trace=flags options
*
* @param flags comma separated list of trace domains
*
* @return TRUE on success, FALSE if unknown domains used
*/
static gboolean mce_enable_trace(const char *flags)
{
static const struct {
const char *domain;
void (*callback)(void);
} lut[] = {
#ifdef ENABLE_WAKELOCKS
{ "wakelocks", lwl_enable_logging },
#endif
{ NULL, NULL }
};
gboolean res = TRUE;
gchar *tmp = g_strdup(flags);
gchar *now, *zen;
size_t bi, bn;
for( now = tmp; now; now = zen ) {
if( (zen = strchr(now, ',')) )
*zen++ = 0;
// initialize to: no match
bi = bn = 0;
for( size_t ti = 0; lut[ti].domain; ++ti ) {
size_t tn = common_length(lut[ti].domain, now);
// all of flag mathed?
if( now[tn] )
continue;
// better or equal as the previous best?
if( bn <= tn )
bi = ti, bn = tn;
// full match found?
if( !lut[ti].domain[tn] )
break;
}
// did we find a match?
if( !bn ) {
fprintf(stderr, "unknown trace domain: '%s'\n", now);
res = FALSE;
}
else {
// report if non-full match was used
if( lut[bi].domain[bn] )
fprintf(stderr, "trace: %s\n", lut[bi].domain);
lut[bi].callback();
}
}
g_free(tmp);
return res;
}
May 12, 2014
May 12, 2014
649
650
651
652
653
654
655
656
657
658
659
660
/* ========================================================================= *
* COMMAND LINE OPTIONS
* ========================================================================= */
static struct
{
bool daemonflag;
int logtype;
int verbosity;
bool systembus;
bool show_module_info;
bool systemd_notify;
May 12, 2017
May 12, 2017
661
bool valgrind_mode;
May 28, 2018
May 28, 2018
662
bool sensortest_mode;
Jan 22, 2015
Jan 22, 2015
663
int auto_exit;
May 12, 2014
May 12, 2014
664
665
666
667
668
669
670
671
} mce_args =
{
.daemonflag = false,
.logtype = MCE_LOG_SYSLOG,
.verbosity = LL_DEFAULT,
.systembus = true,
.show_module_info = false,
.systemd_notify = false,
May 12, 2017
May 12, 2017
672
.valgrind_mode = false,
May 28, 2018
May 28, 2018
673
.sensortest_mode = false,
Jan 22, 2015
Jan 22, 2015
674
.auto_exit = -1,
May 12, 2014
May 12, 2014
675
676
};
May 12, 2017
May 12, 2017
677
678
679
680
681
bool mce_in_valgrind_mode(void)
{
return mce_args.valgrind_mode;
}
May 28, 2018
May 28, 2018
682
683
684
685
686
bool mce_in_sensortest_mode(void)
{
return mce_args.sensortest_mode;
}
May 12, 2014
May 12, 2014
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
static bool mce_do_help(const char *arg);
static bool mce_do_version(const char *arg);
static bool mce_do_daemonize(const char *arg)
{
(void)arg;
mce_args.daemonflag = true;
return true;
}
static bool mce_do_force_stderr(const char *arg)
{
(void)arg;
mce_args.logtype = MCE_LOG_STDERR;
return true;
}
static bool mce_do_force_syslog(const char *arg)
{
(void)arg;
mce_args.logtype = MCE_LOG_SYSLOG;
return true;
}
Jan 22, 2015
Jan 22, 2015
711
712
713
714
715
static bool mce_do_auto_exit(const char *arg)
{
mce_args.auto_exit = arg ? strtol(arg, 0, 0) : 5;
return true;
}
May 12, 2017
May 12, 2017
716
717
718
719
720
721
static bool mce_do_valgrind_mode(const char *arg)
{
(void)arg;
mce_args.valgrind_mode = true;
return true;
}
May 28, 2018
May 28, 2018
722
723
724
725
726
727
static bool mce_do_sensortest_mode(const char *arg)
{
(void)arg;
mce_args.sensortest_mode = true;
return true;
}
May 12, 2014
May 12, 2014
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
static bool mce_do_log_function(const char *arg)
{
mce_log_add_pattern(arg);
return true;
}
static bool mce_do_verbose(const char *arg)
{
(void)arg;
if( mce_args.verbosity < LL_DEBUG )
mce_args.verbosity++;
return true;
}
static bool mce_do_quiet(const char *arg)
{
(void)arg;
if( mce_args.verbosity > LL_NONE )
mce_args.verbosity--;
return true;
}
static bool mce_do_session_bus(const char *arg)
{
(void)arg;
mce_args.systembus = false;
return true;
}
static bool mce_do_show_module_info(const char *arg)
{
(void)arg;
mce_args.show_module_info = true;
return true;
}
static bool mce_do_systemd(const char *arg)
{
(void)arg;
mce_args.systemd_notify = true;
return true;
}
static bool mce_do_trace(const char *arg)
{
return mce_enable_trace(arg);
}
static const mce_opt_t options[] =
{
{
.name = "help",
.flag = 'h',
.with_arg = mce_do_help,
.without_arg = mce_do_help,
.values = "option|\"all\"",
.usage =
"Show usage information\n"
"\n"
"If the optional argument is given, more detailed information is\n"
"given about matching options. Using \"all\" lists all options\n"
},
{
.name = "version",
.flag = 'V',
.without_arg = mce_do_version,
.usage =
"Output version information and exit\n"
},
{
.name = "verbose",
.flag = 'v',
.without_arg = mce_do_verbose,
.usage =
"Increase debug message verbosity\n"
},
{
.name = "quiet",
.flag = 'q',
.without_arg = mce_do_quiet,
.usage =
"Decrease debug message verbosity\n"
},
{
.name = "systemd",
.flag = 'n',
.without_arg = mce_do_systemd,
.usage =
"Notify systemd when started up\n"
},
{
.name = "daemonflag",
.flag = 'd',
.without_arg = mce_do_daemonize,
.usage =
"Run MCE as a daemon\n"
},
{
.name = "force-syslog",
.flag = 's',
.without_arg = mce_do_force_syslog,
.usage =
"Log to syslog even when not daemonized\n"
},
{
.name = "force-stderr",
.flag = 'T',
.without_arg = mce_do_force_stderr,
.usage =
"Log to stderr even when daemonized\n"
},
{
.name = "session",
.flag = 'S',
.without_arg = mce_do_session_bus,
.usage =
"Use the session bus instead of the system bus for D-Bus\n"
},
{
.name = "show-module-info",
.flag = 'M',
.without_arg = mce_do_show_module_info,
.usage =
"Show information about loaded modules\n"
},
{
.name = "trace",
.flag = 't',
.with_arg = mce_do_trace,
.values = "what",
.usage =
"enable domain specific debug logging; supported values:\n"
" wakelocks\n"
},
{
.name = "log-function",
.flag = 'l',
.with_arg = mce_do_log_function,
.values = "file:func",
.usage =
"Add function logging override"
},
Jan 22, 2015
Jan 22, 2015
879
880
881
882
883
884
885
886
887
888
{
.name = "auto-exit",
.values = "seconds",
.with_arg = mce_do_auto_exit,
.without_arg = mce_do_auto_exit,
.usage =
"Exit after mainloop gets idle\n"
"\n"
"This is usefult for mce startup debugging only.\n"
},
May 12, 2017
May 12, 2017
889
890
891
892
893
894
{
.name = "valgrind-mode",
.without_arg = mce_do_valgrind_mode,
.usage =
"Enable run-under valgrind mode\n"
},
May 28, 2018
May 28, 2018
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
{
.name = "sensortest-mode",
.without_arg = mce_do_sensortest_mode,
.usage =
"Enable track-all-sensors mode\n"
"\n"
"Intents to provide a quick way to check whether\n"
"sensor adaptation is in a state where all sensors\n"
"that are supposedly supported actually report\n"
"changes via sensorfwd interfaces.\n"
"\n"
"This is mainly useful when porting to new devices.\n"
"\n"
"Suggested usage is to manually execute mce in a way\n"
"where it is otherwise quiet, but debug logging for\n"
"sensor related activity is enabled, for example:\n"
"\n"
" mce --sensortest-mode -Tqqq -lmce-sensorfw.c:*\n"
},
May 12, 2014
May 12, 2014
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
// sentinel
{
.name = 0
}
};
static bool mce_do_version(const char *arg)
{
(void)arg;
static const char vers[] = G_STRINGIFY(PRG_VERSION);
static const char info[] =
"Written by David Weinehall.\n"
"\n"
"Copyright (C) 2004-2010 Nokia Corporation. "
"All rights reserved.\n";
fprintf(stdout, "%s v%s\n%s", progname, vers, info);
exit(EXIT_SUCCESS);
}
static bool mce_do_help(const char *arg)
{
fprintf(stdout,
"Mode Control Entity\n"
"\n"
"USAGE\n"
"\tmce [OPTION] ...\n"
"\n"
"OPTIONS\n");
mce_command_line_usage(options, arg);
if( !arg )
goto EXIT;
fprintf(stdout,
"REPORTING BUGS\n"
"\tSend e-mail to: <simo.piiroinen@jollamobile.com>\n");
EXIT:
exit(EXIT_SUCCESS);
}
Jan 22, 2015
Jan 22, 2015
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
static gboolean mce_auto_exit_cb(gpointer aptr)
{
(void)aptr;
if( mce_args.auto_exit <= 0 ) {
mce_log(LL_WARN, "exit");
mce_quit_mainloop();
}
else {
mce_log(LL_WARN, "idle");
g_timeout_add_seconds(mce_args.auto_exit, mce_auto_exit_cb, 0);
mce_args.auto_exit = 0;
}
return FALSE;
}
May 12, 2014
May 12, 2014
974
975
976
977
/* ========================================================================= *
* MAIN ENTRY POINT
* ========================================================================= */
Dec 16, 2010
Dec 16, 2010
978
979
980
981
982
983
984
985
986
/**
* Main
*
* @param argc Number of command line arguments
* @param argv Array with command line arguments
* @return 0 on success, non-zero on failure
*/
int main(int argc, char **argv)
{
May 12, 2014
May 12, 2014
987
int status = EXIT_FAILURE;
Dec 16, 2010
Dec 16, 2010
988
Mar 14, 2015
Mar 14, 2015
989
990
/* Set the program-name */
progname = PRG_NAME;
Dec 16, 2010
Dec 16, 2010
991
992
/* Parse the command-line options */
May 12, 2014
May 12, 2014
993
994
if( !mce_command_line_parse(options, argc, argv) )
goto EXIT;
Dec 16, 2010
Dec 16, 2010
995
996
997
/* We don't take any non-flag arguments */
if ((argc - optind) > 0) {
May 27, 2014
May 27, 2014
998
999
fprintf(stderr, "%s: Too many arguments\n"
"Try: `%s --help' for more information.\n",
Dec 16, 2010
Dec 16, 2010
1000
progname, progname);