1 /*
2 * Copyright (c) 1993-1997 by Alexander V. Lukyanov (lav@yars.free.net)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <config.h>
20 #include <signal.h>
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <setjmp.h>
28 #include "edit.h"
29
30 #ifndef __MSDOS__
31 #include <termios.h>
32 #ifdef HAVE_SYS_IOCTL_H
33 #include <sys/ioctl.h>
34 #endif
35 #endif
36
37 /* This pair of functions is to work
38 with signal handlers - install and release */
39 static struct sigaction OldSIGHUP;
40 static struct sigaction OldSIGINT;
41 static struct sigaction OldSIGQUIT;
42 static struct sigaction OldSIGTSTP;
43
44 #ifdef __GNUC__
45 #define SA_HANDLER_TYPE typeof(OldSIGHUP.sa_handler)
46 #else
47 #define SA_HANDLER_TYPE void(*)(int)
48 #endif
49 #ifndef SA_RESTART
50 #define SA_RESTART 0
51 #endif
52
53
BlockSignals()54 void BlockSignals()
55 {
56 sigset_t ss;
57
58 sigemptyset(&ss);
59 sigaddset(&ss,SIGALRM);
60
61 sigprocmask(SIG_BLOCK,&ss,NULL);
62 }
UnblockSignals()63 void UnblockSignals()
64 {
65 sigset_t ss;
66
67 sigemptyset(&ss);
68 sigaddset(&ss,SIGALRM);
69
70 sigprocmask(SIG_UNBLOCK,&ss,NULL);
71 }
72
73 #ifndef KEY_RESIZE
74 int resize_flag=0;
75
CheckWindowResize()76 void CheckWindowResize()
77 {
78 #if !defined(__MSDOS__) && defined(TIOCGWINSZ)
79 struct winsize winsz;
80 static bool disable_resize=false;
81
82 resize_flag=0;
83
84 if(disable_resize)
85 return;
86
87 winsz.ws_col=COLS;
88 winsz.ws_row=LINES;
89 ioctl(0,TIOCGWINSZ,&winsz);
90 if(winsz.ws_col && winsz.ws_row
91 && (winsz.ws_col!=COLS || winsz.ws_row!=LINES)
92 && !(getenv("LINES") && getenv("COLUMNS")))
93 {
94 WIN *w=CreateWin(0,0,COLS,LINES,NORMAL_TEXT_ATTR,"",NOSHADOW);
95 DisplayWin(w);
96 InitCurses(); // this does endwin() automatically
97 if(winsz.ws_col!=COLS || winsz.ws_row!=LINES)
98 {
99 beep();
100 disable_resize=true;
101 }
102 clearok(stdscr,TRUE);
103 CorrectParameters();
104 flag|=REDISPLAY_ALL;
105 CloseWin();
106 DestroyWin(w);
107 }
108 #endif
109 }
110
resize_sig(int sig)111 void resize_sig(int sig)
112 {
113 (void)sig;
114 resize_flag=1;
115
116 extern bool getch_return_set;
117 extern sigjmp_buf getch_return;
118
119 if(getch_return_set)
120 siglongjmp(getch_return,1);
121 }
122 #endif // KEY_RESIZE
123
SuspendEditor()124 void SuspendEditor()
125 {
126 #ifndef __MSDOS__
127 /* clear();*/
128 curs_set(1);
129 refresh();
130 endwin();
131 kill(getpid(),SIGSTOP);
132 refresh();
133 #else
134 ErrMsg("Suspending is not supported under MSDOG");
135 #endif
136 }
137
138 static char mem[4000];
TmpFileName()139 char *TmpFileName()
140 {
141 #ifndef __MSDOS__
142 sprintf(mem,"%s/.le/tmp/",HOME);
143 char *add=mem+strlen(mem);
144 strcpy(add,FileName);
145 while(*add)
146 {
147 if(isslash(*add))
148 *add='_';
149 add++;
150 }
151 sprintf(add,".%d",(int)getpid());
152 #else
153 sprintf(mem,"le%d.res",(int)getpid());
154 #endif
155 return mem;
156 }
HupFileName(int sig)157 char *HupFileName(int sig)
158 {
159 #ifndef __MSDOS__
160 sprintf(mem,"%s/.le/tmp/DUMP-%d-",HOME,sig);
161 char *add=mem+strlen(mem);
162 strcpy(add,FileName);
163 while(*add)
164 {
165 if(isslash(*add))
166 *add='_';
167 add++;
168 }
169 sprintf(add,".%d",(int)getpid());
170 #else
171 sprintf(mem,"le%d.hup",(int)getpid());
172 #endif
173 return mem;
174 }
175
hup(int sig)176 void hup(int sig)
177 {
178 endwin();
179
180 if(modified)
181 {
182 char *s=HupFileName(sig);
183 fprintf(stderr,"le: Caught signal %d, dumping text to %s\n",sig,s);
184 int fd=creat(s,0600);
185 num act_written;
186 WriteBlock(fd,0,Size(),&act_written);
187 close(fd);
188 }
189 else
190 {
191 fprintf(stderr,"le: Caught signal %d\n",sig);
192 }
193 if(sig==SIGSEGV || sig==SIGBUS)
194 {
195 ReleaseSignalHandlers();
196 sigset_t mask;
197 sigemptyset(&mask);
198 sigaddset(&mask,sig);
199 sigprocmask(SIG_UNBLOCK,&mask,0);
200 kill(getpid(),sig);
201 }
202 exit(1);
203 }
204
alarmsave(int a)205 void alarmsave(int a)
206 {
207 // set handler again to be safe
208 struct sigaction alarmsaveaction;
209 alarmsaveaction.sa_handler=(SA_HANDLER_TYPE)alarmsave;
210 alarmsaveaction.sa_flags=SA_RESTART;
211 sigemptyset(&alarmsaveaction.sa_mask);
212 sigaction(SIGALRM,&alarmsaveaction,NULL);
213
214 static offs dump_pos=0;
215 static int fd=-1;
216 static int interrupted=0;
217 const int chunk=0x20000;
218
219 (void)a;
220
221 // check if the text changed
222 if(modified==1)
223 {
224 // it did - reset dump state
225 dump_pos=0;
226 if(fd!=-1)
227 {
228 interrupted++;
229 close(fd);
230 }
231 char *s=TmpFileName();
232 fd=open(s,O_CREAT|O_WRONLY|O_TRUNC,0600);
233 if(fd==-1)
234 {
235 alarm(ALARMDELAY);
236 return;
237 }
238 modified=3;
239 }
240 // if the dump is in progress
241 if(modified==3)
242 {
243 num act_written;
244 if(WriteBlock(fd,dump_pos,(interrupted>5?Size()-dump_pos:chunk),
245 &act_written)!=OK)
246 {
247 done:
248 close(fd);
249 fd=-1;
250 // mark it as dumped
251 modified=2;
252 }
253 else
254 {
255 dump_pos+=act_written;
256 if(dump_pos>=Size())
257 {
258 interrupted=0;
259 goto done;
260 }
261 // after a second write next chunk
262 alarm(1);
263 return;
264 }
265 }
266 alarm(ALARMDELAY);
267 }
268
InstallSignalHandlers()269 void InstallSignalHandlers()
270 {
271 struct sigaction hupaction;
272 struct sigaction alarmsaveaction;
273 struct sigaction ign_action;
274 struct sigaction suspend_action;
275
276 hupaction.sa_handler=(SA_HANDLER_TYPE)hup;
277 hupaction.sa_flags=0;
278 sigfillset(&hupaction.sa_mask);
279
280 alarmsaveaction.sa_handler=(SA_HANDLER_TYPE)alarmsave;
281 alarmsaveaction.sa_flags=SA_RESTART;
282 sigemptyset(&alarmsaveaction.sa_mask);
283
284 ign_action.sa_handler=(SA_HANDLER_TYPE)SIG_IGN;
285 ign_action.sa_flags=0;
286 sigemptyset(&ign_action.sa_mask);
287
288 suspend_action.sa_handler=(SA_HANDLER_TYPE)SuspendEditor;
289 suspend_action.sa_flags=0;
290 sigemptyset(&suspend_action.sa_mask);
291
292 #ifndef KEY_RESIZE
293 struct sigaction resize_action;
294 resize_action.sa_handler=(SA_HANDLER_TYPE)resize_sig;
295 resize_action.sa_flags=0;
296 sigemptyset(&resize_action.sa_mask);
297 #endif
298
299 BlockSignals();
300
301 /* catch signals to dump editing file and exit */
302 sigaction(SIGHUP,&hupaction,&OldSIGHUP);
303
304 #ifndef DEBUG
305 sigaction(SIGILL,&hupaction,NULL);
306 #ifdef SIGTRAP
307 sigaction(SIGTRAP,&hupaction,NULL);
308 #endif
309 sigaction(SIGABRT,&hupaction,NULL);
310 #ifdef SIGEMT
311 sigaction(SIGEMT,&hupaction,NULL);
312 #endif
313 sigaction(SIGFPE,&hupaction,NULL);
314 #if SIGBUS
315 sigaction(SIGBUS,&hupaction,NULL);
316 #endif
317 sigaction(SIGSEGV,&hupaction,NULL);
318 #ifdef SIGSYS
319 sigaction(SIGSYS,&hupaction,NULL);
320 #endif
321 #endif /* DEBUG */
322
323 sigaction(SIGTERM,&hupaction,NULL);
324 #ifdef SIGPWR
325 sigaction(SIGPWR,&hupaction,NULL);
326 #endif
327
328 sigaction(SIGALRM,&alarmsaveaction,NULL);
329
330 sigaction(SIGINT,&ign_action,&OldSIGINT);
331 sigaction(SIGQUIT,&ign_action,&OldSIGQUIT);
332 #ifdef SIGTSTP
333 sigaction(SIGTSTP,&suspend_action,&OldSIGTSTP);
334 #endif
335 #ifdef SIGVTALRM
336 sigaction(SIGVTALRM,&ign_action,NULL);
337 #endif
338 #ifdef SIGPIPE
339 sigaction(SIGPIPE,&ign_action,NULL);
340 #endif
341 sigaction(SIGUSR1,&ign_action,NULL);
342 sigaction(SIGUSR2,&ign_action,NULL);
343
344 #if defined(SIGWINCH) && !defined(KEY_RESIZE)
345 sigaction(SIGWINCH,&resize_action,NULL);
346 #endif
347 #ifdef SIGCHLD
348 // sigaction(SIGCHLD,&ign_action,NULL);
349 #endif
350 #ifdef SIGTTIN
351 sigaction(SIGTTIN,&suspend_action,NULL);
352 #endif
353 #ifdef SIGTTOU
354 sigaction(SIGTTOU,&suspend_action,NULL);
355 #endif
356 }
ReleaseSignalHandlers()357 void ReleaseSignalHandlers()
358 {
359 struct sigaction dfl_action;
360
361 dfl_action.sa_handler=(SA_HANDLER_TYPE)SIG_DFL;
362 dfl_action.sa_flags=0;
363
364 alarm(0); /* turn off alarm */
365
366 sigaction(SIGHUP,&OldSIGHUP,NULL);
367 sigaction(SIGILL,&dfl_action,NULL);
368 #ifdef SIGTRAP
369 sigaction(SIGTRAP,&dfl_action,NULL);
370 #endif
371 sigaction(SIGABRT,&dfl_action,NULL);
372 #ifdef SIGEMT
373 sigaction(SIGEMT,&dfl_action,NULL);
374 #endif
375 sigaction(SIGFPE,&dfl_action,NULL);
376 #ifdef SIGBUS
377 sigaction(SIGBUS,&dfl_action,NULL);
378 #endif
379 sigaction(SIGSEGV,&dfl_action,NULL);
380 #ifdef SIGSYS
381 sigaction(SIGSYS,&dfl_action,NULL);
382 #endif
383 sigaction(SIGTERM,&dfl_action,NULL);
384 #ifdef SIGPWR
385 sigaction(SIGPWR,&dfl_action,NULL);
386 #endif
387
388 sigaction(SIGALRM,&dfl_action,NULL);
389
390 sigaction(SIGINT,&OldSIGINT,NULL);
391 sigaction(SIGQUIT,&OldSIGQUIT,NULL);
392 #ifdef SIGTSTP
393 sigaction(SIGTSTP,&OldSIGTSTP,NULL);
394 #endif
395 #ifdef SIGVTALRM
396 sigaction(SIGVTALRM,&dfl_action,NULL);
397 #endif
398 #ifdef SIGPIPE
399 sigaction(SIGPIPE,&dfl_action,NULL);
400 #endif
401 sigaction(SIGUSR1,&dfl_action,NULL);
402 sigaction(SIGUSR2,&dfl_action,NULL);
403
404 UnblockSignals();
405 }
406