OSDN Git Service

For consistency, changed English diary entries to use simple past tense. In a couple...
[hengband/hengband.git] / src / signal-handlers.c
1 /*!
2  * @file signal-handlers.c
3  * @brief シグナルハンドラの管理 / Controlling signal handlers
4  * @date 2020/02/23
5  * @author Hourier
6  */
7
8 #include "signal-handlers.h"
9 #include "core.h"
10 #include "save.h"
11 #include "world.h"
12 #include "term.h"
13 #include "io/write-diary.h"
14 #include "cmd/cmd-dump.h"
15 #include "floor-events.h"
16
17 s16b signal_count;              /* Hack -- Count interupts */
18
19 #ifdef HANDLE_SIGNALS
20
21 #include <signal.h>
22
23 /*!
24  * @brief OSからのシグナルを受けてサスペンド状態に入る /
25  * Handle signals -- suspend
26  * @param sig 受け取ったシグナル
27  * @details
28  * Actually suspend the game, and then resume cleanly
29  */
30 static void handle_signal_suspend(int sig)
31 {
32         (void)signal(sig, SIG_IGN);
33 #ifdef SIGSTOP
34         Term_fresh();
35         Term_xtra(TERM_XTRA_ALIVE, 0);
36         (void)kill(0, SIGSTOP);
37         Term_xtra(TERM_XTRA_ALIVE, 1);
38         Term_redraw();
39         Term_fresh();
40 #endif
41         (void)signal(sig, handle_signal_suspend);
42 }
43
44
45 /*!
46  * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
47  * @brief OSからのシグナルを受けて中断、終了する /
48  * Handle signals -- simple (interrupt and quit)
49  * @param sig 受け取ったシグナル
50  * @details
51  * <pre>
52  * This function was causing a *huge* number of problems, so it has
53  * been simplified greatly.  We keep a global variable which counts
54  * the number of times the user attempts to kill the process, and
55  * we commit suicide if the user does this a certain number of times.
56  * We attempt to give "feedback" to the user as he approaches the
57  * suicide thresh-hold, but without penalizing accidental keypresses.
58  * To prevent messy accidents, we should reset this global variable
59  * whenever the user enters a keypress, or something like that.
60  * </pre>
61  */
62 static void handle_signal_simple(int sig)
63 {
64         (void)signal(sig, SIG_IGN);
65         if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
66                 quit(NULL);
67
68         signal_count++;
69         if (p_ptr->is_dead)
70         {
71                 (void)strcpy(p_ptr->died_from, _("強制終了", "Abortion"));
72                 forget_lite(p_ptr->current_floor_ptr);
73                 forget_view(p_ptr->current_floor_ptr);
74                 clear_mon_lite(p_ptr->current_floor_ptr);
75                 close_game(p_ptr);
76                 quit(_("強制終了", "interrupt"));
77         }
78         else if (signal_count >= 5)
79         {
80                 (void)strcpy(p_ptr->died_from, _("強制終了中", "Interrupting"));
81                 forget_lite(p_ptr->current_floor_ptr);
82                 forget_view(p_ptr->current_floor_ptr);
83                 clear_mon_lite(p_ptr->current_floor_ptr);
84                 p_ptr->playing = FALSE;
85                 p_ptr->is_dead = TRUE;
86                 p_ptr->leaving = TRUE;
87                 close_game(p_ptr);
88                 quit(_("強制終了", "interrupt"));
89         }
90         else if (signal_count >= 4)
91         {
92                 Term_xtra(TERM_XTRA_NOISE, 0);
93                 Term_erase(0, 0, 255);
94                 Term_putstr(0, 0, -1, TERM_WHITE, _("熟慮の上の自殺!", "Contemplating suicide!"));
95                 Term_fresh();
96         }
97         else if (signal_count >= 2)
98         {
99                 Term_xtra(TERM_XTRA_NOISE, 0);
100         }
101
102         (void)signal(sig, handle_signal_simple);
103 }
104
105
106 /*!
107  * todo ここにp_ptrを追加すると関数ポインタ周りの収拾がつかなくなるので保留
108  * @brief OSからのシグナルを受けて強制終了する /
109  * Handle signal -- abort, kill, etc
110  * @param sig 受け取ったシグナル
111  * @return なし
112  * @details
113  * <pre>
114  * This function was causing a *huge* number of problems, so it has
115  * been simplified greatly.  We keep a global variable which counts
116  * the number of times the user attempts to kill the process, and
117  * we commit suicide if the user does this a certain number of times.
118  * We attempt to give "feedback" to the user as he approaches the
119  * suicide thresh-hold, but without penalizing accidental keypresses.
120  * To prevent messy accidents, we should reset this global variable
121  * whenever the user enters a keypress, or something like that.
122  * </pre>
123  */
124 static void handle_signal_abort(int sig)
125 {
126         int wid, hgt;
127         Term_get_size(&wid, &hgt);
128
129         (void)signal(sig, SIG_IGN);
130         if (!current_world_ptr->character_generated || current_world_ptr->character_saved) quit(NULL);
131
132         forget_lite(p_ptr->current_floor_ptr);
133         forget_view(p_ptr->current_floor_ptr);
134         clear_mon_lite(p_ptr->current_floor_ptr);
135
136         Term_erase(0, hgt - 1, 255);
137         Term_putstr(0, hgt - 1, -1, TERM_RED,
138                 _("恐ろしいソフトのバグが飛びかかってきた!", "A gruesome software bug LEAPS out at you!"));
139
140         Term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ...", "Panic save..."));
141
142         exe_write_diary(p_ptr, DIARY_GAMESTART, 0, _("----ゲーム異常終了----", "-- Tried Panic Save and Aborted Game --"));
143         Term_fresh();
144
145         p_ptr->panic_save = 1;
146         (void)strcpy(p_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
147
148         signals_ignore_tstp();
149
150         if (save_player(p_ptr))
151         {
152                 Term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ成功!", "Panic save succeeded!"));
153         }
154         else
155         {
156                 Term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ失敗!", "Panic save failed!"));
157         }
158
159         Term_fresh();
160         quit(_("ソフトのバグ", "software bug"));
161 }
162
163
164 /*!
165  * @brief OSからのSIGTSTPシグナルを無視する関数 /
166  * Ignore SIGTSTP signals (keyboard suspend)
167  * @return なし
168  * @details
169  */
170 void signals_ignore_tstp(void)
171 {
172 #ifdef SIGTSTP
173         (void)signal(SIGTSTP, SIG_IGN);
174 #endif
175 }
176
177
178 /*!
179  * @brief OSからのSIGTSTPシグナルハンドラ /
180  * Handle SIGTSTP signals (keyboard suspend)
181  * @return なし
182  * @details
183  */
184 void signals_handle_tstp(void)
185 {
186 #ifdef SIGTSTP
187         (void)signal(SIGTSTP, handle_signal_suspend);
188 #endif
189 }
190
191
192 /*!
193  * @brief OSからのシグナルハンドルを初期化する /
194  * Prepare to handle the relevant signals
195  * @return なし
196  * @details
197  */
198 void signals_init(void)
199 {
200 #ifdef SIGHUP
201         (void)signal(SIGHUP, SIG_IGN);
202 #endif
203
204 #ifdef SIGTSTP
205         (void)signal(SIGTSTP, handle_signal_suspend);
206 #endif
207
208 #ifdef SIGINT
209         (void)signal(SIGINT, handle_signal_simple);
210 #endif
211
212 #ifdef SIGQUIT
213         (void)signal(SIGQUIT, handle_signal_simple);
214 #endif
215
216 #ifdef SIGFPE
217         (void)signal(SIGFPE, handle_signal_abort);
218 #endif
219
220 #ifdef SIGILL
221         (void)signal(SIGILL, handle_signal_abort);
222 #endif
223
224 #ifdef SIGTRAP
225         (void)signal(SIGTRAP, handle_signal_abort);
226 #endif
227
228 #ifdef SIGIOT
229         (void)signal(SIGIOT, handle_signal_abort);
230 #endif
231
232 #ifdef SIGKILL
233         (void)signal(SIGKILL, handle_signal_abort);
234 #endif
235
236 #ifdef SIGBUS
237         (void)signal(SIGBUS, handle_signal_abort);
238 #endif
239
240 #ifdef SIGSEGV
241         (void)signal(SIGSEGV, handle_signal_abort);
242 #endif
243
244 #ifdef SIGTERM
245         (void)signal(SIGTERM, handle_signal_abort);
246 #endif
247
248 #ifdef SIGPIPE
249         (void)signal(SIGPIPE, handle_signal_abort);
250 #endif
251
252 #ifdef SIGEMT
253         (void)signal(SIGEMT, handle_signal_abort);
254 #endif
255
256 #ifdef SIGDANGER
257         (void)signal(SIGDANGER, handle_signal_abort);
258 #endif
259
260 #ifdef SIGSYS
261         (void)signal(SIGSYS, handle_signal_abort);
262 #endif
263
264 #ifdef SIGXCPU
265         (void)signal(SIGXCPU, handle_signal_abort);
266 #endif
267
268 #ifdef SIGPWR
269         (void)signal(SIGPWR, handle_signal_abort);
270 #endif
271 }
272
273 #else
274
275 /*!
276  * @brief ダミー /
277  * Do nothing
278  */
279 void signals_ignore_tstp(void)
280 {
281 }
282
283
284 /*!
285  * @brief ダミー /
286  * Do nothing
287  */
288 void signals_handle_tstp(void)
289 {
290 }
291
292
293 /*!
294  * @brief ダミー /
295  * Do nothing
296  */
297 void signals_init(void)
298 {
299 }
300 #endif