1126a8a12Smrg/* 2126a8a12Smrg 3126a8a12SmrgCopyright 1993, 1998 The Open Group 4126a8a12Smrg 5126a8a12SmrgPermission to use, copy, modify, distribute, and sell this software and its 6126a8a12Smrgdocumentation for any purpose is hereby granted without fee, provided that 7126a8a12Smrgthe above copyright notice appear in all copies and that both that 8126a8a12Smrgcopyright notice and this permission notice appear in supporting 9126a8a12Smrgdocumentation. 10126a8a12Smrg 11126a8a12SmrgThe above copyright notice and this permission notice shall be included in 12126a8a12Smrgall copies or substantial portions of the Software. 13126a8a12Smrg 14126a8a12SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15126a8a12SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16126a8a12SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17126a8a12SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18126a8a12SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19126a8a12SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20126a8a12Smrg 21126a8a12SmrgExcept as contained in this notice, the name of The Open Group shall not be 22126a8a12Smrgused in advertising or otherwise to promote the sale, use or other dealings 23126a8a12Smrgin this Software without prior written authorization from The Open Group. 24126a8a12Smrg 25126a8a12Smrg*/ 26126a8a12Smrg 27126a8a12Smrg/* 28126a8a12Smrg * Author: Ralph Mor, X Consortium 29126a8a12Smrg */ 30126a8a12Smrg 31126a8a12Smrg#ifdef HAVE_CONFIG_H 32126a8a12Smrg#include <config.h> 33126a8a12Smrg#endif 34126a8a12Smrg#include <X11/SM/SMlib.h> 35126a8a12Smrg#include "SMlibint.h" 36126a8a12Smrg 37d656433aSmrgint _SmcOpcode = 0; 38d656433aSmrgint _SmsOpcode = 0; 39d656433aSmrg 40d656433aSmrgSmsNewClientProc _SmsNewClientProc; 41d656433aSmrgSmPointer _SmsNewClientData; 42d656433aSmrg 43d656433aSmrgSmcErrorHandler _SmcErrorHandler = _SmcDefaultErrorHandler; 44d656433aSmrgSmsErrorHandler _SmsErrorHandler = _SmsDefaultErrorHandler; 45d656433aSmrg 46d656433aSmrg 47d656433aSmrgstatic void 48d656433aSmrgset_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks); 49126a8a12Smrg 50126a8a12Smrg 51126a8a12SmrgSmcConn 52d656433aSmrgSmcOpenConnection(char *networkIdsList, SmPointer context, 53d656433aSmrg int xsmpMajorRev, int xsmpMinorRev, 54d656433aSmrg unsigned long mask, SmcCallbacks *callbacks, 550a6b08f8Smrg const char *previousId, char **clientIdRet, 56d656433aSmrg int errorLength, char *errorStringRet) 57126a8a12Smrg{ 58126a8a12Smrg SmcConn smcConn; 59126a8a12Smrg IceConn iceConn; 60126a8a12Smrg char *ids; 61126a8a12Smrg IceProtocolSetupStatus setupstat; 62126a8a12Smrg int majorVersion; 63126a8a12Smrg int minorVersion; 64126a8a12Smrg char *vendor = NULL; 65126a8a12Smrg char *release = NULL; 66126a8a12Smrg smRegisterClientMsg *pMsg; 67126a8a12Smrg char *pData; 680a6b08f8Smrg unsigned int extra, len; 69126a8a12Smrg IceReplyWaitInfo replyWait; 70126a8a12Smrg _SmcRegisterClientReply reply; 71126a8a12Smrg Bool gotReply, ioErrorOccured; 72126a8a12Smrg 73126a8a12Smrg const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"}; 74126a8a12Smrg IcePoAuthProc auth_procs[] = {_IcePoMagicCookie1Proc}; 75126a8a12Smrg int auth_count = 1; 76126a8a12Smrg 77126a8a12Smrg IcePoVersionRec versions[] = { 78126a8a12Smrg {SmProtoMajor, SmProtoMinor, _SmcProcessMessage} 79126a8a12Smrg }; 80126a8a12Smrg int version_count = 1; 81126a8a12Smrg 82126a8a12Smrg 83126a8a12Smrg *clientIdRet = NULL; 84126a8a12Smrg 85126a8a12Smrg if (errorStringRet && errorLength > 0) 86126a8a12Smrg *errorStringRet = '\0'; 87126a8a12Smrg 88126a8a12Smrg if (!_SmcOpcode) 89126a8a12Smrg { 90126a8a12Smrg /* 91126a8a12Smrg * For now, there is only one version of XSMP, so we don't 92126a8a12Smrg * have to check {xsmpMajorRev, xsmpMinorRev}. In the future, 93126a8a12Smrg * we will check against versions and generate the list 94126a8a12Smrg * of versions the application actually supports. 95126a8a12Smrg */ 96126a8a12Smrg 97126a8a12Smrg if ((_SmcOpcode = IceRegisterForProtocolSetup ("XSMP", 98126a8a12Smrg SmVendorString, SmReleaseString, version_count, versions, 99126a8a12Smrg auth_count, auth_names, auth_procs, NULL)) < 0) 100126a8a12Smrg { 101126a8a12Smrg if (errorStringRet && errorLength > 0) { 102126a8a12Smrg strncpy (errorStringRet, 103126a8a12Smrg "Could not register XSMP protocol with ICE", 104126a8a12Smrg errorLength); 105126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 106126a8a12Smrg } 107126a8a12Smrg 108126a8a12Smrg return (NULL); 109126a8a12Smrg } 110126a8a12Smrg } 111126a8a12Smrg 112126a8a12Smrg if (networkIdsList == NULL || *networkIdsList == '\0') 113126a8a12Smrg { 1146bea0e4fSmrg if ((ids = getenv ("SESSION_MANAGER")) == NULL) 115126a8a12Smrg { 116126a8a12Smrg if (errorStringRet && errorLength > 0) { 117126a8a12Smrg strncpy (errorStringRet, 118126a8a12Smrg "SESSION_MANAGER environment variable not defined", 119126a8a12Smrg errorLength); 120126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 121126a8a12Smrg } 122126a8a12Smrg return (NULL); 123126a8a12Smrg } 124126a8a12Smrg } 125126a8a12Smrg else 126126a8a12Smrg { 127126a8a12Smrg ids = networkIdsList; 128126a8a12Smrg } 129126a8a12Smrg 130126a8a12Smrg if ((iceConn = IceOpenConnection ( 131126a8a12Smrg ids, context, 0, _SmcOpcode, errorLength, errorStringRet)) == NULL) 132126a8a12Smrg { 133126a8a12Smrg return (NULL); 134126a8a12Smrg } 135126a8a12Smrg 1363c15da26Smrg if ((smcConn = malloc (sizeof (struct _SmcConn))) == NULL) 137126a8a12Smrg { 138126a8a12Smrg if (errorStringRet && errorLength > 0) { 139126a8a12Smrg strncpy (errorStringRet, "Can't malloc", errorLength); 140126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 141126a8a12Smrg } 142126a8a12Smrg IceCloseConnection (iceConn); 143126a8a12Smrg return (NULL); 144126a8a12Smrg } 145126a8a12Smrg 146126a8a12Smrg setupstat = IceProtocolSetup (iceConn, _SmcOpcode, 147126a8a12Smrg (IcePointer) smcConn, 148126a8a12Smrg False /* mustAuthenticate */, 149126a8a12Smrg &majorVersion, &minorVersion, 150126a8a12Smrg &vendor, &release, errorLength, errorStringRet); 151126a8a12Smrg 152126a8a12Smrg if (setupstat == IceProtocolSetupFailure || 153126a8a12Smrg setupstat == IceProtocolSetupIOError) 154126a8a12Smrg { 155126a8a12Smrg IceCloseConnection (iceConn); 1563c15da26Smrg free (smcConn); 157126a8a12Smrg return (NULL); 158126a8a12Smrg } 159126a8a12Smrg else if (setupstat == IceProtocolAlreadyActive) 160126a8a12Smrg { 161126a8a12Smrg /* 162126a8a12Smrg * This case should never happen, because when we called 163126a8a12Smrg * IceOpenConnection, we required that the ICE connection 164126a8a12Smrg * may not already have XSMP active on it. 165126a8a12Smrg */ 166126a8a12Smrg 1673c15da26Smrg free (smcConn); 168126a8a12Smrg if (errorStringRet && errorLength > 0) { 169126a8a12Smrg strncpy (errorStringRet, "Internal error in IceOpenConnection", 170126a8a12Smrg errorLength); 171126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 172126a8a12Smrg } 173126a8a12Smrg return (NULL); 174126a8a12Smrg } 175126a8a12Smrg 176126a8a12Smrg smcConn->iceConn = iceConn; 177126a8a12Smrg smcConn->proto_major_version = majorVersion; 178126a8a12Smrg smcConn->proto_minor_version = minorVersion; 179126a8a12Smrg smcConn->vendor = vendor; 180126a8a12Smrg smcConn->release = release; 181126a8a12Smrg smcConn->client_id = NULL; 182126a8a12Smrg 183126a8a12Smrg bzero ((char *) &smcConn->callbacks, sizeof (SmcCallbacks)); 184126a8a12Smrg set_callbacks (smcConn, mask, callbacks); 185126a8a12Smrg 186126a8a12Smrg smcConn->interact_waits = NULL; 187126a8a12Smrg smcConn->phase2_wait = NULL; 188126a8a12Smrg smcConn->prop_reply_waits = NULL; 189126a8a12Smrg 190126a8a12Smrg smcConn->save_yourself_in_progress = False; 191126a8a12Smrg smcConn->shutdown_in_progress = False; 192126a8a12Smrg 193126a8a12Smrg 194126a8a12Smrg /* 195126a8a12Smrg * Now register the client 196126a8a12Smrg */ 197126a8a12Smrg 198d656433aSmrg if (!previousId) 199d656433aSmrg previousId = ""; 200d656433aSmrg len = strlen (previousId); 201126a8a12Smrg extra = ARRAY8_BYTES (len); 202126a8a12Smrg 203126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient, 204126a8a12Smrg SIZEOF (smRegisterClientMsg), WORD64COUNT (extra), 205126a8a12Smrg smRegisterClientMsg, pMsg, pData); 206126a8a12Smrg 2073fb97780Smrg if (pData != NULL) { 2083fb97780Smrg STORE_ARRAY8 (pData, len, previousId); 2093fb97780Smrg IceFlush (iceConn); 2103fb97780Smrg } 2113fb97780Smrg else { 2123fb97780Smrg SEND_ARRAY8 (iceConn, len, previousId); 2133fb97780Smrg } 214126a8a12Smrg 215126a8a12Smrg replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn); 216126a8a12Smrg replyWait.major_opcode_of_request = _SmcOpcode; 217126a8a12Smrg replyWait.minor_opcode_of_request = SM_RegisterClient; 218126a8a12Smrg replyWait.reply = (IcePointer) &reply; 219126a8a12Smrg 220126a8a12Smrg gotReply = False; 221126a8a12Smrg ioErrorOccured = False; 222126a8a12Smrg 223126a8a12Smrg while (!gotReply && !ioErrorOccured) 224126a8a12Smrg { 225126a8a12Smrg ioErrorOccured = (IceProcessMessages ( 226126a8a12Smrg iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 227126a8a12Smrg 228126a8a12Smrg if (ioErrorOccured) 229126a8a12Smrg { 230126a8a12Smrg if (errorStringRet && errorLength > 0) { 2313fb97780Smrg strncpy (errorStringRet, "IO error occurred opening connection", 232126a8a12Smrg errorLength); 233126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 234126a8a12Smrg } 235126a8a12Smrg free (smcConn->vendor); 236126a8a12Smrg free (smcConn->release); 2373c15da26Smrg free (smcConn); 238126a8a12Smrg 239126a8a12Smrg return (NULL); 240126a8a12Smrg } 241126a8a12Smrg else if (gotReply) 242126a8a12Smrg { 243126a8a12Smrg if (reply.status == 1) 244126a8a12Smrg { 245126a8a12Smrg /* 246126a8a12Smrg * The client successfully registered. 247126a8a12Smrg */ 248126a8a12Smrg 249126a8a12Smrg *clientIdRet = reply.client_id; 250126a8a12Smrg 2513c15da26Smrg smcConn->client_id = strdup (*clientIdRet); 252126a8a12Smrg } 253126a8a12Smrg else 254126a8a12Smrg { 255126a8a12Smrg /* 256126a8a12Smrg * Could not register the client because the previous ID 257126a8a12Smrg * was bad. So now we register the client with the 258126a8a12Smrg * previous ID set to NULL. 259126a8a12Smrg */ 260126a8a12Smrg 261126a8a12Smrg extra = ARRAY8_BYTES (0); 262126a8a12Smrg 263126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient, 264126a8a12Smrg SIZEOF (smRegisterClientMsg), WORD64COUNT (extra), 265126a8a12Smrg smRegisterClientMsg, pMsg, pData); 266126a8a12Smrg 2673fb97780Smrg if (pData != NULL) { 2683fb97780Smrg STORE_ARRAY8 (pData, 0, ""); 2693fb97780Smrg IceFlush (iceConn); 2703fb97780Smrg } 2713fb97780Smrg else { 2723fb97780Smrg SEND_ARRAY8 (iceConn, 0, ""); 2733fb97780Smrg } 274126a8a12Smrg 275126a8a12Smrg replyWait.sequence_of_request = 276126a8a12Smrg IceLastSentSequenceNumber (iceConn); 277126a8a12Smrg 278126a8a12Smrg gotReply = False; 279126a8a12Smrg } 280126a8a12Smrg } 281126a8a12Smrg } 282126a8a12Smrg 283126a8a12Smrg return (smcConn); 284126a8a12Smrg} 285126a8a12Smrg 286126a8a12Smrg 287126a8a12Smrg 288126a8a12SmrgSmcCloseStatus 289d656433aSmrgSmcCloseConnection(SmcConn smcConn, int count, char **reasonMsgs) 290126a8a12Smrg{ 291126a8a12Smrg IceConn iceConn = smcConn->iceConn; 292126a8a12Smrg smCloseConnectionMsg *pMsg; 293126a8a12Smrg char *pData; 294126a8a12Smrg int extra, i; 295126a8a12Smrg IceCloseStatus closeStatus; 296126a8a12Smrg SmcCloseStatus statusRet; 297126a8a12Smrg 298126a8a12Smrg extra = 8; 299126a8a12Smrg 300126a8a12Smrg for (i = 0; i < count; i++) 301126a8a12Smrg extra += ARRAY8_BYTES (strlen (reasonMsgs[i])); 302126a8a12Smrg 303126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_CloseConnection, 304126a8a12Smrg SIZEOF (smCloseConnectionMsg), WORD64COUNT (extra), 305126a8a12Smrg smCloseConnectionMsg, pMsg, pData); 306126a8a12Smrg 3073fb97780Smrg if (pData != NULL) { 3083fb97780Smrg STORE_CARD32 (pData, (CARD32) count); 3093fb97780Smrg STORE_CARD32 (pData, (CARD32) 0); /* padding */ 310126a8a12Smrg 3113fb97780Smrg for (i = 0; i < count; i++) 3123fb97780Smrg STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]); 313126a8a12Smrg 3143fb97780Smrg IceFlush (iceConn); 3153fb97780Smrg } else { 3163fb97780Smrg CARD32 count_header[2] = { 3173fb97780Smrg (CARD32) count, 3183fb97780Smrg (CARD32) 0 /* padding */ 3193fb97780Smrg }; 3203fb97780Smrg IceWriteData32 (iceConn, 8, count_header); 3213fb97780Smrg 3223fb97780Smrg for (i = 0; i < count; i++) 3233fb97780Smrg SEND_ARRAY8 (iceConn, strlen (reasonMsgs[i]), reasonMsgs[i]); 3243fb97780Smrg } 325126a8a12Smrg 326126a8a12Smrg IceProtocolShutdown (iceConn, _SmcOpcode); 327126a8a12Smrg IceSetShutdownNegotiation (iceConn, False); 328126a8a12Smrg closeStatus = IceCloseConnection (iceConn); 329126a8a12Smrg 330126a8a12Smrg if (smcConn->vendor) 331126a8a12Smrg free (smcConn->vendor); 332126a8a12Smrg 333126a8a12Smrg if (smcConn->release) 334126a8a12Smrg free (smcConn->release); 335126a8a12Smrg 336126a8a12Smrg if (smcConn->client_id) 337126a8a12Smrg free (smcConn->client_id); 338126a8a12Smrg 3393fb97780Smrg if (smcConn->interact_waits) 3403fb97780Smrg { 3413fb97780Smrg _SmcInteractWait *ptr = smcConn->interact_waits; 3423fb97780Smrg _SmcInteractWait *next; 3433fb97780Smrg 3443fb97780Smrg while (ptr) 3453fb97780Smrg { 3463fb97780Smrg next = ptr->next; 3473fb97780Smrg free (ptr); 3483fb97780Smrg ptr = next; 3493fb97780Smrg } 3503fb97780Smrg } 3513fb97780Smrg 3523fb97780Smrg if (smcConn->phase2_wait) 3533fb97780Smrg free (smcConn->phase2_wait); 3543fb97780Smrg 355126a8a12Smrg if (smcConn->prop_reply_waits) 356126a8a12Smrg { 357126a8a12Smrg _SmcPropReplyWait *ptr = smcConn->prop_reply_waits; 358126a8a12Smrg _SmcPropReplyWait *next; 359126a8a12Smrg 360126a8a12Smrg while (ptr) 361126a8a12Smrg { 362126a8a12Smrg next = ptr->next; 3633c15da26Smrg free (ptr); 364126a8a12Smrg ptr = next; 365126a8a12Smrg } 3663c15da26Smrg 367126a8a12Smrg } 368126a8a12Smrg 3693c15da26Smrg free (smcConn); 370126a8a12Smrg 371126a8a12Smrg if (closeStatus == IceClosedNow) 372126a8a12Smrg statusRet = SmcClosedNow; 373126a8a12Smrg else if (closeStatus == IceClosedASAP) 374126a8a12Smrg statusRet = SmcClosedASAP; 375126a8a12Smrg else 376126a8a12Smrg statusRet = SmcConnectionInUse; 377126a8a12Smrg 378126a8a12Smrg return (statusRet); 379126a8a12Smrg} 380126a8a12Smrg 381126a8a12Smrg 382126a8a12Smrg 383126a8a12Smrgvoid 384d656433aSmrgSmcModifyCallbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks) 385126a8a12Smrg{ 386126a8a12Smrg set_callbacks (smcConn, mask, callbacks); 387126a8a12Smrg} 388126a8a12Smrg 389126a8a12Smrg 390126a8a12Smrg 391126a8a12Smrgvoid 392d656433aSmrgSmcSetProperties(SmcConn smcConn, int numProps, SmProp **props) 393126a8a12Smrg{ 394126a8a12Smrg IceConn iceConn = smcConn->iceConn; 395126a8a12Smrg smSetPropertiesMsg *pMsg; 396126a8a12Smrg char *pBuf; 397126a8a12Smrg char *pStart; 3980a6b08f8Smrg unsigned int bytes; 399126a8a12Smrg 400126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties, 401126a8a12Smrg SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg); 402126a8a12Smrg 403126a8a12Smrg LISTOF_PROP_BYTES (numProps, props, bytes); 404126a8a12Smrg pMsg->length += WORD64COUNT (bytes); 405126a8a12Smrg 406126a8a12Smrg pBuf = pStart = IceAllocScratch (iceConn, bytes); 407d656433aSmrg memset(pStart, 0, bytes); 408126a8a12Smrg 409126a8a12Smrg STORE_LISTOF_PROPERTY (pBuf, numProps, props); 410126a8a12Smrg 411126a8a12Smrg IceWriteData (iceConn, bytes, pStart); 412126a8a12Smrg IceFlush (iceConn); 413126a8a12Smrg} 414126a8a12Smrg 415126a8a12Smrg 416126a8a12Smrg 417126a8a12Smrgvoid 418d656433aSmrgSmcDeleteProperties(SmcConn smcConn, int numProps, char **propNames) 419126a8a12Smrg{ 420126a8a12Smrg IceConn iceConn = smcConn->iceConn; 421126a8a12Smrg smDeletePropertiesMsg *pMsg; 422126a8a12Smrg char *pData; 423126a8a12Smrg int extra, i; 424126a8a12Smrg 425126a8a12Smrg extra = 8; 426126a8a12Smrg 427126a8a12Smrg for (i = 0; i < numProps; i++) 428126a8a12Smrg extra += ARRAY8_BYTES (strlen (propNames[i])); 429126a8a12Smrg 430126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties, 431126a8a12Smrg SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra), 432126a8a12Smrg smDeletePropertiesMsg, pMsg, pData); 433126a8a12Smrg 4343fb97780Smrg if (pData != NULL) { 4353fb97780Smrg STORE_CARD32 (pData, (CARD32) numProps); 4363fb97780Smrg STORE_CARD32 (pData, (CARD32) 0); /* padding */ 437126a8a12Smrg 4383fb97780Smrg for (i = 0; i < numProps; i++) 4393fb97780Smrg STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]); 440126a8a12Smrg 4413fb97780Smrg IceFlush (iceConn); 4423fb97780Smrg } 4433fb97780Smrg else { 4443fb97780Smrg CARD32 count_header[2] = { 4453fb97780Smrg (CARD32) numProps, 4463fb97780Smrg (CARD32) 0 /* padding */ 4473fb97780Smrg }; 4483fb97780Smrg IceWriteData32 (iceConn, 8, count_header); 4493fb97780Smrg 4503fb97780Smrg for (i = 0; i < numProps; i++) 4513fb97780Smrg SEND_ARRAY8 (iceConn, strlen (propNames[i]), propNames[i]); 4523fb97780Smrg } 453126a8a12Smrg} 454126a8a12Smrg 455126a8a12Smrg 456126a8a12Smrg 457126a8a12SmrgStatus 458d656433aSmrgSmcGetProperties(SmcConn smcConn, SmcPropReplyProc propReplyProc, 459d656433aSmrg SmPointer clientData) 460126a8a12Smrg{ 461126a8a12Smrg IceConn iceConn = smcConn->iceConn; 462126a8a12Smrg _SmcPropReplyWait *wait, *ptr; 463126a8a12Smrg 4643c15da26Smrg if ((wait = malloc (sizeof (_SmcPropReplyWait))) == NULL) 465126a8a12Smrg { 466126a8a12Smrg return (0); 467126a8a12Smrg } 468126a8a12Smrg 469126a8a12Smrg wait->prop_reply_proc = propReplyProc; 470126a8a12Smrg wait->client_data = clientData; 471126a8a12Smrg wait->next = NULL; 472126a8a12Smrg 473126a8a12Smrg ptr = smcConn->prop_reply_waits; 474126a8a12Smrg while (ptr && ptr->next) 475126a8a12Smrg ptr = ptr->next; 476126a8a12Smrg 477126a8a12Smrg if (ptr == NULL) 478126a8a12Smrg smcConn->prop_reply_waits = wait; 479126a8a12Smrg else 480126a8a12Smrg ptr->next = wait; 481126a8a12Smrg 482126a8a12Smrg IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties); 483126a8a12Smrg IceFlush (iceConn); 484126a8a12Smrg 485126a8a12Smrg return (1); 486126a8a12Smrg} 487126a8a12Smrg 488126a8a12Smrg 489126a8a12Smrg 490126a8a12SmrgStatus 491d656433aSmrgSmcInteractRequest(SmcConn smcConn, int dialogType, 492d656433aSmrg SmcInteractProc interactProc, SmPointer clientData) 493126a8a12Smrg{ 494126a8a12Smrg IceConn iceConn = smcConn->iceConn; 495126a8a12Smrg smInteractRequestMsg *pMsg; 496126a8a12Smrg _SmcInteractWait *wait, *ptr; 497126a8a12Smrg 4983c15da26Smrg if ((wait = malloc (sizeof (_SmcInteractWait))) == NULL) 499126a8a12Smrg { 500126a8a12Smrg return (0); 501126a8a12Smrg } 502126a8a12Smrg 503126a8a12Smrg wait->interact_proc = interactProc; 504126a8a12Smrg wait->client_data = clientData; 505126a8a12Smrg wait->next = NULL; 506126a8a12Smrg 507126a8a12Smrg ptr = smcConn->interact_waits; 508126a8a12Smrg while (ptr && ptr->next) 509126a8a12Smrg ptr = ptr->next; 510126a8a12Smrg 511126a8a12Smrg if (ptr == NULL) 512126a8a12Smrg smcConn->interact_waits = wait; 513126a8a12Smrg else 514126a8a12Smrg ptr->next = wait; 515126a8a12Smrg 516126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest, 517126a8a12Smrg SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg); 518126a8a12Smrg 519126a8a12Smrg pMsg->dialogType = dialogType; 520126a8a12Smrg 521126a8a12Smrg IceFlush (iceConn); 522126a8a12Smrg 523126a8a12Smrg return (1); 524126a8a12Smrg} 525126a8a12Smrg 526126a8a12Smrg 527126a8a12Smrg 528126a8a12Smrgvoid 529d656433aSmrgSmcInteractDone(SmcConn smcConn, Bool cancelShutdown) 530126a8a12Smrg{ 531126a8a12Smrg IceConn iceConn = smcConn->iceConn; 532126a8a12Smrg smInteractDoneMsg *pMsg; 533126a8a12Smrg 534126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone, 535126a8a12Smrg SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg); 536126a8a12Smrg 537126a8a12Smrg pMsg->cancelShutdown = cancelShutdown; 538126a8a12Smrg 539126a8a12Smrg IceFlush (iceConn); 540126a8a12Smrg} 541126a8a12Smrg 542126a8a12Smrg 543126a8a12Smrg 544126a8a12Smrgvoid 545d656433aSmrgSmcRequestSaveYourself(SmcConn smcConn, int saveType, Bool shutdown, 546d656433aSmrg int interactStyle, Bool fast, Bool global) 547126a8a12Smrg{ 548126a8a12Smrg IceConn iceConn = smcConn->iceConn; 549126a8a12Smrg smSaveYourselfRequestMsg *pMsg; 550126a8a12Smrg 551126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest, 552126a8a12Smrg SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg); 553126a8a12Smrg 554126a8a12Smrg pMsg->saveType = saveType; 555126a8a12Smrg pMsg->shutdown = shutdown; 556126a8a12Smrg pMsg->interactStyle = interactStyle; 557126a8a12Smrg pMsg->fast = fast; 558126a8a12Smrg pMsg->global = global; 559126a8a12Smrg 560126a8a12Smrg IceFlush (iceConn); 561126a8a12Smrg} 562126a8a12Smrg 563126a8a12Smrg 564126a8a12Smrg 565126a8a12SmrgStatus 566d656433aSmrgSmcRequestSaveYourselfPhase2(SmcConn smcConn, 567d656433aSmrg SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc, 568d656433aSmrg SmPointer clientData) 569126a8a12Smrg{ 570126a8a12Smrg IceConn iceConn = smcConn->iceConn; 571126a8a12Smrg _SmcPhase2Wait *wait; 572126a8a12Smrg 573126a8a12Smrg if (smcConn->phase2_wait) 574126a8a12Smrg wait = smcConn->phase2_wait; 575126a8a12Smrg else 576126a8a12Smrg { 5773c15da26Smrg if ((wait = malloc (sizeof (_SmcPhase2Wait))) == NULL) 578126a8a12Smrg { 579126a8a12Smrg return (0); 580126a8a12Smrg } 581126a8a12Smrg } 582126a8a12Smrg 583126a8a12Smrg wait->phase2_proc = saveYourselfPhase2Proc; 584126a8a12Smrg wait->client_data = clientData; 585126a8a12Smrg 586126a8a12Smrg smcConn->phase2_wait = wait; 587126a8a12Smrg 588126a8a12Smrg IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request); 589126a8a12Smrg IceFlush (iceConn); 590126a8a12Smrg 591126a8a12Smrg return (1); 592126a8a12Smrg} 593126a8a12Smrg 594126a8a12Smrg 595126a8a12Smrg 596126a8a12Smrgvoid 597d656433aSmrgSmcSaveYourselfDone(SmcConn smcConn, Bool success) 598126a8a12Smrg{ 599126a8a12Smrg IceConn iceConn = smcConn->iceConn; 600126a8a12Smrg smSaveYourselfDoneMsg *pMsg; 601126a8a12Smrg 602126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone, 603126a8a12Smrg SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg); 604126a8a12Smrg 605126a8a12Smrg pMsg->success = success; 606126a8a12Smrg 607126a8a12Smrg IceFlush (iceConn); 608126a8a12Smrg} 609126a8a12Smrg 610126a8a12Smrg 611126a8a12Smrg 612126a8a12Smrgstatic void 613d656433aSmrgset_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks) 614126a8a12Smrg{ 615126a8a12Smrg if (mask & SmcSaveYourselfProcMask) 616126a8a12Smrg { 617126a8a12Smrg smcConn->callbacks.save_yourself.callback = 618126a8a12Smrg callbacks->save_yourself.callback; 619126a8a12Smrg smcConn->callbacks.save_yourself.client_data = 620126a8a12Smrg callbacks->save_yourself.client_data; 621126a8a12Smrg } 622126a8a12Smrg 623126a8a12Smrg if (mask & SmcDieProcMask) 624126a8a12Smrg { 625126a8a12Smrg smcConn->callbacks.die.callback = callbacks->die.callback; 626126a8a12Smrg smcConn->callbacks.die.client_data = callbacks->die.client_data; 627126a8a12Smrg } 628126a8a12Smrg 629126a8a12Smrg if (mask & SmcSaveCompleteProcMask) 630126a8a12Smrg { 631126a8a12Smrg smcConn->callbacks.save_complete.callback = 632126a8a12Smrg callbacks->save_complete.callback; 633126a8a12Smrg smcConn->callbacks.save_complete.client_data = 634126a8a12Smrg callbacks->save_complete.client_data; 635126a8a12Smrg } 636126a8a12Smrg 637126a8a12Smrg if (mask & SmcShutdownCancelledProcMask) 638126a8a12Smrg { 639126a8a12Smrg smcConn->callbacks.shutdown_cancelled.callback = 640126a8a12Smrg callbacks->shutdown_cancelled.callback; 641126a8a12Smrg smcConn->callbacks.shutdown_cancelled.client_data = 642126a8a12Smrg callbacks->shutdown_cancelled.client_data; 643126a8a12Smrg } 644126a8a12Smrg} 645