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