1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, see: <http://www.gnu.org/licenses/>
14 */
15
16 #include "config.h"
17
18 #include <unistd.h>
19 #include <signal.h>
20 #include <errno.h>
21 #include "FvwmIconMan.h"
22 #include "readconfig.h"
23 #include "x.h"
24 #include "xmanager.h"
25
26 #include "libs/fvwmsignal.h"
27 #include "libs/Module.h"
28 #include "libs/FTips.h"
29 #include "libs/FEvent.h"
30 #include "libs/Parse.h"
31
32
33 char *MyName;
34 FlocaleWinString *FwinString;
35 int mods_unused = DEFAULT_MODS_UNUSED;
36
37 static RETSIGTYPE TerminateHandler(int);
38
copy_string(char ** target,const char * src)39 char *copy_string(char **target, const char *src)
40 {
41 int len;
42 if (src == NULL)
43 {
44 len = 0;
45 if (*target)
46 {
47 Free(*target);
48 }
49 return *target = NULL;
50 }
51
52 len = strlen(src);
53 ConsoleDebug(CORE, "copy_string: 1: 0x%lx\n", (unsigned long)*target);
54
55 if (*target)
56 {
57 Free(*target);
58 }
59
60 ConsoleDebug(CORE, "copy_string: 2\n");
61 *target = fxmalloc((len + 1) * sizeof(char));
62 strcpy(*target, src);
63 ConsoleDebug(CORE, "copy_string: 3\n");
64 return *target;
65 }
66
67 #ifdef TRACE_MEMUSE
68
69 long MemUsed = 0;
70
Free(void * p)71 void Free(void *p)
72 {
73 struct malloc_header *head = (struct malloc_header *)p;
74
75 if (p != NULL)
76 {
77 head--;
78 if (head->magic != MALLOC_MAGIC)
79 {
80 fvwm_debug(__func__,
81 "Corrupted memory found in Free\n");
82 abort();
83 return;
84 }
85 if (head->len > MemUsed)
86 {
87 fvwm_debug(__func__, "Free block too big\n");
88 return;
89 }
90 MemUsed -= head->len;
91 Free(head);
92 }
93 }
94
PrintMemuse(void)95 void PrintMemuse(void)
96 {
97 ConsoleDebug(CORE, "Memory used: %ld\n", MemUsed);
98 }
99
100 #else
101
Free(void * p)102 void Free(void *p)
103 {
104 if (p != NULL)
105 {
106 free(p);
107 }
108 }
109
PrintMemuse(void)110 void PrintMemuse(void)
111 {
112 }
113
114 #endif
115
116
117 static RETSIGTYPE
TerminateHandler(int sig)118 TerminateHandler(int sig)
119 {
120 fvwmSetTerminate(sig);
121 SIGNAL_RETURN;
122 }
123
124
125 void
ShutMeDown(int flag)126 ShutMeDown(int flag)
127 {
128 ConsoleDebug(CORE, "Bye Bye\n");
129 exit(flag);
130 }
131
132 void
DeadPipe(int nothing)133 DeadPipe(int nothing)
134 {
135 (void)nothing;
136 ShutMeDown(0);
137 SIGNAL_RETURN;
138 }
139
140 static void
main_loop(void)141 main_loop(void)
142 {
143 fd_set readset, saveset;
144 fd_set_size_t fd_width = x_fd;
145 unsigned long ms;
146 struct timeval tv;
147
148 /*
149 * Calculate which is descriptor is numerically higher:
150 * this determines how wide the descriptor set needs to be ...
151 */
152 if (fd_width < fvwm_fd[1])
153 {
154 fd_width = fvwm_fd[1];
155 }
156 ++fd_width;
157
158 FD_ZERO(&saveset);
159 FD_SET(fvwm_fd[1], &saveset);
160 FD_SET(x_fd, &saveset);
161
162 tv.tv_sec = 60;
163 tv.tv_usec = 0;
164
165 while (!isTerminated)
166 {
167 /* Check the pipes for anything to read, and block if
168 * there is nothing there yet ...
169 */
170 readset = saveset;
171
172 if (fvwmSelect(fd_width, &readset, NULL, NULL, &tv) < 0)
173 {
174 ConsoleMessage(
175 "Internal error with select: errno=%s\n",
176 strerror(errno));
177 }
178 else
179 {
180
181 if (FD_ISSET(x_fd, &readset) || FPending(theDisplay))
182 {
183 xevent_loop();
184 }
185 if (FD_ISSET(fvwm_fd[1], &readset))
186 {
187 ReadFvwmPipe();
188 }
189
190 }
191 if ((ms = FTipsCheck(theDisplay)))
192 {
193 tv.tv_sec = ms / 1000;
194 tv.tv_usec = (ms % 1000) * 1000;
195 }
196 else
197 {
198 tv.tv_sec = 60;
199 tv.tv_usec = 0;
200 }
201 } /* while */
202 }
203
204 int
main(int argc,char ** argv)205 main(int argc, char **argv)
206 {
207 int i;
208
209 #ifdef HAVE_LIBEFENCE
210 extern int EF_PROTECT_BELOW, EF_PROTECT_FREE;
211
212 EF_PROTECT_BELOW = 1;
213 EF_PROTECT_FREE = 1;
214 #endif
215
216 FlocaleInit(LC_CTYPE, "", "", "FvwmIconMan");
217
218 OpenConsole(OUTPUT_FILE);
219
220 init_globals();
221 init_winlists();
222
223 MyName = GetFileNameFromPath(argv[0]);
224
225 if (argc >= 7)
226 {
227 if (strcasecmp(argv[6], "-Transient") == 0)
228 {
229 globals.transient = 1;
230
231 /* Optionally accept an alias to use as the transient
232 * FvwmIconMan instance.
233 */
234 if (argv[7])
235 MyName = argv[7];
236 }
237 else
238 {
239 MyName = argv[6];
240 }
241 }
242 ModuleLen = strlen(MyName) + 1;
243 Module = fxmalloc(ModuleLen+1);
244 *Module = '*';
245 strcpy(Module+1, MyName);
246
247 if (argc < 6)
248 {
249 fvwm_debug(__func__,
250 "%s version %s should only be executed by fvwm!\n",
251 MyName, VERSION);
252 ShutMeDown(1);
253 }
254 fvwm_fd[0] = atoi(argv[1]);
255 fvwm_fd[1] = atoi(argv[2]);
256 init_display();
257
258 #ifdef HAVE_SIGACTION
259 {
260 struct sigaction sigact;
261
262 sigemptyset(&sigact.sa_mask);
263 sigaddset(&sigact.sa_mask, SIGPIPE);
264 sigaddset(&sigact.sa_mask, SIGINT);
265 sigaddset(&sigact.sa_mask, SIGHUP);
266 sigaddset(&sigact.sa_mask, SIGTERM);
267 sigaddset(&sigact.sa_mask, SIGQUIT);
268 # ifdef SA_RESTART
269 sigact.sa_flags = SA_RESTART;
270 # else
271 sigact.sa_flags = 0;
272 # endif
273 sigact.sa_handler = TerminateHandler;
274
275 sigaction(SIGPIPE, &sigact, NULL);
276 sigaction(SIGINT, &sigact, NULL);
277 sigaction(SIGHUP, &sigact, NULL);
278 sigaction(SIGTERM, &sigact, NULL);
279 sigaction(SIGQUIT, &sigact, NULL);
280 }
281 #else
282 /* We don't have sigaction(), so fall back to less robust methods. */
283 #ifdef USE_BSD_SIGNALS
284 fvwmSetSignalMask(
285 sigmask(SIGPIPE) |
286 sigmask(SIGINT) |
287 sigmask(SIGHUP) |
288 sigmask(SIGTERM) |
289 sigmask(SIGQUIT));
290 #endif
291 signal(SIGPIPE, TerminateHandler);
292 signal(SIGINT, TerminateHandler);
293 signal(SIGHUP, TerminateHandler);
294 signal(SIGTERM, TerminateHandler);
295 signal(SIGQUIT, TerminateHandler);
296 #ifdef HAVE_SIGINTERRUPT
297 siginterrupt(SIGPIPE, 0);
298 siginterrupt(SIGINT, 0);
299 siginterrupt(SIGHUP, 0);
300 siginterrupt(SIGTERM, 0);
301 siginterrupt(SIGQUIT, 0);
302 #endif
303 #endif
304
305 read_in_resources();
306 FlocaleAllocateWinString(&FwinString);
307
308 for (i = 0; i < globals.num_managers; i++)
309 {
310 X_init_manager(i);
311 }
312
313 assert(globals.managers);
314
315 SetMessageMask(
316 fvwm_fd, M_CONFIGURE_WINDOW | M_RES_CLASS | M_RES_NAME |
317 M_ADD_WINDOW | M_DESTROY_WINDOW | M_ICON_NAME |
318 M_DEICONIFY | M_ICONIFY | M_ICON_LOCATION | M_END_WINDOWLIST |
319 M_NEW_DESK | M_NEW_PAGE | M_FOCUS_CHANGE | M_WINDOW_NAME |
320 M_CONFIG_INFO | M_SENDCONFIG | M_VISIBLE_NAME |
321 M_MINI_ICON | M_STRING | M_WINDOWSHADE | M_DEWINDOWSHADE);
322 /* extended messages */
323 SetMessageMask(fvwm_fd, MX_VISIBLE_ICON_NAME | MX_PROPERTY_CHANGE);
324
325 SendText(fvwm_fd, "Send_WindowList", 0);
326
327 /* tell fvwm we're running */
328 SendFinishedStartupNotification(fvwm_fd);
329
330 /* Lock on send only for iconify and deiconify (for NoIconAction) */
331 SetSyncMask(fvwm_fd, M_DEICONIFY | M_ICONIFY);
332 SetNoGrabMask(fvwm_fd, M_DEICONIFY | M_ICONIFY);
333
334 main_loop();
335
336 return 0;
337 }
338