1 /*
2 **
3 ** gv_signal.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyright (C) 2004 Jose E. Marchesi
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 3 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with GNU gv; see the file COPYING.  If not, write to
20 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ** Boston, MA 02111-1307, USA.
22 **
23 ** Author:   Johannes Plass (plass@thep.physik.uni-mainz.de)
24 **           Department of Physics
25 **           Johannes Gutenberg-University
26 **           Mainz, Germany
27 **
28 **           Jose E. Marchesi (jemarch@gnu.org)
29 **           GNU Project
30 **
31 */
32 #include "ac_config.h"
33 
34 /*
35 #define MESSAGES
36 */
37 #include <ac_config.h>
38 
39 #include "message.h"
40 
41 #include <stdio.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 #include <unistd.h>
45 #include <stdlib.h>
46 
47 #include "paths.h"
48 #include INC_X11(Intrinsic.h)
49 
50 
51 #ifdef USE_SIGNAL_HANDLER
52 #   if (XtSpecificationRelease >= 6)
53 #      define USE_XT_SIGNAL_HANDLER
54 #   else
55 #      define USE_DUMMY_SIGNAL_HANDLER
56 #   endif
57 #else
58 #   define USE_DUMMY_SIGNAL_HANDLER
59 #endif
60 
61 #include "types.h"
62 #include "callbacks.h"
63 #include "main_resources.h"
64 #include "main_globals.h"
65 #include "gv_signal.h"
66 #include "actions.h"
67 
68 #ifdef SIGNALRETURNSINT
69 #   define SIGVAL int
70 #   define SIGNAL_RETURN return(0);
71 #else
72 #   define SIGVAL void
73 #   define SIGNAL_RETURN
74 #endif
75 
76 
77 #ifdef USE_XT_SIGNAL_HANDLER
78 
79 
80 static XtSignalId sid_updateFile = 0;
81 static XtSignalId sid_terminate  = 0;
82 static int block_terminate       = 0;
83 static int block_updateFile      = 0;
84 static pid_t gv_pid = (pid_t) 0;
85 
86 /*------------------------------------------------------------*/
87 /* signal_signalIsOk */
88 /*------------------------------------------------------------*/
89 
signal_signalIsOk(void)90 static int signal_signalIsOk(void)
91 {
92   BEGINMESSAGE(signal_signalIsOk)
93 # ifdef MESSAGES
94     IIMESSAGE(gv_pid,getpid())
95     if (gv_pid == getpid()) { INFMESSAGE(signal is ok) }
96     else                    { INFMESSAGE(bogus signal) }
97 # endif
98   ENDMESSAGE(signal_signalIsOk)
99   return(gv_pid == getpid() ? 1 : 0);
100 }
101 
102 /*------------------------------------------------------------*/
103 /* signal_scb_terminate */
104 /*------------------------------------------------------------*/
105 
signal_scb_terminate(XtPointer client_data _GL_UNUSED,XtSignalId * sidP _GL_UNUSED)106 static void signal_scb_terminate(XtPointer client_data _GL_UNUSED, XtSignalId *sidP _GL_UNUSED)
107 {
108   BEGINMESSAGE(signal_scb_terminate)
109   cb_doQuit(NULL,NULL,NULL);
110   ENDMESSAGE(signal_scb_terminate)
111 }
112 
113 /*------------------------------------------------------------*/
114 /* signal_sh_terminate */
115 /*------------------------------------------------------------*/
116 
signal_sh_terminate(int sig)117 static SIGVAL signal_sh_terminate(int sig)
118 {
119   BEGINMESSAGE(signal_fatalSignalHandler)
120   if (signal_signalIsOk()) {
121     if (!block_terminate) {
122       fprintf(stderr, "gv: terminated by signal %d\n", sig);
123       XtNoticeSignal(sid_terminate);
124       block_terminate = 1;
125     }
126     signal(sig,signal_sh_terminate);
127   } else {
128     INFMESSAGE(forcing bogus caller to die)
129     clean_safe_tempdir();
130     exit(EXIT_STATUS_ERROR);
131   }
132   ENDMESSAGE(signal_sh_terminate)
133   SIGNAL_RETURN
134 }
135 
136 /*------------------------------------------------------------*/
137 /* signal_scb_updateFile */
138 /*------------------------------------------------------------*/
139 
signal_scb_updateFile(XtPointer client_data _GL_UNUSED,XtSignalId * sidP _GL_UNUSED)140 static void signal_scb_updateFile(XtPointer client_data _GL_UNUSED, XtSignalId *sidP _GL_UNUSED)
141 {
142   BEGINMESSAGE(signal_scb_updateFile)
143   if (gv_filename) {
144     String s;
145     struct stat sbuf;
146     s = XtNewString(gv_filename);
147     if (!stat(s, &sbuf) && mtime != sbuf.st_mtime)
148        cb_checkFile(NULL,(XtPointer)CHECK_FILE_VERSION,NULL);
149     XtFree(s);
150   }
151   block_updateFile = 0;
152   ENDMESSAGE(signal_scb_updateFile)
153 }
154 
155 /*------------------------------------------------------------*/
156 /* signal_sh_updateFile */
157 /*------------------------------------------------------------*/
158 
signal_sh_updateFile(int sig)159 static SIGVAL signal_sh_updateFile(int sig)
160 {
161   BEGINMESSAGE(signal_sh_updateFile)
162   if (signal_signalIsOk()) {
163     if (!block_updateFile) {
164       block_updateFile=1;
165       XtNoticeSignal(sid_updateFile);
166     }
167     signal(sig,signal_sh_updateFile);
168   } else {
169     INFMESSAGE(forcing bogus caller to die)
170     clean_safe_tempdir();
171     exit(EXIT_STATUS_ERROR);
172   }
173   ENDMESSAGE(signal_sh_updateFile)
174   SIGNAL_RETURN
175 }
176 
177 /*############################################################*/
178 /* signal_setSignalHandlers */
179 /*############################################################*/
180 
signal_setSignalHandlers(int on)181 void signal_setSignalHandlers(int on)
182 {
183   SIGVAL (*sht)(int),(*shu)(int);
184 
185   BEGINMESSAGE(signal_setSignalHandlers)
186 
187   if (!gv_pid) gv_pid = getpid();
188 
189   if (on) {
190     shu = signal_sh_updateFile;
191     sht = signal_sh_terminate;
192     sid_updateFile = XtAppAddSignal(app_con,signal_scb_updateFile,NULL);
193     sid_terminate  = XtAppAddSignal(app_con,signal_scb_terminate,NULL);
194   } else {
195     shu = sht = SIG_DFL;
196     if (sid_updateFile) XtRemoveSignal(sid_updateFile);
197     if (sid_terminate)  XtRemoveSignal(sid_terminate);
198     sid_updateFile = sid_terminate = 0;
199   }
200   signal(SIGHUP,  shu);
201   signal(SIGQUIT, sht);
202   signal(SIGTERM, sht);
203 #if 0
204   signal(SIGINT,  sht);
205   signal(SIGILL,  sht);
206   signal(SIGBUS,  sht);
207   signal(SIGFPE,  sht);
208   signal(SIGSEGV, sht);
209   signal(SIGSYS,  sht);
210 #endif
211   ENDMESSAGE(signal_setSignalHandlers)
212 }
213 
214 #endif /* USE_XT_SIGNAL_HANDLER */
215 
216 
217 #ifdef USE_DUMMY_SIGNAL_HANDLER
218 
219 int signaldummy;
220 
221 #endif /* USE_DUMMY_SIGNAL_HANDLER */
222