Add removing window decorations to FAQ.
[fvwm.git] / libs / fsm.c
blob232e0a16fa1f4c22f80f3d16301a44b8a4d0223d
1 /* -*-c-*- */
2 /* Copyright (C) 2003 Olivier Chapuis
3 * some code taken from the xsm: Copyright 1993, 1998 The Open Group */
5 /* This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 /* A set of functions for implementing a dummy sm. The code is based on xsm */
22 /* ---------------------------- included header files ---------------------- */
24 #include "config.h"
25 #include <stdio.h>
26 #include <fcntl.h>
27 #ifdef HAVE_GETPWUID
28 #include <pwd.h>
29 #endif
30 #include <sys/types.h>
31 #include <sys/stat.h>
33 #include <X11/Xlib.h>
34 #include <X11/Xutil.h>
35 #include <X11/Xproto.h>
36 #include <X11/Xatom.h>
38 #include "fvwmlib.h"
39 #include "System.h"
40 #include "flist.h"
41 #include "fsm.h"
43 /* #define FVWM_DEBUG_FSM */
45 /* ---------------------------- local definitions -------------------------- */
47 /* ---------------------------- local macros ------------------------------- */
49 /* ---------------------------- imports ------------------------------------ */
51 /* ---------------------------- included code files ------------------------ */
53 /* ---------------------------- local types -------------------------------- */
55 typedef struct
57 FIceConn ice_conn;
58 int fd;
59 } fsm_ice_conn_t;
61 /* ---------------------------- forward declarations ----------------------- */
63 /* ---------------------------- local variables ---------------------------- */
65 static FIceAuthDataEntry *authDataEntries = NULL;
66 static FIceIOErrorHandler prev_handler;
67 static FIceListenObj *listenObjs;
69 static char *addAuthFile = NULL;
70 static char *remAuthFile = NULL;
72 static flist *fsm_ice_conn_list = NULL;
73 static flist *pending_ice_conn_list = NULL;
74 static int numTransports = 0;
75 static char *networkIds = NULL;
76 static int *ice_fd = NULL;
78 static char *module_name = NULL;
79 static flist *running_list = NULL;
80 static Bool fsm_init_succeed = False;
82 static Atom _XA_WM_CLIENT_LEADER = None;
83 static Atom _XA_SM_CLIENT_ID = None;
85 /* ---------------------------- exported variables (globals) --------------- */
87 /* ---------------------------- local functions ---------------------------- */
90 * client list stuff
93 static
94 void free_fsm_client(fsm_client_t *client)
96 if (!SessionSupport)
98 return;
101 if (client->clientId)
103 free(client->clientId);
105 free(client);
109 * auth stuff
111 static void
112 fprintfhex(register FILE *fp, unsigned int len, char *cp)
114 static const char hexchars[] = "0123456789abcdef";
116 for (; len > 0; len--, cp++) {
117 unsigned char s = *cp;
118 putc(hexchars[s >> 4], fp);
119 putc(hexchars[s & 0x0f], fp);
124 * Host Based Authentication Callback. This callback is invoked if
125 * the connecting client can't offer any authentication methods that
126 * we can accept. We can accept/reject based on the hostname.
129 static
130 Bool HostBasedAuthProc(char *hostname)
132 return (0); /* For now, we don't support host based authentication */
136 * We use temporary files which contain commands to add/remove entries from
137 * the .ICEauthority file.
140 static void
141 write_iceauth(FILE *addfp, FILE *removefp, FIceAuthDataEntry *entry)
143 if (!SessionSupport)
145 return;
148 fprintf(addfp,
149 "add %s \"\" %s %s ", entry->protocol_name, entry->network_id,
150 entry->auth_name);
151 fprintfhex(addfp, entry->auth_data_length, entry->auth_data);
152 fprintf(addfp, "\n");
154 fprintf(
155 removefp,
156 "remove protoname=%s protodata=\"\" netid=%s authname=%s\n",
157 entry->protocol_name, entry->network_id, entry->auth_name);
161 static char *
162 unique_filename(char *path, char *prefix, int *pFd)
164 char *tempFile;
166 tempFile = (char *)safemalloc(strlen(path) + strlen(prefix) + 8);
167 sprintf(tempFile, "%s/%sXXXXXX", path, prefix);
168 *pFd = fvwm_mkstemp(tempFile);
169 if (*pFd == -1)
171 free(tempFile);
172 tempFile = NULL;
174 return tempFile;
178 * Provide authentication data to clients that wish to connect
181 #define MAGIC_COOKIE_LEN 16
183 static
184 Status SetAuthentication(
185 int count,FIceListenObj *listenObjs,FIceAuthDataEntry **authDataEntries)
187 FILE *addfp = NULL;
188 FILE *removefp = NULL;
189 char *path;
190 int original_umask;
191 char command[256];
192 int i;
193 int fd;
195 if (!SessionSupport)
197 return 0;
200 original_umask = umask (0077); /* disallow non-owner access */
202 path = (char *)getenv("SM_SAVE_DIR");
203 if (!path)
205 path = getenv("HOME");
208 #ifdef HAVE_GETPWUID
209 if (!path)
211 struct passwd *pwd;
213 pwd = getpwuid(getuid());
214 if (pwd)
216 path = pwd->pw_dir;
219 #endif
220 if (!path)
222 path = ".";
224 if ((addAuthFile = unique_filename (path, ".fsm-", &fd)) == NULL)
226 goto bad;
228 if (!(addfp = fdopen(fd, "wb")))
230 goto bad;
232 if ((remAuthFile = unique_filename (path, ".fsm-", &fd)) == NULL)
234 goto bad;
236 if (!(removefp = fdopen(fd, "wb")))
238 goto bad;
241 *authDataEntries = (FIceAuthDataEntry *) safemalloc(
242 count * 2 * sizeof (FIceAuthDataEntry));
244 for (i = 0; i < count * 2; i += 2)
246 (*authDataEntries)[i].network_id =
247 FIceGetListenConnectionString(listenObjs[i/2]);
248 (*authDataEntries)[i].protocol_name = "ICE";
249 (*authDataEntries)[i].auth_name = "MIT-MAGIC-COOKIE-1";
251 (*authDataEntries)[i].auth_data =
252 FIceGenerateMagicCookie (MAGIC_COOKIE_LEN);
253 (*authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
255 (*authDataEntries)[i+1].network_id =
256 FIceGetListenConnectionString(listenObjs[i/2]);
257 (*authDataEntries)[i+1].protocol_name = "XSMP";
258 (*authDataEntries)[i+1].auth_name = "MIT-MAGIC-COOKIE-1";
260 (*authDataEntries)[i+1].auth_data =
261 FIceGenerateMagicCookie (MAGIC_COOKIE_LEN);
262 (*authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN;
264 write_iceauth(addfp, removefp, &(*authDataEntries)[i]);
265 write_iceauth(addfp, removefp, &(*authDataEntries)[i+1]);
267 FIceSetPaAuthData(2, &(*authDataEntries)[i]);
268 FIceSetHostBasedAuthProc(listenObjs[i/2], HostBasedAuthProc);
271 fclose(addfp);
272 fclose(removefp);
274 umask (original_umask);
276 sprintf (command, "iceauth source %s", addAuthFile);
277 system(command);
279 unlink (addAuthFile);
281 return 1;
283 bad:
285 if (addfp)
287 fclose (addfp);
290 if (removefp)
292 fclose (removefp);
295 if (addAuthFile)
297 unlink (addAuthFile);
298 free (addAuthFile);
300 if (remAuthFile)
302 unlink (remAuthFile);
303 free (remAuthFile);
306 return 0;
309 static
310 void FreeAuthenticationData(int count, FIceAuthDataEntry *authDataEntries)
312 /* Each transport has entries for ICE and XSMP */
314 char command[256];
315 int i;
317 if (!SessionSupport)
319 return;
322 for (i = 0; i < count * 2; i++)
324 free(authDataEntries[i].network_id);
325 free(authDataEntries[i].auth_data);
328 free ((char *) authDataEntries);
330 sprintf (command, "iceauth source %s", remAuthFile);
331 system(command);
333 unlink (remAuthFile);
335 free (addAuthFile);
336 free (remAuthFile);
340 * ice stuff
343 static
344 void MyIoErrorHandler(FIceConn ice_conn)
346 if (!SessionSupport)
348 return;
351 if (prev_handler)
353 (*prev_handler) (ice_conn);
357 static
358 void InstallIOErrorHandler(void)
360 FIceIOErrorHandler default_handler;
362 if (!SessionSupport)
364 return;
367 prev_handler = FIceSetIOErrorHandler(NULL);
368 default_handler = FIceSetIOErrorHandler(MyIoErrorHandler);
369 if (prev_handler == default_handler)
371 prev_handler = NULL;
375 static void
376 CloseListeners(void)
378 if (!SessionSupport)
380 return;
383 FIceFreeListenObjs(numTransports, listenObjs);
386 static
387 void ice_watch_fd(
388 FIceConn conn, FIcePointer client_data, Bool opening,
389 FIcePointer *watch_data)
391 fsm_ice_conn_t *fice_conn;
393 if (!SessionSupport)
395 return;
398 if (opening)
400 fice_conn = (fsm_ice_conn_t *)safemalloc(sizeof(fsm_ice_conn_t));
401 fice_conn->ice_conn = conn;
402 fice_conn->fd = FIceConnectionNumber(conn);
403 *watch_data = (FIcePointer) fice_conn;
404 fsm_ice_conn_list =
405 flist_append_obj(fsm_ice_conn_list, fice_conn);
406 fcntl(fice_conn->fd, F_SETFD, FD_CLOEXEC);
408 else
410 fice_conn = (fsm_ice_conn_t *)*watch_data;
411 fsm_ice_conn_list =
412 flist_remove_obj(fsm_ice_conn_list, fice_conn);
413 free(fice_conn);
418 * Session Manager callbacks
421 static
422 Status RegisterClientProc(
423 FSmsConn smsConn, FSmPointer managerData, char *previousId)
425 fsm_client_t *client = (fsm_client_t *) managerData;
426 char *id;
427 int send_save = 0;
429 if (!SessionSupport)
431 return 0;
433 #ifdef FVWM_DEBUG_FSM
434 fprintf (stderr,
435 "[%s][RegisterClientProc] On FIceConn fd = %d, received "
436 "REGISTER CLIENT [Previous Id = %s]\n", module_name,
437 FIceConnectionNumber (client->ice_conn),
438 previousId ? previousId : "NULL");
439 #endif
441 /* ignore previousID!! (we are dummy) */
442 id = FSmsGenerateClientID(smsConn);
443 if (!FSmsRegisterClientReply(smsConn, id))
445 /* cannot happen ? */
446 if (id)
448 free(id);
450 fprintf(
451 stderr,
452 "[%s][RegisterClientProc] ERR -- fail to register "
453 "client", module_name);
454 return 0;
457 #ifdef FVWM_DEBUG_FSM
458 fprintf (stderr,
459 "[%s][RegisterClientProc] On FIceConn fd = %d, sent "
460 "REGISTER CLIENT REPLY [Client Id = %s]\n",
461 module_name, FIceConnectionNumber (client->ice_conn), id);
462 #endif
464 client->clientId = id;
465 /* client->clientHostname = FSmsClientHostName (smsConn); */
467 /* we are dummy ... do not do that */
468 if (send_save)
470 FSmsSaveYourself(
471 smsConn, FSmSaveLocal, False, FSmInteractStyleNone,
472 False);
475 return 1;
478 static void
479 InteractRequestProc(FSmsConn smsConn, FSmPointer managerData, int dialogType)
481 if (!SessionSupport)
483 return;
485 /* no intercation! */
486 #if 0
487 FSmsInteract (client->smsConn);
488 #endif
492 static void
493 InteractDoneProc(FSmsConn smsConn, FSmPointer managerData, Bool cancelShutdown)
495 /* no intercation! */
498 static void
499 SaveYourselfReqProc(FSmsConn smsConn, FSmPointer managerData, int saveType,
500 Bool shutdown, int interactStyle, Bool fast, Bool global)
502 /* no session to save */
505 static
506 void SaveYourselfPhase2ReqProc(FSmsConn smsConn, FSmPointer managerData)
508 fsm_client_t *client;
510 if (!SessionSupport)
512 return;
514 client = (fsm_client_t *)managerData;
515 FSmsSaveYourselfPhase2(client->smsConn);
518 static void
519 SaveYourselfDoneProc(FSmsConn smsConn, FSmPointer managerData, Bool success)
521 fsm_client_t *client;
523 if (!SessionSupport)
525 return;
527 client = (fsm_client_t *) managerData;
528 FSmsSaveComplete(client->smsConn);
531 static void
532 CloseDownClient(fsm_client_t *client)
535 if (!SessionSupport)
537 return;
540 #ifdef FVWM_DEBUG_FSM
541 fprintf(
542 stderr, "[%s][CloseDownClient] ICE Connection closed, "
543 "FIceConn fd = %d\n", module_name,
544 FIceConnectionNumber (client->ice_conn));
545 #endif
547 FSmsCleanUp(client->smsConn);
548 FIceSetShutdownNegotiation(client->ice_conn, False);
549 if (!FIceCloseConnection(client->ice_conn) != FIceClosedNow)
551 /* do not care */
554 client->ice_conn = NULL;
555 client->smsConn = NULL;
557 running_list = flist_remove_obj(running_list, client);
558 free_fsm_client(client);
561 static void
562 CloseConnectionProc(FSmsConn smsConn, FSmPointer managerData,
563 int count, char **reasonMsgs)
565 fsm_client_t *client = (fsm_client_t *) managerData;
567 if (!SessionSupport)
569 return;
571 FSmFreeReasons(count, reasonMsgs);
572 CloseDownClient(client);
575 static
576 void SetPropertiesProc(
577 FSmsConn smsConn, FSmPointer managerData, int numProps, FSmProp **props)
579 int i;
581 if (!SessionSupport)
583 return;
585 for (i = 0; i < numProps; i++)
587 FSmFreeProperty(props[i]);
589 free ((char *) props);
592 static
593 void DeletePropertiesProc(
594 FSmsConn smsConn, FSmPointer managerData, int numProps, char **propNames)
596 int i;
598 if (!SessionSupport)
600 return;
602 for (i = 0; i < numProps; i++)
604 free (propNames[i]);
606 free ((char *) propNames);
609 static
610 void GetPropertiesProc(FSmsConn smsConn, FSmPointer managerData)
614 static Status
615 NewClientProc(
616 FSmsConn smsConn, FSmPointer managerData, unsigned long *maskRet,
617 FSmsCallbacks *callbacksRet, char **failureReasonRet)
619 fsm_client_t *nc;
621 if (!SessionSupport)
623 return 0;
626 nc = (fsm_client_t *)safemalloc(sizeof (fsm_client_t));
627 *maskRet = 0;
629 nc->smsConn = smsConn;
630 nc->ice_conn = FSmsGetIceConnection(smsConn);
631 nc->clientId = NULL;
633 running_list = flist_append_obj(running_list, nc);
635 #ifdef FVWM_DEBUG_FSM
636 fprintf(
637 stderr, "[%s][NewClientProc] On FIceConn fd = %d, client "
638 "set up session mngmt protocol\n", module_name,
639 FIceConnectionNumber (nc->ice_conn));
640 #endif
643 * Set up session manager callbacks.
646 *maskRet |= FSmsRegisterClientProcMask;
647 callbacksRet->register_client.callback = RegisterClientProc;
648 callbacksRet->register_client.manager_data = (FSmPointer) nc;
650 *maskRet |= FSmsInteractRequestProcMask;
651 callbacksRet->interact_request.callback = InteractRequestProc;
652 callbacksRet->interact_request.manager_data = (FSmPointer) nc;
654 *maskRet |= FSmsInteractDoneProcMask;
655 callbacksRet->interact_done.callback = InteractDoneProc;
656 callbacksRet->interact_done.manager_data = (FSmPointer) nc;
658 *maskRet |= FSmsSaveYourselfRequestProcMask;
659 callbacksRet->save_yourself_request.callback = SaveYourselfReqProc;
660 callbacksRet->save_yourself_request.manager_data = (FSmPointer) nc;
662 *maskRet |= FSmsSaveYourselfP2RequestProcMask;
663 callbacksRet->save_yourself_phase2_request.callback =
664 SaveYourselfPhase2ReqProc;
665 callbacksRet->save_yourself_phase2_request.manager_data =
666 (FSmPointer) nc;
668 *maskRet |= FSmsSaveYourselfDoneProcMask;
669 callbacksRet->save_yourself_done.callback = SaveYourselfDoneProc;
670 callbacksRet->save_yourself_done.manager_data = (FSmPointer) nc;
672 *maskRet |= FSmsCloseConnectionProcMask;
673 callbacksRet->close_connection.callback = CloseConnectionProc;
674 callbacksRet->close_connection.manager_data = (FSmPointer) nc;
676 *maskRet |= FSmsSetPropertiesProcMask;
677 callbacksRet->set_properties.callback = SetPropertiesProc;
678 callbacksRet->set_properties.manager_data = (FSmPointer) nc;
680 *maskRet |= FSmsDeletePropertiesProcMask;
681 callbacksRet->delete_properties.callback = DeletePropertiesProc;
682 callbacksRet->delete_properties.manager_data = (FSmPointer) nc;
684 *maskRet |= FSmsGetPropertiesProcMask;
685 callbacksRet->get_properties.callback = GetPropertiesProc;
686 callbacksRet->get_properties.manager_data = (FSmPointer) nc;
688 return 1;
695 static
696 void CompletNewConnectionMsg(void)
698 flist *l = pending_ice_conn_list;
699 FIceConn ice_conn;
700 Bool pending = False;
701 FIceAcceptStatus cstatus;
703 if (!SessionSupport)
705 return;
708 while(l != NULL)
710 ice_conn = (FIceConn)l->object;
711 cstatus = FIceConnectionStatus(ice_conn);
712 if (cstatus == FIceConnectPending)
714 pending = True;
715 l = l->next;
717 else if (cstatus == FIceConnectAccepted)
719 l = l->next;
720 pending_ice_conn_list =
721 flist_remove_obj(
722 pending_ice_conn_list,
723 ice_conn);
724 #ifdef FVWM_DEBUG_FSM
725 char *connstr;
727 connstr = FIceConnectionString (ice_conn);
728 fprintf(stderr, "[%s][NewConnection] ICE Connection "
729 "opened by client, FIceConn fd = %d, Accept at "
730 "networkId %s\n", module_name,
731 FIceConnectionNumber (ice_conn), connstr);
732 free (connstr);
733 #endif
735 else
737 if (FIceCloseConnection (ice_conn) != FIceClosedNow)
739 /* don't care */
741 pending_ice_conn_list =
742 flist_remove_obj(
743 pending_ice_conn_list,
744 ice_conn);
745 #ifdef FVWM_DEBUG_FSM
746 if (cstatus == FIceConnectIOError)
748 fprintf(stderr, "[%s][NewConnection] IO error "
749 "opening ICE Connection!\n",
750 module_name);
752 else
754 fprintf(stderr, "[%s][NewConnection] ICE "
755 "Connection rejected!\n",
756 module_name);
758 #endif
763 static
764 void NewConnectionMsg(int i)
766 FIceConn ice_conn;
767 FIceAcceptStatus status;
769 if (!SessionSupport)
771 status = 0;
772 return;
775 ice_conn = FIceAcceptConnection(listenObjs[i], &status);
776 #ifdef FVWM_DEBUG_FSM
777 fprintf(stderr, "[%s][NewConnection] %i\n", module_name, i);
778 #endif
779 if (!ice_conn)
781 #ifdef FVWM_DEBUG_FSM
782 fprintf(stderr, "[%s][NewConnection] "
783 "FIceAcceptConnection failed\n", module_name);
784 #endif
786 else
788 pending_ice_conn_list =
789 flist_append_obj(pending_ice_conn_list, ice_conn);
791 CompletNewConnectionMsg();
795 static
796 void ProcessIceMsg(fsm_ice_conn_t *fic)
798 FIceProcessMessagesStatus status;
800 if (!SessionSupport)
802 return;
805 #ifdef FVWM_DEBUG_FSM
806 fprintf(stderr, "[%s][ProcessIceMsg] %i\n", module_name, (int)fic->fd);
807 #endif
809 status = FIceProcessMessages(fic->ice_conn, NULL, NULL);
811 if (status == FIceProcessMessagesIOError)
813 flist *cl;
814 int found = 0;
816 #ifdef FVWM_DEBUG_FSM
817 fprintf(stderr, "[%s][ProcessIceMsg] IO error on connection\n",
818 module_name);
819 #endif
821 for (cl = running_list; cl; cl = cl->next)
823 fsm_client_t *client = (fsm_client_t *) cl->object;
825 if (client->ice_conn == fic->ice_conn)
827 CloseDownClient (client);
828 found = 1;
829 break;
833 if (!found)
836 * The client must have disconnected before it was added
837 * to the session manager's running list (i.e. before the
838 * NewClientProc callback was invoked).
841 FIceSetShutdownNegotiation (fic->ice_conn, False);
842 if (!FIceCloseConnection(fic->ice_conn) != FIceClosedNow)
844 /* do not care */
851 * proxy stuff
853 static
854 char *GetClientID(Display *dpy, Window window)
856 char *client_id = NULL;
857 Window client_leader = None;
858 XTextProperty tp;
859 Atom actual_type;
860 int actual_format;
861 unsigned long nitems;
862 unsigned long bytes_after;
863 unsigned char *prop = NULL;
865 if (!SessionSupport)
867 return NULL;
870 if (!_XA_WM_CLIENT_LEADER)
872 _XA_WM_CLIENT_LEADER = XInternAtom(
873 dpy, "WM_CLIENT_LEADER", False);
875 if (!_XA_SM_CLIENT_ID)
877 _XA_SM_CLIENT_ID = XInternAtom(dpy, "SM_CLIENT_ID", False);
880 if (XGetWindowProperty(
881 dpy, window, _XA_WM_CLIENT_LEADER, 0L, 1L, False,
882 AnyPropertyType, &actual_type, &actual_format, &nitems,
883 &bytes_after, &prop) == Success)
885 if (actual_type == XA_WINDOW && actual_format == 32 &&
886 nitems == 1 && bytes_after == 0)
888 client_leader = (Window)(*(long *)prop);
892 if (!client_leader)
894 client_leader = window;
897 if (client_leader)
899 if (XGetTextProperty(dpy, client_leader, &tp, _XA_SM_CLIENT_ID))
901 if (tp.encoding == XA_STRING && tp.format == 8 &&
902 tp.nitems != 0)
904 client_id = (char *) tp.value;
909 if (prop)
911 XFree (prop);
914 return client_id;
917 static
918 void set_session_manager(Display *dpy, Window window, char *sm)
920 Window client_leader = None;
921 Atom actual_type;
922 int actual_format;
923 unsigned long nitems;
924 unsigned long bytes_after;
925 unsigned char *prop = NULL;
926 char *dummy_id;
927 static Atom _XA_SESSION_MANAGER = None;
929 if (!SessionSupport)
931 return;
934 dummy_id = "0";
936 if (!_XA_SESSION_MANAGER)
938 _XA_SESSION_MANAGER = XInternAtom (
939 dpy, "SESSION_MANAGER", False);
941 if (!_XA_WM_CLIENT_LEADER)
943 _XA_WM_CLIENT_LEADER = XInternAtom(
944 dpy, "WM_CLIENT_LEADER", False);
946 if (!_XA_SM_CLIENT_ID)
948 _XA_SM_CLIENT_ID = XInternAtom(dpy, "SM_CLIENT_ID", False);
951 if (XGetWindowProperty(
952 dpy, window, _XA_WM_CLIENT_LEADER, 0L, 1L, False,
953 AnyPropertyType, &actual_type, &actual_format, &nitems,
954 &bytes_after, &prop) == Success)
956 if (actual_type == XA_WINDOW && actual_format == 32 &&
957 nitems == 1 && bytes_after == 0)
959 client_leader = (Window)(*(long *)prop);
963 if (!client_leader)
965 client_leader = window;
968 #ifdef FVWM_DEBUG_FSM
969 fprintf(
970 stderr, "[%s][fsm_init] Proxy %s window 0x%lx\n",
971 module_name, (sm)? "On":"Off", client_leader);
973 #endif
975 /* set the client id for ksmserver */
976 if (sm)
978 XChangeProperty(
979 dpy, client_leader, _XA_SESSION_MANAGER, XA_STRING,
980 8, PropModeReplace, (unsigned char *)sm, strlen(sm));
981 XChangeProperty(
982 dpy, client_leader, _XA_SM_CLIENT_ID, XA_STRING,
983 8, PropModeReplace, (unsigned char *)dummy_id,
984 strlen(dummy_id));
986 else
988 XDeleteProperty(dpy, client_leader, _XA_SESSION_MANAGER);
989 XDeleteProperty(dpy, client_leader, _XA_SM_CLIENT_ID);
993 /* ---------------------------- interface functions ------------------------ */
995 int fsm_init(char *module)
997 char errormsg[256];
998 int i;
999 char *p;
1001 if (!SessionSupport)
1003 /* -Wall fix */
1004 MyIoErrorHandler(NULL);
1005 HostBasedAuthProc(NULL);
1006 ice_watch_fd(0, NULL, 0, NULL);
1007 NewClientProc(0, NULL, 0, NULL, NULL);
1008 #ifdef FVWM_DEBUG_FSM
1009 fprintf(
1010 stderr, "[%s][fsm_init] No Session Support\n",
1011 module_name);
1012 #endif
1013 return 0;
1016 if (fsm_init_succeed)
1018 fprintf(
1019 stderr, "[%s][fsm_init] <<ERROR>> -- "
1020 "Session already Initialized!\n", module_name);
1021 return 1;
1023 module_name = module;
1024 InstallIOErrorHandler ();
1026 #ifdef FVWM_DEBUG_FSM
1027 fprintf(stderr, "[%s][fsm_init] FSmsInitialize\n", module_name);
1028 #endif
1029 if (!FSmsInitialize(
1030 module, "1.0", NewClientProc, NULL, HostBasedAuthProc, 256,
1031 errormsg))
1033 fprintf(
1034 stderr, "[%s][fsm_init] <<ERROR>> -- "
1035 "FSmsInitialize failed: %s\n",
1036 module_name, errormsg);
1037 return 0;
1040 if (!FIceListenForConnections (
1041 &numTransports, &listenObjs, 256, errormsg))
1043 fprintf(
1044 stderr, "[%s][fsm_init] <<ERROR>> -- "
1045 "FIceListenForConnections failed:\n"
1046 "%s\n", module_name, errormsg);
1047 return 0;
1050 atexit(CloseListeners);
1052 if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
1054 fprintf(
1055 stderr, "[%s][fsm_init] <<ERROR>> -- "
1056 "Could not set authorization\n", module_name);
1057 return 0;
1060 if (FIceAddConnectionWatch(&ice_watch_fd, NULL) == 0)
1062 fprintf(stderr,
1063 "[%s][fsm_init] <<ERROR>> -- "
1064 "FIceAddConnectionWatch failed\n", module_name);
1065 return 0;
1068 ice_fd = (int *)safemalloc(sizeof(int) * numTransports + 1);
1069 for (i = 0; i < numTransports; i++)
1071 ice_fd[i] = FIceGetListenConnectionNumber(listenObjs[i]);
1074 networkIds = FIceComposeNetworkIdList(numTransports, listenObjs);
1075 p = (char *)safemalloc(
1076 16 + strlen(networkIds) + 1);
1077 sprintf(p, "SESSION_MANAGER=%s", networkIds);
1078 putenv(p);
1080 #ifdef FVWM_DEBUG_FSM
1081 fprintf(stderr,"[%s][fsm_init] OK: %i\n", module_name, numTransports);
1082 fprintf(stderr,"\t%s\n", p);
1083 #endif
1085 fsm_init_succeed = True;
1086 return 1;
1089 void fsm_fdset(fd_set *in_fdset)
1091 int i;
1092 flist *l = fsm_ice_conn_list;
1093 fsm_ice_conn_t *fic;
1095 if (!SessionSupport || !fsm_init_succeed)
1097 return;
1100 for (i = 0; i < numTransports; i++)
1102 FD_SET(ice_fd[i], in_fdset);
1104 while(l != NULL)
1106 fic = (fsm_ice_conn_t *)l->object;
1107 FD_SET(fic->fd, in_fdset);
1108 l = l->next;
1113 Bool fsm_process(fd_set *in_fdset)
1115 int i;
1116 flist *l = fsm_ice_conn_list;
1117 fsm_ice_conn_t *fic;
1119 if (!SessionSupport || !fsm_init_succeed)
1121 return False;
1124 if (pending_ice_conn_list != NULL)
1126 CompletNewConnectionMsg();
1128 while(l != NULL)
1130 fic = (fsm_ice_conn_t *)l->object;
1131 if (FD_ISSET(fic->fd, in_fdset))
1133 ProcessIceMsg(fic);
1135 l = l->next;
1137 for (i = 0; i < numTransports; i++)
1139 if (FD_ISSET(ice_fd[i], in_fdset))
1141 NewConnectionMsg(i);
1144 if (pending_ice_conn_list != NULL)
1146 return True;
1148 return False;
1151 /* this try to explain to ksmserver and various sm poxies that they should not
1152 * connect our non XSMP award leader window to the top level sm */
1153 void fsm_proxy(Display *dpy, Window win, char *sm)
1155 char *client_id;
1156 flist *l = running_list;
1157 Bool found = False;
1159 if (!SessionSupport || !fsm_init_succeed)
1161 return;
1164 client_id = GetClientID(dpy, win);
1166 if (client_id != NULL && strcmp("0", client_id) != 0)
1168 for (l = running_list; l; l = l->next)
1170 fsm_client_t *client = (fsm_client_t *) l->object;
1172 if (client->clientId &&
1173 strcmp(client->clientId, client_id) == 0)
1175 found = 1;
1176 break;
1181 if (found)
1183 return;
1186 set_session_manager(dpy, win, sm);
1189 void fsm_close(void)
1191 if (!SessionSupport || !fsm_init_succeed)
1193 return;
1195 FreeAuthenticationData(numTransports, authDataEntries);