OSDN Git Service

[Fix] need_term_freshの引数忘れ
[hengband/hengband.git] / src / io / 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 "io/signal-handlers.h"
9 #include "cmd-io/cmd-dump.h"
10 #include "core/game-closer.h"
11 #include "floor/floor-events.h"
12 #include "io/write-diary.h"
13 #include "monster-floor/monster-lite.h"
14 #include "save/save.h"
15 #include "system/system-variables.h"
16 #include "term/term-color-types.h"
17 #include "world/world.h"
18
19 s16b signal_count; /* Hack -- Count interupts */
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  * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
46  * @brief OSからのシグナルを受けて中断、終了する /
47  * Handle signals -- simple (interrupt and quit)
48  * @param sig 受け取ったシグナル
49  * @details
50  * <pre>
51  * This function was causing a *huge* number of problems, so it has
52  * been simplified greatly.  We keep a global variable which counts
53  * the number of times the user attempts to kill the process, and
54  * we commit suicide if the user does this a certain number of times.
55  * We attempt to give "feedback" to the user as he approaches the
56  * suicide thresh-hold, but without penalizing accidental keypresses.
57  * To prevent messy accidents, we should reset this global variable
58  * whenever the user enters a keypress, or something like that.
59  * </pre>
60  */
61 static void handle_signal_simple(int sig)
62 {
63     (void)signal(sig, SIG_IGN);
64     if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
65         quit(NULL);
66
67     signal_count++;
68     if (p_ptr->is_dead) {
69         (void)strcpy(p_ptr->died_from, _("強制終了", "Abortion"));
70         forget_lite(p_ptr->current_floor_ptr);
71         forget_view(p_ptr->current_floor_ptr);
72         clear_mon_lite(p_ptr->current_floor_ptr);
73         close_game(p_ptr);
74         quit(_("強制終了", "interrupt"));
75     } else if (signal_count >= 5) {
76         (void)strcpy(p_ptr->died_from, _("強制終了中", "Interrupting"));
77         forget_lite(p_ptr->current_floor_ptr);
78         forget_view(p_ptr->current_floor_ptr);
79         clear_mon_lite(p_ptr->current_floor_ptr);
80         p_ptr->playing = FALSE;
81         p_ptr->is_dead = TRUE;
82         p_ptr->leaving = TRUE;
83         close_game(p_ptr);
84         quit(_("強制終了", "interrupt"));
85     } else if (signal_count >= 4) {
86         term_xtra(TERM_XTRA_NOISE, 0);
87         term_erase(0, 0, 255);
88         term_putstr(0, 0, -1, TERM_WHITE, _("熟慮の上の自殺!", "Contemplating suicide!"));
89         term_fresh();
90     } else if (signal_count >= 2) {
91         term_xtra(TERM_XTRA_NOISE, 0);
92     }
93
94     (void)signal(sig, handle_signal_simple);
95 }
96
97 /*!
98  * todo ここにp_ptrを追加すると関数ポインタ周りの収拾がつかなくなるので保留
99  * @brief OSからのシグナルを受けて強制終了する /
100  * Handle signal -- abort, kill, etc
101  * @param sig 受け取ったシグナル
102  * @return なし
103  * @details
104  * <pre>
105  * This function was causing a *huge* number of problems, so it has
106  * been simplified greatly.  We keep a global variable which counts
107  * the number of times the user attempts to kill the process, and
108  * we commit suicide if the user does this a certain number of times.
109  * We attempt to give "feedback" to the user as he approaches the
110  * suicide thresh-hold, but without penalizing accidental keypresses.
111  * To prevent messy accidents, we should reset this global variable
112  * whenever the user enters a keypress, or something like that.
113  * </pre>
114  */
115 static void handle_signal_abort(int sig)
116 {
117     int wid, hgt;
118     term_get_size(&wid, &hgt);
119
120     (void)signal(sig, SIG_IGN);
121     if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
122         quit(NULL);
123
124     forget_lite(p_ptr->current_floor_ptr);
125     forget_view(p_ptr->current_floor_ptr);
126     clear_mon_lite(p_ptr->current_floor_ptr);
127
128     term_erase(0, hgt - 1, 255);
129     term_putstr(0, hgt - 1, -1, TERM_RED, _("恐ろしいソフトのバグが飛びかかってきた!", "A gruesome software bug LEAPS out at you!"));
130
131     term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ...", "Panic save..."));
132
133     exe_write_diary(p_ptr, DIARY_GAMESTART, 0, _("----ゲーム異常終了----", "-- Tried Panic Save and Aborted Game --"));
134     term_fresh();
135
136     p_ptr->panic_save = 1;
137     (void)strcpy(p_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
138
139     signals_ignore_tstp();
140
141     if (save_player(p_ptr)) {
142         term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ成功!", "Panic save succeeded!"));
143     } else {
144         term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ失敗!", "Panic save failed!"));
145     }
146
147     term_fresh();
148     quit(_("ソフトのバグ", "software bug"));
149 }
150
151 /*!
152  * @brief OSからのSIGTSTPシグナルを無視する関数 /
153  * Ignore SIGTSTP signals (keyboard suspend)
154  * @return なし
155  * @details
156  */
157 void signals_ignore_tstp(void)
158 {
159 #ifdef SIGTSTP
160     (void)signal(SIGTSTP, SIG_IGN);
161 #endif
162 }
163
164 /*!
165  * @brief OSからのSIGTSTPシグナルハンドラ /
166  * Handle SIGTSTP signals (keyboard suspend)
167  * @return なし
168  * @details
169  */
170 void signals_handle_tstp(void)
171 {
172 #ifdef SIGTSTP
173     (void)signal(SIGTSTP, handle_signal_suspend);
174 #endif
175 }
176
177 /*!
178  * @brief OSからのシグナルハンドルを初期化する /
179  * Prepare to handle the relevant signals
180  * @return なし
181  * @details
182  */
183 void signals_init(void)
184 {
185 #ifdef SIGHUP
186     (void)signal(SIGHUP, SIG_IGN);
187 #endif
188
189 #ifdef SIGTSTP
190     (void)signal(SIGTSTP, handle_signal_suspend);
191 #endif
192
193 #ifdef SIGINT
194     (void)signal(SIGINT, handle_signal_simple);
195 #endif
196
197 #ifdef SIGQUIT
198     (void)signal(SIGQUIT, handle_signal_simple);
199 #endif
200
201 #ifdef SIGFPE
202     (void)signal(SIGFPE, handle_signal_abort);
203 #endif
204
205 #ifdef SIGILL
206     (void)signal(SIGILL, handle_signal_abort);
207 #endif
208
209 #ifdef SIGTRAP
210     (void)signal(SIGTRAP, handle_signal_abort);
211 #endif
212
213 #ifdef SIGIOT
214     (void)signal(SIGIOT, handle_signal_abort);
215 #endif
216
217 #ifdef SIGKILL
218     (void)signal(SIGKILL, handle_signal_abort);
219 #endif
220
221 #ifdef SIGBUS
222     (void)signal(SIGBUS, handle_signal_abort);
223 #endif
224
225 #ifdef SIGSEGV
226     (void)signal(SIGSEGV, handle_signal_abort);
227 #endif
228
229 #ifdef SIGTERM
230     (void)signal(SIGTERM, handle_signal_abort);
231 #endif
232
233 #ifdef SIGPIPE
234     (void)signal(SIGPIPE, handle_signal_abort);
235 #endif
236
237 #ifdef SIGEMT
238     (void)signal(SIGEMT, handle_signal_abort);
239 #endif
240
241 #ifdef SIGDANGER
242     (void)signal(SIGDANGER, handle_signal_abort);
243 #endif
244
245 #ifdef SIGSYS
246     (void)signal(SIGSYS, handle_signal_abort);
247 #endif
248
249 #ifdef SIGXCPU
250     (void)signal(SIGXCPU, handle_signal_abort);
251 #endif
252
253 #ifdef SIGPWR
254     (void)signal(SIGPWR, handle_signal_abort);
255 #endif
256 }
257