| 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 |