xref: /dragonfly/games/larn/signal.c (revision a8718c14)
1 /* "Larn is copyrighted 1986 by Noah Morgan.\n" */
2 
3 #include <signal.h>
4 #include "header.h"
5 
6 static void s2choose(void);
7 static void cntlc(int);
8 static void sgam(int);
9 #ifdef SIGTSTP
10 static void tstop(int);
11 #endif
12 static void sigill(int);
13 static void sigtrap(int);
14 static void sigiot(int);
15 static void sigemt(int);
16 static void sigfpe(int);
17 static void sigbus(int);
18 static void sigsegv(int);
19 static void sigsys(int);
20 static void sigpipe(int);
21 static void sigterm(int);
22 static void sigpanic(int);
23 
24 #define BIT(a) (1<<((a)-1))
25 
26 static void
s2choose(void)27 s2choose(void)	/* text to be displayed if ^C during intro screen */
28 {
29 	cursor(1, 24);
30 	lprcat("Press ");
31 	setbold();
32 	lprcat("return");
33 	resetbold();
34 	lprcat(" to continue: ");
35 	lflush();
36 }
37 
38 static void
cntlc(__unused int sig)39 cntlc(__unused int sig)	/* what to do for a ^C */
40 {
41 	if (nosignal)	/* don't do anything if inhibited */
42 		return;
43 	signal(SIGQUIT, SIG_IGN);
44 	signal(SIGINT, SIG_IGN);
45 	quit();
46 	if (predostuff == 1)
47 		s2choose();
48 	else
49 		showplayer();
50 	lflush();
51 	signal(SIGQUIT, cntlc);
52 	signal(SIGINT, cntlc);
53 }
54 
55 /*
56  *	subroutine to save the game if a hangup signal
57  */
58 static void
sgam(__unused int sig)59 sgam(__unused int sig)
60 {
61 	savegame(savefilename);
62 	wizard = 1;
63 	died(-257);		/* hangup signal */
64 }
65 
66 #ifdef SIGTSTP
67 static void
tstop(__unused int sig)68 tstop(__unused int sig) /* control Y */
69 {
70 	if (nosignal)		/* nothing if inhibited */
71 		return;
72 	lcreat(NULL);
73 	clearvt100();
74 	lflush();
75 	signal(SIGTSTP, SIG_DFL);
76 #ifdef SIGVTALRM
77 	/* looks like BSD4.2 or higher - must clr mask for signal to take effect*/
78 	sigsetmask(sigblock(0) & ~BIT(SIGTSTP));
79 #endif
80 	kill(getpid(), SIGTSTP);
81 
82 	setupvt100();
83 	signal(SIGTSTP, tstop);
84 	if (predostuff == 1)
85 		s2choose();
86 	else
87 		drawscreen();
88 	showplayer();
89 	lflush();
90 }
91 #endif /* SIGTSTP */
92 
93 /*
94  *	subroutine to issue the needed signal traps  called from main()
95  */
96 static void
sigill(__unused int sig)97 sigill(__unused int sig)
98 {
99 	sigpanic(SIGILL);
100 }
101 
102 static void
sigtrap(__unused int sig)103 sigtrap(__unused int sig)
104 {
105 	sigpanic(SIGTRAP);
106 }
107 
108 static void
sigiot(__unused int sig)109 sigiot(__unused int sig)
110 {
111 	sigpanic(SIGIOT);
112 }
113 
114 static void
sigemt(__unused int sig)115 sigemt(__unused int sig)
116 {
117 	sigpanic(SIGEMT);
118 }
119 
120 static void
sigfpe(__unused int sig)121 sigfpe(__unused int sig)
122 {
123 	sigpanic(SIGFPE);
124 }
125 
126 static void
sigbus(__unused int sig)127 sigbus(__unused int sig)
128 {
129 	sigpanic(SIGBUS);
130 }
131 
132 static void
sigsegv(__unused int sig)133 sigsegv(__unused int sig)
134 {
135 	sigpanic(SIGSEGV);
136 }
137 
138 static void
sigsys(__unused int sig)139 sigsys(__unused int sig)
140 {
141 	sigpanic(SIGSYS);
142 }
143 
144 static void
sigpipe(__unused int sig)145 sigpipe(__unused int sig)
146 {
147 	sigpanic(SIGPIPE);
148 }
149 
150 static void
sigterm(__unused int sig)151 sigterm(__unused int sig)
152 {
153 	sigpanic(SIGTERM);
154 }
155 
156 void
sigsetup(void)157 sigsetup(void)
158 {
159 	signal(SIGQUIT, cntlc);
160 	signal(SIGINT, cntlc);
161 	signal(SIGKILL, SIG_IGN);
162 	signal(SIGHUP, sgam);
163 	signal(SIGILL, sigill);
164 	signal(SIGTRAP, sigtrap);
165 	signal(SIGIOT, sigiot);
166 	signal(SIGEMT, sigemt);
167 	signal(SIGFPE, sigfpe);
168 	signal(SIGBUS, sigbus);
169 	signal(SIGSEGV, sigsegv);
170 	signal(SIGSYS, sigsys);
171 	signal(SIGPIPE, sigpipe);
172 	signal(SIGTERM, sigterm);
173 #ifdef SIGTSTP
174 	signal(SIGTSTP, tstop);
175 	signal(SIGSTOP, tstop);
176 #endif /* SIGTSTP */
177 }
178 
179 static const char *signame[NSIG] = { "",
180 "SIGHUP",  /*   1	hangup */
181 "SIGINT",  /*   2	interrupt */
182 "SIGQUIT", /*   3	quit */
183 "SIGILL",  /*   4	illegal instruction (not reset when caught) */
184 "SIGTRAP", /*   5	trace trap (not reset when caught) */
185 "SIGIOT",  /*   6	IOT instruction */
186 "SIGEMT",  /*   7	EMT instruction */
187 "SIGFPE",  /*   8	floating point exception */
188 "SIGKILL", /*   9	kill (cannot be caught or ignored) */
189 "SIGBUS",  /*  10	bus error */
190 "SIGSEGV", /*  11	segmentation violation */
191 "SIGSYS",  /*  12	bad argument to system call */
192 "SIGPIPE", /*  13	write on a pipe with no one to read it */
193 "SIGALRM", /*  14	alarm clock */
194 "SIGTERM", /*  15	software termination signal from kill */
195 "SIGURG",  /*  16	urgent condition on IO channel */
196 "SIGSTOP", /*  17	sendable stop signal not from tty */
197 "SIGTSTP", /*  18	stop signal from tty */
198 "SIGCONT", /*  19	continue a stopped process */
199 "SIGCHLD", /*  20	to parent on child stop or exit */
200 "SIGTTIN", /*  21	to readers pgrp upon background tty read */
201 "SIGTTOU", /*  22	like TTIN for output if (tp->t_local&LTOSTOP) */
202 "SIGIO",   /*  23	input/output possible signal */
203 "SIGXCPU", /*  24	exceeded CPU time limit */
204 "SIGXFSZ", /*  25	exceeded file size limit */
205 "SIGVTALRM",/* 26	virtual time alarm */
206 "SIGPROF", /*  27	profiling time alarm */
207 "SIGWINCH",/*  28	window size changes */
208 "SIGINFO", /*  29	information request */
209 "SIGUSR1", /*  30	user defined signal 1 */
210 "SIGUSR2", /*  31	user defined signal 2 */
211 };
212 
213 /*
214  *	routine to process a fatal error signal
215  */
216 static void
sigpanic(int sig)217 sigpanic(int sig)
218 {
219 	char buf[128];
220 	signal(sig, SIG_DFL);
221 	sprintf(buf, "\nLarn - Panic! Signal %d received [%s]", sig, signame[sig]);
222 	write(2, buf, strlen(buf));
223 	sleep(2);
224 	sncbr();
225 	savegame(savefilename);
226 	kill(getpid(), sig);	/* this will terminate us */
227 }
228