File: | session.c |
Location: | line 499, column 10 |
Description: | Branch condition evaluates to a garbage value |
1 | /****************************************************************************** | |||
2 | ||||
3 | Copyright 1994, 1998 The Open Group | |||
4 | ||||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
6 | documentation for any purpose is hereby granted without fee, provided that | |||
7 | the above copyright notice appear in all copies and that both that | |||
8 | copyright notice and this permission notice appear in supporting | |||
9 | documentation. | |||
10 | ||||
11 | The above copyright notice and this permission notice shall be included in | |||
12 | all copies or substantial portions of the Software. | |||
13 | ||||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
20 | ||||
21 | Except as contained in this notice, the name of The Open Group shall not be | |||
22 | used in advertising or otherwise to promote the sale, use or other dealings | |||
23 | in this Software without prior written authorization from The Open Group. | |||
24 | ||||
25 | Author: Ralph Mor, X Consortium | |||
26 | ******************************************************************************/ | |||
27 | ||||
28 | #ifdef HAVE_CONFIG_H1 | |||
29 | # include "config.h" | |||
30 | #endif | |||
31 | ||||
32 | #include <X11/Xos.h> | |||
33 | ||||
34 | #ifndef X_NOT_POSIX | |||
35 | #ifdef _POSIX_SOURCE | |||
36 | #include <limits.h> | |||
37 | #else | |||
38 | #define _POSIX_SOURCE | |||
39 | #include <limits.h> | |||
40 | #undef _POSIX_SOURCE | |||
41 | #endif | |||
42 | #endif /* X_NOT_POSIX */ | |||
43 | #ifndef PATH_MAX1024 | |||
44 | #include <sys/param.h> | |||
45 | #ifndef PATH_MAX1024 | |||
46 | #ifdef MAXPATHLEN | |||
47 | #define PATH_MAX1024 MAXPATHLEN | |||
48 | #else | |||
49 | #define PATH_MAX1024 1024 | |||
50 | #endif | |||
51 | #endif | |||
52 | #endif /* PATH_MAX */ | |||
53 | #ifdef HAVE_MKSTEMP1 | |||
54 | #include <unistd.h> | |||
55 | #endif | |||
56 | ||||
57 | #include <X11/Xlib.h> | |||
58 | #include <X11/SM/SMlib.h> | |||
59 | #include <X11/Xatom.h> | |||
60 | #include <stdio.h> | |||
61 | #include "twm.h" | |||
62 | #include "screen.h" | |||
63 | #include "session.h" | |||
64 | ||||
65 | SmcConn smcConn = NULL((void*)0); | |||
66 | static XtInputId iceInputId; | |||
67 | static char *twm_clientId; | |||
68 | static TWMWinConfigEntry *winConfigHead = NULL((void*)0); | |||
69 | static Boolint sent_save_done = 0; | |||
70 | ||||
71 | #define SAVEFILE_VERSION2 2 | |||
72 | ||||
73 | #ifndef HAVE_MKSTEMP1 | |||
74 | static char *unique_filename ( const char *path, const char *prefix ); | |||
75 | #else | |||
76 | static char *unique_filename ( const char *path, const char *prefix, int *pFd ); | |||
77 | #endif | |||
78 | ||||
79 | ||||
80 | static char * | |||
81 | GetClientID (Window window) | |||
82 | { | |||
83 | char *client_id = NULL((void*)0); | |||
84 | Window client_leader; | |||
85 | XTextProperty tp; | |||
86 | Atom actual_type; | |||
87 | int actual_format; | |||
88 | unsigned long nitems; | |||
89 | unsigned long bytes_after; | |||
90 | unsigned char *prop = NULL((void*)0); | |||
91 | ||||
92 | if (XGetWindowProperty (dpy, window, _XA_WM_CLIENT_LEADERTwmAtoms[9], | |||
93 | 0L, 1L, False0, AnyPropertyType0L, &actual_type, &actual_format, | |||
94 | &nitems, &bytes_after, &prop) == Success0) | |||
95 | { | |||
96 | if (actual_type == XA_WINDOW((Atom) 33) && actual_format == 32 && | |||
97 | nitems == 1 && bytes_after == 0) | |||
98 | { | |||
99 | client_leader = *((Window *) prop); | |||
100 | ||||
101 | if (XGetTextProperty (dpy, client_leader, &tp, _XA_SM_CLIENT_IDTwmAtoms[8])) | |||
102 | { | |||
103 | if (tp.encoding == XA_STRING((Atom) 31) && | |||
104 | tp.format == 8 && tp.nitems != 0) | |||
105 | client_id = (char *) tp.value; | |||
106 | } | |||
107 | } | |||
108 | ||||
109 | if (prop) | |||
110 | XFree (prop); | |||
111 | } | |||
112 | ||||
113 | return client_id; | |||
114 | } | |||
115 | ||||
116 | ||||
117 | ||||
118 | static char * | |||
119 | GetWindowRole (Window window) | |||
120 | { | |||
121 | XTextProperty tp; | |||
122 | ||||
123 | if (XGetTextProperty (dpy, window, &tp, _XA_WM_WINDOW_ROLETwmAtoms[10])) | |||
124 | { | |||
125 | if (tp.encoding == XA_STRING((Atom) 31) && tp.format == 8 && tp.nitems != 0) | |||
126 | return ((char *) tp.value); | |||
127 | } | |||
128 | ||||
129 | return NULL((void*)0); | |||
130 | } | |||
131 | ||||
132 | ||||
133 | ||||
134 | static int | |||
135 | write_byte (FILE *file, unsigned char b) | |||
136 | { | |||
137 | if (fwrite ((char *) &b, 1, 1, file) != 1) | |||
138 | return 0; | |||
139 | return 1; | |||
140 | } | |||
141 | ||||
142 | ||||
143 | static int | |||
144 | write_ushort (FILE *file, unsigned short s) | |||
145 | { | |||
146 | unsigned char file_short[2]; | |||
147 | ||||
148 | file_short[0] = (s & (unsigned)0xff00) >> 8; | |||
149 | file_short[1] = s & 0xff; | |||
150 | if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) | |||
151 | return 0; | |||
152 | return 1; | |||
153 | } | |||
154 | ||||
155 | ||||
156 | static int | |||
157 | write_short (FILE *file, short s) | |||
158 | { | |||
159 | unsigned char file_short[2]; | |||
160 | ||||
161 | file_short[0] = (s & (unsigned)0xff00) >> 8; | |||
162 | file_short[1] = s & 0xff; | |||
163 | if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) | |||
164 | return 0; | |||
165 | return 1; | |||
166 | } | |||
167 | ||||
168 | ||||
169 | static int | |||
170 | write_counted_string (FILE *file, char *string) | |||
171 | { | |||
172 | if (string) | |||
173 | { | |||
174 | unsigned char count = strlen (string); | |||
175 | ||||
176 | if (write_byte (file, count) == 0) | |||
177 | return 0; | |||
178 | if (fwrite (string, (int) sizeof (char), (int) count, file) != count) | |||
179 | return 0; | |||
180 | } | |||
181 | else | |||
182 | { | |||
183 | if (write_byte (file, 0) == 0) | |||
184 | return 0; | |||
185 | } | |||
186 | ||||
187 | return 1; | |||
188 | } | |||
189 | ||||
190 | ||||
191 | ||||
192 | static int | |||
193 | read_byte (FILE *file, unsigned char *bp) | |||
194 | { | |||
195 | if (fread ((char *) bp, 1, 1, file) != 1) | |||
196 | return 0; | |||
197 | return 1; | |||
198 | } | |||
199 | ||||
200 | ||||
201 | static int | |||
202 | read_ushort (FILE *file, unsigned short *shortp) | |||
203 | { | |||
204 | unsigned char file_short[2]; | |||
205 | ||||
206 | if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) | |||
207 | return 0; | |||
208 | *shortp = file_short[0] * 256 + file_short[1]; | |||
209 | return 1; | |||
210 | } | |||
211 | ||||
212 | ||||
213 | static int | |||
214 | read_short (FILE *file, short *shortp) | |||
215 | { | |||
216 | unsigned char file_short[2]; | |||
217 | ||||
218 | if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) | |||
219 | return 0; | |||
220 | *shortp = file_short[0] * 256 + file_short[1]; | |||
221 | return 1; | |||
222 | } | |||
223 | ||||
224 | ||||
225 | static int | |||
226 | read_counted_string (FILE *file, char **stringp) | |||
227 | { | |||
228 | unsigned char len; | |||
229 | char *data; | |||
230 | ||||
231 | if (read_byte (file, &len) == 0) | |||
232 | return 0; | |||
233 | if (len == 0) { | |||
234 | data = 0; | |||
235 | } else { | |||
236 | data = malloc ((unsigned) len + 1); | |||
237 | if (!data) | |||
238 | return 0; | |||
239 | if (fread (data, (int) sizeof (char), (int) len, file) != len) { | |||
240 | free (data); | |||
241 | return 0; | |||
242 | } | |||
243 | data[len] = '\0'; | |||
244 | } | |||
245 | *stringp = data; | |||
246 | return 1; | |||
247 | } | |||
248 | ||||
249 | ||||
250 | ||||
251 | /* | |||
252 | * An entry in the saved window config file looks like this: | |||
253 | * | |||
254 | * FIELD BYTES | |||
255 | * ----- ---- | |||
256 | * SM_CLIENT_ID ID len 1 (may be 0) | |||
257 | * SM_CLIENT_ID LIST of bytes (may be NULL) | |||
258 | * | |||
259 | * WM_WINDOW_ROLE length 1 (may be 0) | |||
260 | * WM_WINDOW_ROLE LIST of bytes (may be NULL) | |||
261 | * | |||
262 | * if no WM_WINDOW_ROLE (length = 0) | |||
263 | * | |||
264 | * WM_CLASS "res name" length 1 | |||
265 | * WM_CLASS "res name" LIST of bytes | |||
266 | * WM_CLASS "res class" length 1 | |||
267 | * WM_CLASS "res class" LIST of bytes | |||
268 | * WM_NAME length 1 (0 if name changed) | |||
269 | * WM_NAME LIST of bytes | |||
270 | * WM_COMMAND arg count 1 (0 if no SM_CLIENT_ID) | |||
271 | * For each arg in WM_COMMAND | |||
272 | * arg length 1 | |||
273 | * arg LIST of bytes | |||
274 | * | |||
275 | * Iconified bool 1 | |||
276 | * Icon info present bool 1 | |||
277 | * | |||
278 | * if icon info present | |||
279 | * icon x 2 | |||
280 | * icon y 2 | |||
281 | * | |||
282 | * Geom x 2 | |||
283 | * Geom y 2 | |||
284 | * Geom width 2 | |||
285 | * Geom height 2 | |||
286 | * | |||
287 | * Width ever changed by user 1 | |||
288 | * Height ever changed by user 1 | |||
289 | */ | |||
290 | ||||
291 | static int | |||
292 | WriteWinConfigEntry (FILE *configFile, TwmWindow *theWindow, | |||
293 | char *clientId, char *windowRole) | |||
294 | { | |||
295 | char **wm_command; | |||
296 | int wm_command_count, i; | |||
297 | ||||
298 | if (!write_counted_string (configFile, clientId)) | |||
299 | return 0; | |||
300 | ||||
301 | if (!write_counted_string (configFile, windowRole)) | |||
302 | return 0; | |||
303 | ||||
304 | if (!windowRole) | |||
305 | { | |||
306 | if (!write_counted_string (configFile, theWindow->class.res_name)) | |||
307 | return 0; | |||
308 | if (!write_counted_string (configFile, theWindow->class.res_class)) | |||
309 | return 0; | |||
310 | if (theWindow->nameChanged) | |||
311 | { | |||
312 | /* | |||
313 | * If WM_NAME changed on this window, we can't use it as | |||
314 | * a criteria for looking up window configurations. See the | |||
315 | * longer explanation in the GetWindowConfig() function below. | |||
316 | */ | |||
317 | ||||
318 | if (!write_counted_string (configFile, NULL((void*)0))) | |||
319 | return 0; | |||
320 | } | |||
321 | else | |||
322 | { | |||
323 | if (!write_counted_string (configFile, theWindow->name)) | |||
324 | return 0; | |||
325 | } | |||
326 | ||||
327 | wm_command = NULL((void*)0); | |||
328 | wm_command_count = 0; | |||
329 | XGetCommand (dpy, theWindow->w, &wm_command, &wm_command_count); | |||
330 | ||||
331 | if (clientId || !wm_command || wm_command_count == 0) | |||
332 | { | |||
333 | if (!write_byte (configFile, 0)) | |||
334 | return 0; | |||
335 | } | |||
336 | else | |||
337 | { | |||
338 | if (!write_byte (configFile, (char) wm_command_count)) | |||
339 | return 0; | |||
340 | for (i = 0; i < wm_command_count; i++) | |||
341 | if (!write_counted_string (configFile, wm_command[i])) | |||
342 | return 0; | |||
343 | XFreeStringList (wm_command); | |||
344 | } | |||
345 | } | |||
346 | ||||
347 | if (!write_byte (configFile, theWindow->icon ? 1 : 0)) /* iconified */ | |||
348 | return 0; | |||
349 | ||||
350 | if (!write_byte (configFile, theWindow->icon_w ? 1 : 0)) /* icon exists */ | |||
351 | return 0; | |||
352 | ||||
353 | if (theWindow->icon_w) | |||
354 | { | |||
355 | int icon_x, icon_y; | |||
356 | ||||
357 | XGetGeometry (dpy, theWindow->icon_w, &JunkRoot, &icon_x, | |||
358 | &icon_y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth); | |||
359 | ||||
360 | if (!write_short (configFile, (short) icon_x)) | |||
361 | return 0; | |||
362 | if (!write_short (configFile, (short) icon_y)) | |||
363 | return 0; | |||
364 | } | |||
365 | ||||
366 | if (!write_short (configFile, (short) theWindow->frame_x)) | |||
367 | return 0; | |||
368 | if (!write_short (configFile, (short) theWindow->frame_y)) | |||
369 | return 0; | |||
370 | if (!write_ushort (configFile, (unsigned short) theWindow->attr.width)) | |||
371 | return 0; | |||
372 | if (!write_ushort (configFile, (unsigned short) theWindow->attr.height)) | |||
373 | return 0; | |||
374 | ||||
375 | if (!write_byte (configFile, theWindow->widthEverChangedByUser ? 1 : 0)) | |||
376 | return 0; | |||
377 | ||||
378 | if (!write_byte (configFile, theWindow->heightEverChangedByUser ? 1 : 0)) | |||
379 | return 0; | |||
380 | ||||
381 | return 1; | |||
382 | } | |||
383 | ||||
384 | ||||
385 | static int | |||
386 | ReadWinConfigEntry (FILE *configFile, unsigned short version, | |||
387 | TWMWinConfigEntry **pentry) | |||
388 | { | |||
389 | TWMWinConfigEntry *entry; | |||
390 | unsigned char byte; | |||
391 | int i; | |||
392 | ||||
393 | *pentry = entry = malloc (sizeof (TWMWinConfigEntry)); | |||
394 | if (!*pentry) | |||
| ||||
395 | return 0; | |||
396 | ||||
397 | entry->tag = 0; | |||
398 | entry->client_id = NULL((void*)0); | |||
399 | entry->window_role = NULL((void*)0); | |||
400 | entry->class.res_name = NULL((void*)0); | |||
401 | entry->class.res_class = NULL((void*)0); | |||
402 | entry->wm_name = NULL((void*)0); | |||
403 | entry->wm_command = NULL((void*)0); | |||
404 | entry->wm_command_count = 0; | |||
405 | ||||
406 | if (!read_counted_string (configFile, &entry->client_id)) | |||
407 | goto give_up; | |||
408 | ||||
409 | if (!read_counted_string (configFile, &entry->window_role)) | |||
410 | goto give_up; | |||
411 | ||||
412 | if (!entry->window_role) | |||
413 | { | |||
414 | if (!read_counted_string (configFile, &entry->class.res_name)) | |||
415 | goto give_up; | |||
416 | if (!read_counted_string (configFile, &entry->class.res_class)) | |||
417 | goto give_up; | |||
418 | if (!read_counted_string (configFile, &entry->wm_name)) | |||
419 | goto give_up; | |||
420 | ||||
421 | if (!read_byte (configFile, &byte)) | |||
422 | goto give_up; | |||
423 | entry->wm_command_count = byte; | |||
424 | ||||
425 | if (entry->wm_command_count == 0) | |||
426 | entry->wm_command = NULL((void*)0); | |||
427 | else | |||
428 | { | |||
429 | entry->wm_command = malloc (entry->wm_command_count * | |||
430 | sizeof (char *)); | |||
431 | ||||
432 | if (!entry->wm_command) | |||
433 | goto give_up; | |||
434 | ||||
435 | for (i = 0; i < entry->wm_command_count; i++) | |||
436 | if (!read_counted_string (configFile, &entry->wm_command[i])) | |||
437 | goto give_up; | |||
438 | } | |||
439 | } | |||
440 | ||||
441 | if (!read_byte (configFile, &byte)) | |||
442 | goto give_up; | |||
443 | entry->iconified = byte; | |||
444 | ||||
445 | if (!read_byte (configFile, &byte)) | |||
446 | goto give_up; | |||
447 | entry->icon_info_present = byte; | |||
448 | ||||
449 | if (entry->icon_info_present) | |||
450 | { | |||
451 | if (!read_short (configFile, (short *) &entry->icon_x)) | |||
452 | goto give_up; | |||
453 | if (!read_short (configFile, (short *) &entry->icon_y)) | |||
454 | goto give_up; | |||
455 | } | |||
456 | ||||
457 | if (!read_short (configFile, (short *) &entry->x)) | |||
458 | goto give_up; | |||
459 | if (!read_short (configFile, (short *) &entry->y)) | |||
460 | goto give_up; | |||
461 | if (!read_ushort (configFile, &entry->width)) | |||
462 | goto give_up; | |||
463 | if (!read_ushort (configFile, &entry->height)) | |||
464 | goto give_up; | |||
465 | ||||
466 | if (version > 1) | |||
467 | { | |||
468 | if (!read_byte (configFile, &byte)) | |||
469 | goto give_up; | |||
470 | entry->width_ever_changed_by_user = byte; | |||
471 | ||||
472 | if (!read_byte (configFile, &byte)) | |||
473 | goto give_up; | |||
474 | entry->height_ever_changed_by_user = byte; | |||
475 | } | |||
476 | else | |||
477 | { | |||
478 | entry->width_ever_changed_by_user = False0; | |||
479 | entry->height_ever_changed_by_user = False0; | |||
480 | } | |||
481 | ||||
482 | return 1; | |||
483 | ||||
484 | give_up: | |||
485 | ||||
486 | if (entry->client_id) | |||
487 | free (entry->client_id); | |||
488 | if (entry->window_role) | |||
489 | free (entry->window_role); | |||
490 | if (entry->class.res_name) | |||
491 | free (entry->class.res_name); | |||
492 | if (entry->class.res_class) | |||
493 | free (entry->class.res_class); | |||
494 | if (entry->wm_name) | |||
495 | free (entry->wm_name); | |||
496 | if (entry->wm_command_count && entry->wm_command) | |||
497 | { | |||
498 | for (i = 0; i < entry->wm_command_count; i++) | |||
499 | if (entry->wm_command[i]) | |||
| ||||
500 | free (entry->wm_command[i]); | |||
501 | } | |||
502 | if (entry->wm_command) | |||
503 | free (entry->wm_command); | |||
504 | ||||
505 | free (entry); | |||
506 | *pentry = NULL((void*)0); | |||
507 | ||||
508 | return 0; | |||
509 | } | |||
510 | ||||
511 | ||||
512 | void | |||
513 | ReadWinConfigFile (char *filename) | |||
514 | { | |||
515 | FILE *configFile; | |||
516 | TWMWinConfigEntry *entry; | |||
517 | int done = 0; | |||
518 | unsigned short version = 0; | |||
519 | ||||
520 | configFile = fopen (filename, "rb"); | |||
521 | if (!configFile) | |||
522 | return; | |||
523 | ||||
524 | if (!read_ushort (configFile, &version) || | |||
525 | version > SAVEFILE_VERSION2) | |||
526 | { | |||
527 | done = 1; | |||
528 | } | |||
529 | ||||
530 | while (!done) | |||
531 | { | |||
532 | if (ReadWinConfigEntry (configFile, version, &entry)) | |||
533 | { | |||
534 | entry->next = winConfigHead; | |||
535 | winConfigHead = entry; | |||
536 | } | |||
537 | else | |||
538 | done = 1; | |||
539 | } | |||
540 | ||||
541 | fclose (configFile); | |||
542 | } | |||
543 | ||||
544 | ||||
545 | ||||
546 | int | |||
547 | GetWindowConfig ( | |||
548 | TwmWindow *theWindow, | |||
549 | short *x, short *y, | |||
550 | unsigned short *width, unsigned short *height, | |||
551 | Boolint *iconified, | |||
552 | Boolint *icon_info_present, | |||
553 | short *icon_x, short *icon_y, | |||
554 | Boolint *width_ever_changed_by_user, | |||
555 | Boolint *height_ever_changed_by_user) | |||
556 | { | |||
557 | char *clientId, *windowRole; | |||
558 | TWMWinConfigEntry *ptr; | |||
559 | int found = 0; | |||
560 | ||||
561 | ptr = winConfigHead; | |||
562 | ||||
563 | if (!ptr) | |||
564 | return 0; | |||
565 | ||||
566 | clientId = GetClientID (theWindow->w); | |||
567 | windowRole = GetWindowRole (theWindow->w); | |||
568 | ||||
569 | while (ptr && !found) | |||
570 | { | |||
571 | int client_id_match = (!clientId && !ptr->client_id) || | |||
572 | (clientId && ptr->client_id && | |||
573 | strcmp (clientId, ptr->client_id) == 0); | |||
574 | ||||
575 | if (!ptr->tag && client_id_match) | |||
576 | { | |||
577 | if (windowRole || ptr->window_role) | |||
578 | { | |||
579 | found = (windowRole && ptr->window_role && | |||
580 | strcmp (windowRole, ptr->window_role) == 0); | |||
581 | } | |||
582 | else | |||
583 | { | |||
584 | /* | |||
585 | * Compare WM_CLASS + only compare WM_NAME if the | |||
586 | * WM_NAME in the saved file is non-NULL. If the | |||
587 | * WM_NAME in the saved file is NULL, this means that | |||
588 | * the client changed the value of WM_NAME during the | |||
589 | * session, and we can not use it as a criteria for | |||
590 | * our search. For example, with xmh, at save time | |||
591 | * the window name might be "xmh: folderY". However, | |||
592 | * if xmh does not properly restore state when it is | |||
593 | * restarted, the initial window name might be | |||
594 | * "xmh: folderX". This would cause the window manager | |||
595 | * to fail in finding the saved window configuration. | |||
596 | * The best we can do is ignore WM_NAME if its value | |||
597 | * changed in the previous session. | |||
598 | */ | |||
599 | ||||
600 | if (strcmp (theWindow->class.res_name, | |||
601 | ptr->class.res_name) == 0 && | |||
602 | strcmp (theWindow->class.res_class, | |||
603 | ptr->class.res_class) == 0 && | |||
604 | (ptr->wm_name == NULL((void*)0) || | |||
605 | strcmp (theWindow->name, ptr->wm_name) == 0)) | |||
606 | { | |||
607 | if (clientId) | |||
608 | { | |||
609 | /* | |||
610 | * If a client ID was present, we should not check | |||
611 | * WM_COMMAND because Xt will put a -xtsessionID arg | |||
612 | * on the command line. | |||
613 | */ | |||
614 | ||||
615 | found = 1; | |||
616 | } | |||
617 | else | |||
618 | { | |||
619 | /* | |||
620 | * For non-XSMP clients, also check WM_COMMAND. | |||
621 | */ | |||
622 | ||||
623 | char **wm_command = NULL((void*)0); | |||
624 | int wm_command_count = 0, i; | |||
625 | ||||
626 | XGetCommand (dpy, theWindow->w, | |||
627 | &wm_command, &wm_command_count); | |||
628 | ||||
629 | if (wm_command_count == ptr->wm_command_count) | |||
630 | { | |||
631 | for (i = 0; i < wm_command_count; i++) | |||
632 | if (strcmp (wm_command[i], | |||
633 | ptr->wm_command[i]) != 0) | |||
634 | break; | |||
635 | ||||
636 | if (i == wm_command_count) | |||
637 | found = 1; | |||
638 | } | |||
639 | } | |||
640 | } | |||
641 | } | |||
642 | } | |||
643 | ||||
644 | if (!found) | |||
645 | ptr = ptr->next; | |||
646 | } | |||
647 | ||||
648 | if (found) | |||
649 | { | |||
650 | *x = ptr->x; | |||
651 | *y = ptr->y; | |||
652 | *width = ptr->width; | |||
653 | *height = ptr->height; | |||
654 | *iconified = ptr->iconified; | |||
655 | *icon_info_present = ptr->icon_info_present; | |||
656 | *width_ever_changed_by_user = ptr->width_ever_changed_by_user; | |||
657 | *height_ever_changed_by_user = ptr->height_ever_changed_by_user; | |||
658 | ||||
659 | if (*icon_info_present) | |||
660 | { | |||
661 | *icon_x = ptr->icon_x; | |||
662 | *icon_y = ptr->icon_y; | |||
663 | } | |||
664 | ptr->tag = 1; | |||
665 | } | |||
666 | else | |||
667 | *iconified = 0; | |||
668 | ||||
669 | if (clientId) | |||
670 | XFree (clientId); | |||
671 | ||||
672 | if (windowRole) | |||
673 | XFree (windowRole); | |||
674 | ||||
675 | return found; | |||
676 | } | |||
677 | ||||
678 | ||||
679 | ||||
680 | #ifndef HAVE_MKSTEMP1 | |||
681 | static char * | |||
682 | unique_filename ( | |||
683 | const char *path, | |||
684 | const char *prefix) | |||
685 | #else | |||
686 | static char * | |||
687 | unique_filename ( | |||
688 | const char *path, | |||
689 | const char *prefix, | |||
690 | int *pFd) | |||
691 | #endif | |||
692 | ||||
693 | { | |||
694 | #ifndef HAVE_MKSTEMP1 | |||
695 | #ifndef X_NOT_POSIX | |||
696 | return ((char *) tempnam (path, prefix)); | |||
697 | #else | |||
698 | char tempFile[PATH_MAX1024]; | |||
699 | char *tmp; | |||
700 | ||||
701 | snprintf (tempFile, sizeof(tempFile), "%s/%sXXXXXX", path, prefix)__builtin___snprintf_chk (tempFile, sizeof(tempFile), 0, __builtin_object_size (tempFile, 2 > 1 ? 1 : 0), "%s/%sXXXXXX", path, prefix); | |||
702 | tmp = (char *) mktemp (tempFile); | |||
703 | if (tmp) | |||
704 | return strdup (tmp); | |||
705 | else | |||
706 | return (NULL((void*)0)); | |||
707 | #endif | |||
708 | #else | |||
709 | char tempFile[PATH_MAX1024]; | |||
710 | char *ptr; | |||
711 | ||||
712 | snprintf (tempFile, sizeof(tempFile), "%s/%sXXXXXX", path, prefix)__builtin___snprintf_chk (tempFile, sizeof(tempFile), 0, __builtin_object_size (tempFile, 2 > 1 ? 1 : 0), "%s/%sXXXXXX", path, prefix); | |||
713 | ptr = strdup (tempFile); | |||
714 | if (ptr != NULL((void*)0)) | |||
715 | *pFd = mkstemp (ptr); | |||
716 | return ptr; | |||
717 | #endif | |||
718 | } | |||
719 | ||||
720 | ||||
721 | ||||
722 | static void | |||
723 | SaveYourselfPhase2CB (SmcConn smcConn, SmPointer clientData) | |||
724 | { | |||
725 | int scrnum; | |||
726 | ScreenInfo *theScreen; | |||
727 | TwmWindow *theWindow; | |||
728 | char *clientId, *windowRole; | |||
729 | FILE *configFile = NULL((void*)0); | |||
730 | const char *path; | |||
731 | char *filename = NULL((void*)0); | |||
732 | Boolint success = False0; | |||
733 | SmProp prop1, prop2, prop3, *props[3]; | |||
734 | SmPropValue prop1val, prop2val, prop3val; | |||
735 | char discardCommand[80]; | |||
736 | int numVals, i; | |||
737 | static int first_time = 1; | |||
738 | #ifdef HAVE_MKSTEMP1 | |||
739 | int fd; | |||
740 | #endif | |||
741 | ||||
742 | if (first_time) | |||
743 | { | |||
744 | char userId[20]; | |||
745 | char hint = SmRestartIfRunning0; | |||
746 | ||||
747 | prop1.name = SmProgram"Program"; | |||
748 | prop1.type = SmARRAY8"ARRAY8"; | |||
749 | prop1.num_vals = 1; | |||
750 | prop1.vals = &prop1val; | |||
751 | prop1val.value = Argv[0]; | |||
752 | prop1val.length = strlen (Argv[0]); | |||
753 | ||||
754 | snprintf (userId, sizeof(userId), "%ld", (long)getuid())__builtin___snprintf_chk (userId, sizeof(userId), 0, __builtin_object_size (userId, 2 > 1 ? 1 : 0), "%ld", (long)getuid()); | |||
755 | prop2.name = SmUserID"UserID"; | |||
756 | prop2.type = SmARRAY8"ARRAY8"; | |||
757 | prop2.num_vals = 1; | |||
758 | prop2.vals = &prop2val; | |||
759 | prop2val.value = (SmPointer) userId; | |||
760 | prop2val.length = strlen (userId); | |||
761 | ||||
762 | prop3.name = SmRestartStyleHint"RestartStyleHint"; | |||
763 | prop3.type = SmCARD8"CARD8"; | |||
764 | prop3.num_vals = 1; | |||
765 | prop3.vals = &prop3val; | |||
766 | prop3val.value = (SmPointer) &hint; | |||
767 | prop3val.length = 1; | |||
768 | ||||
769 | props[0] = &prop1; | |||
770 | props[1] = &prop2; | |||
771 | props[2] = &prop3; | |||
772 | ||||
773 | SmcSetProperties (smcConn, 3, props); | |||
774 | ||||
775 | first_time = 0; | |||
776 | } | |||
777 | ||||
778 | path = getenv ("SM_SAVE_DIR"); | |||
779 | if (!path) | |||
780 | { | |||
781 | path = getenv ("HOME"); | |||
782 | if (!path) | |||
783 | path = "."; | |||
784 | } | |||
785 | #ifndef HAVE_MKSTEMP1 | |||
786 | if ((filename = unique_filename (path, ".twm")) == NULL((void*)0)) | |||
787 | goto bad; | |||
788 | ||||
789 | if (!(configFile = fopen (filename, "wb"))) | |||
790 | goto bad; | |||
791 | #else | |||
792 | if ((filename = unique_filename (path, ".twm", &fd)) == NULL((void*)0)) | |||
793 | goto bad; | |||
794 | ||||
795 | if (!(configFile = fdopen(fd, "wb"))) | |||
796 | goto bad; | |||
797 | #endif | |||
798 | ||||
799 | if (!write_ushort (configFile, SAVEFILE_VERSION2)) | |||
800 | goto bad; | |||
801 | ||||
802 | success = True1; | |||
803 | ||||
804 | for (scrnum = 0; scrnum < NumScreens && success; scrnum++) | |||
805 | { | |||
806 | if (ScreenList[scrnum] != NULL((void*)0)) | |||
807 | { | |||
808 | theScreen = ScreenList[scrnum]; | |||
809 | theWindow = theScreen->TwmRoot.next; | |||
810 | ||||
811 | while (theWindow && success) | |||
812 | { | |||
813 | clientId = GetClientID (theWindow->w); | |||
814 | windowRole = GetWindowRole (theWindow->w); | |||
815 | ||||
816 | if (!WriteWinConfigEntry (configFile, theWindow, | |||
817 | clientId, windowRole)) | |||
818 | success = False0; | |||
819 | ||||
820 | if (clientId) | |||
821 | XFree (clientId); | |||
822 | ||||
823 | if (windowRole) | |||
824 | XFree (windowRole); | |||
825 | ||||
826 | theWindow = theWindow->next; | |||
827 | } | |||
828 | } | |||
829 | } | |||
830 | ||||
831 | prop1.name = SmRestartCommand"RestartCommand"; | |||
832 | prop1.type = SmLISTofARRAY8"LISTofARRAY8"; | |||
833 | ||||
834 | prop1.vals = malloc ((Argc + 4) * sizeof (SmPropValue)); | |||
835 | ||||
836 | if (!prop1.vals) | |||
837 | { | |||
838 | success = False0; | |||
839 | goto bad; | |||
840 | } | |||
841 | ||||
842 | numVals = 0; | |||
843 | ||||
844 | for (i = 0; i < Argc; i++) | |||
845 | { | |||
846 | if (strcmp (Argv[i], "-clientId") == 0 || | |||
847 | strcmp (Argv[i], "-restore") == 0) | |||
848 | { | |||
849 | i++; | |||
850 | } | |||
851 | else | |||
852 | { | |||
853 | prop1.vals[numVals].value = (SmPointer) Argv[i]; | |||
854 | prop1.vals[numVals++].length = strlen (Argv[i]); | |||
855 | } | |||
856 | } | |||
857 | ||||
858 | prop1.vals[numVals].value = (SmPointer) "-clientId"; | |||
859 | prop1.vals[numVals++].length = 9; | |||
860 | ||||
861 | prop1.vals[numVals].value = (SmPointer) twm_clientId; | |||
862 | prop1.vals[numVals++].length = strlen (twm_clientId); | |||
863 | ||||
864 | prop1.vals[numVals].value = (SmPointer) "-restore"; | |||
865 | prop1.vals[numVals++].length = 8; | |||
866 | ||||
867 | prop1.vals[numVals].value = (SmPointer) filename; | |||
868 | prop1.vals[numVals++].length = strlen (filename); | |||
869 | ||||
870 | prop1.num_vals = numVals; | |||
871 | ||||
872 | snprintf (discardCommand, sizeof(discardCommand), "rm %s", filename)__builtin___snprintf_chk (discardCommand, sizeof(discardCommand ), 0, __builtin_object_size (discardCommand, 2 > 1 ? 1 : 0 ), "rm %s", filename); | |||
873 | prop2.name = SmDiscardCommand"DiscardCommand"; | |||
874 | prop2.type = SmARRAY8"ARRAY8"; | |||
875 | prop2.num_vals = 1; | |||
876 | prop2.vals = &prop2val; | |||
877 | prop2val.value = (SmPointer) discardCommand; | |||
878 | prop2val.length = strlen (discardCommand); | |||
879 | ||||
880 | props[0] = &prop1; | |||
881 | props[1] = &prop2; | |||
882 | ||||
883 | SmcSetProperties (smcConn, 2, props); | |||
884 | free (prop1.vals); | |||
885 | ||||
886 | bad: | |||
887 | SmcSaveYourselfDone (smcConn, success); | |||
888 | sent_save_done = 1; | |||
889 | ||||
890 | if (configFile) | |||
891 | fclose (configFile); | |||
892 | ||||
893 | if (filename) | |||
894 | free (filename); | |||
895 | } | |||
896 | ||||
897 | ||||
898 | ||||
899 | static void | |||
900 | SaveYourselfCB ( | |||
901 | SmcConn smcConn, | |||
902 | SmPointer clientData, | |||
903 | int saveType, | |||
904 | Boolint shutdown, | |||
905 | int interactStyle, | |||
906 | Boolint fast) | |||
907 | { | |||
908 | if (!SmcRequestSaveYourselfPhase2 (smcConn, SaveYourselfPhase2CB, NULL((void*)0))) | |||
909 | { | |||
910 | SmcSaveYourselfDone (smcConn, False0); | |||
911 | sent_save_done = 1; | |||
912 | } | |||
913 | else | |||
914 | sent_save_done = 0; | |||
915 | } | |||
916 | ||||
917 | ||||
918 | ||||
919 | static void | |||
920 | DieCB (SmcConn smcConn, SmPointer clientData) | |||
921 | { | |||
922 | SmcCloseConnection (smcConn, 0, NULL((void*)0)); | |||
923 | XtRemoveInput (iceInputId); | |||
924 | Done(NULL((void*)0), NULL((void*)0)); | |||
925 | } | |||
926 | ||||
927 | ||||
928 | ||||
929 | static void | |||
930 | SaveCompleteCB (SmcConn smcConnm, SmPointer clientData) | |||
931 | { | |||
932 | ; | |||
933 | } | |||
934 | ||||
935 | ||||
936 | ||||
937 | static void | |||
938 | ShutdownCancelledCB (SmcConn smcConn, SmPointer clientData) | |||
939 | { | |||
940 | if (!sent_save_done) | |||
941 | { | |||
942 | SmcSaveYourselfDone (smcConn, False0); | |||
943 | sent_save_done = 1; | |||
944 | } | |||
945 | } | |||
946 | ||||
947 | ||||
948 | ||||
949 | static void | |||
950 | ProcessIceMsgProc (XtPointer client_data, int *source, XtInputId *id) | |||
951 | { | |||
952 | IceConn ice_conn = (IceConn) client_data; | |||
953 | ||||
954 | IceProcessMessages (ice_conn, NULL((void*)0), NULL((void*)0)); | |||
955 | } | |||
956 | ||||
957 | ||||
958 | ||||
959 | void | |||
960 | ConnectToSessionManager (char *previous_id) | |||
961 | { | |||
962 | char errorMsg[256]; | |||
963 | unsigned long mask; | |||
964 | SmcCallbacks callbacks; | |||
965 | IceConn iceConn; | |||
966 | ||||
967 | mask = SmcSaveYourselfProcMask(1L << 0) | SmcDieProcMask(1L << 1) | | |||
968 | SmcSaveCompleteProcMask(1L << 2) | SmcShutdownCancelledProcMask(1L << 3); | |||
969 | ||||
970 | callbacks.save_yourself.callback = SaveYourselfCB; | |||
971 | callbacks.save_yourself.client_data = (SmPointer) NULL((void*)0); | |||
972 | ||||
973 | callbacks.die.callback = DieCB; | |||
974 | callbacks.die.client_data = (SmPointer) NULL((void*)0); | |||
975 | ||||
976 | callbacks.save_complete.callback = SaveCompleteCB; | |||
977 | callbacks.save_complete.client_data = (SmPointer) NULL((void*)0); | |||
978 | ||||
979 | callbacks.shutdown_cancelled.callback = ShutdownCancelledCB; | |||
980 | callbacks.shutdown_cancelled.client_data = (SmPointer) NULL((void*)0); | |||
981 | ||||
982 | smcConn = SmcOpenConnection ( | |||
983 | NULL((void*)0), /* use SESSION_MANAGER env */ | |||
984 | (SmPointer) appContext, | |||
985 | SmProtoMajor1, | |||
986 | SmProtoMinor0, | |||
987 | mask, | |||
988 | &callbacks, | |||
989 | previous_id, | |||
990 | &twm_clientId, | |||
991 | 256, errorMsg); | |||
992 | ||||
993 | if (smcConn == NULL((void*)0)) | |||
994 | return; | |||
995 | ||||
996 | iceConn = SmcGetIceConnection (smcConn); | |||
997 | ||||
998 | iceInputId = XtAppAddInput ( | |||
999 | appContext, | |||
1000 | IceConnectionNumber (iceConn), | |||
1001 | (XtPointer) XtInputReadMask(1L<<0), | |||
1002 | ProcessIceMsgProc, | |||
1003 | (XtPointer) iceConn); | |||
1004 | } | |||
1005 | ||||
1006 | ||||
1007 |