"Fossies" - the Fresh Open Source Software Archive 
Member "shake-1.0/signals.c" (15 Nov 2014, 5295 Bytes) of package /linux/privat/shake-1.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "signals.c" see the
Fossies "Dox" file reference documentation.
1 /***************************************************************************/
2 /* Copyright (C) 2006-2011 Brice Arnould. */
3 /* */
4 /* This file is part of ShaKe. */
5 /* */
6 /* ShaKe is free software; you can redistribute it and/or modify */
7 /* it under the terms of the GNU General Public License as published by */
8 /* the Free Software Foundation; either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* This program is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public License */
17 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /***************************************************************************/
19
20 #include "linux.h" // OS_RESERVED_SIGNAL
21 #include "signals.h"
22 #include <assert.h> // assert()
23 #include <errno.h> // errno
24 #include <error.h> // error()
25 #include <signal.h> // sigaction, sigprocmask, sigsetops
26 #include <unistd.h> // unlink()
27 #include <stdbool.h>
28
29 /* Those variables would have to be put in a thread-specific storage
30 * for ShaKe to be multithread
31 */
32 static const char *current_msg = NULL;
33 static const char *current_tempfile = NULL;
34 static const char *current_file = NULL; // The file being shaked
35 static volatile enum mode current_mode; // Tell in which mode we are, cf signals.h
36
37 /* If we're in CRITICAL mode, display current_msg and exit,
38 * if we're in PREPARE mode, cancel the backup by going in cancel mode
39 * else unlink the current_tempfile and call he default handler
40 */
41 static void
42 handle_signals (int sig)
43 {
44 if (current_mode == CRITICAL)
45 {
46 /* Appart from SIGLOCKEXPIRED, we receive only SIGILL, SIGFPE or
47 * SIGSEG in this mode (that is, fatal signals) */
48 assert (current_msg);
49 error (1, 0, "%s", current_msg);
50 }
51 else
52 {
53 assert (current_tempfile);
54 unlink (current_tempfile);
55 // Calls the default handler, because sa_flags == SA_RESETHAND
56 raise (sig);
57 }
58 }
59
60 /* Does what sigaction() would, except if the previous
61 * handler is SIG_IGN in which case it does nothing.
62 */
63 static int
64 sigaction_or_ignore (int signum, const struct sigaction *action,
65 struct sigaction *old_action_res)
66 {
67 struct sigaction old_action;
68 if (-1 == sigaction (signum, NULL, &old_action))
69 return -1;
70 else if (SIG_IGN == old_action.sa_handler)
71 {
72 /* Signal was set to "ignore", do not change it,
73 * but set old_action_res if it is not NULL
74 */
75 if (NULL != old_action_res)
76 *old_action_res = old_action;
77 return 0;
78 }
79 else
80 return sigaction (signum, action, old_action_res);
81 }
82
83
84 void
85 install_sighandler (const char *tempfile)
86 {
87 assert (tempfile);
88 struct sigaction sa;
89 current_tempfile = tempfile;
90 sigemptyset (&sa.sa_mask);
91 // All signals after the firsts will be handled by system's default
92 // handlers
93 sa.sa_flags = SA_RESETHAND;
94 // Automatically restart syscalls after handling a signal
95 sa.sa_flags |= SA_RESTART;
96 sa.sa_handler = handle_signals;
97 /* Set our handler as the one that will handle critical situations */
98 sigaction (SIGFPE, &sa, NULL);
99 sigaction (SIGILL, &sa, NULL);
100 sigaction (SIGPIPE, &sa, NULL);
101 sigaction (SIGSEGV, &sa, NULL);
102 sigaction (SIGTERM, &sa, NULL);
103 sigaction (SIGUSR1, &sa, NULL);
104 sigaction (SIGUSR2, &sa, NULL);
105 sigaction (SIGBUS, &sa, NULL);
106 sigaction (SIGXCPU, &sa, NULL);
107 sigaction (SIGXFSZ, &sa, NULL);
108 /* The same holds terminal-related signals, except that we need to
109 * take in account the shell's dispositions.
110 */
111 sigaction_or_ignore (SIGHUP, &sa, NULL);
112 sigaction_or_ignore (SIGINT, &sa, NULL);
113 sigaction_or_ignore (SIGQUIT, &sa, NULL);
114 sigaction_or_ignore (SIGTTIN, &sa, NULL);
115 sigaction_or_ignore (SIGTTOU, &sa, NULL);
116 /* Set the NORMAL mode */
117 enter_normal_mode ();
118 }
119
120 void
121 enter_normal_mode (void)
122 {
123 sigset_t sset;
124 assert (NORMAL != current_mode);
125 sigfillset (&sset);
126 current_mode = NORMAL;
127 current_msg = NULL;
128 current_file = NULL;
129 sigprocmask (SIG_UNBLOCK, &sset, NULL);
130 }
131
132 void
133 enter_critical_mode (const char *msg)
134 {
135 sigset_t sset;
136 assert (CRITICAL != current_mode);
137 sigfillset (&sset);
138 current_msg = msg;
139 /* Don't suspend signals raised by internal errors */
140 sigdelset (&sset, SIGILL);
141 sigdelset (&sset, SIGFPE);
142 sigdelset (&sset, SIGSEGV);
143 /* Don't suspend signals reserved for use by the OS-specific layer */
144 sigdelset (&sset, OS_RESERVED_SIGNAL);
145 /* Stop and suspend works as usual */
146 sigdelset (&sset, SIGTSTP);
147 sigdelset (&sset, SIGSTOP);
148 sigprocmask (SIG_BLOCK, &sset, NULL);
149 current_mode = CRITICAL;
150 }