sm_client.c revision d656433a
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 40d656433aSmrg#ifndef __UNIXOS2__ 41d656433aSmrgSmsNewClientProc _SmsNewClientProc; 42d656433aSmrgSmPointer _SmsNewClientData; 43d656433aSmrg#else 44d656433aSmrgSmsNewClientProc _SmsNewClientProc = 0; 45d656433aSmrgSmPointer _SmsNewClientData = 0; 46d656433aSmrg#endif 47d656433aSmrg 48d656433aSmrgSmcErrorHandler _SmcErrorHandler = _SmcDefaultErrorHandler; 49d656433aSmrgSmsErrorHandler _SmsErrorHandler = _SmsDefaultErrorHandler; 50d656433aSmrg 51d656433aSmrg 52d656433aSmrgstatic void 53d656433aSmrgset_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks); 54126a8a12Smrg 55126a8a12Smrg 56126a8a12SmrgSmcConn 57d656433aSmrgSmcOpenConnection(char *networkIdsList, SmPointer context, 58d656433aSmrg int xsmpMajorRev, int xsmpMinorRev, 59d656433aSmrg unsigned long mask, SmcCallbacks *callbacks, 60d656433aSmrg char *previousId, char **clientIdRet, 61d656433aSmrg int errorLength, char *errorStringRet) 62126a8a12Smrg{ 63126a8a12Smrg SmcConn smcConn; 64126a8a12Smrg IceConn iceConn; 65126a8a12Smrg char *ids; 66126a8a12Smrg IceProtocolSetupStatus setupstat; 67126a8a12Smrg int majorVersion; 68126a8a12Smrg int minorVersion; 69126a8a12Smrg char *vendor = NULL; 70126a8a12Smrg char *release = NULL; 71126a8a12Smrg smRegisterClientMsg *pMsg; 72126a8a12Smrg char *pData; 73126a8a12Smrg int extra, len; 74126a8a12Smrg IceReplyWaitInfo replyWait; 75126a8a12Smrg _SmcRegisterClientReply reply; 76126a8a12Smrg Bool gotReply, ioErrorOccured; 77126a8a12Smrg 78126a8a12Smrg const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"}; 79126a8a12Smrg IcePoAuthProc auth_procs[] = {_IcePoMagicCookie1Proc}; 80126a8a12Smrg int auth_count = 1; 81126a8a12Smrg 82126a8a12Smrg IcePoVersionRec versions[] = { 83126a8a12Smrg {SmProtoMajor, SmProtoMinor, _SmcProcessMessage} 84126a8a12Smrg }; 85126a8a12Smrg int version_count = 1; 86126a8a12Smrg 87126a8a12Smrg 88126a8a12Smrg *clientIdRet = NULL; 89126a8a12Smrg 90126a8a12Smrg if (errorStringRet && errorLength > 0) 91126a8a12Smrg *errorStringRet = '\0'; 92126a8a12Smrg 93126a8a12Smrg if (!_SmcOpcode) 94126a8a12Smrg { 95126a8a12Smrg /* 96126a8a12Smrg * For now, there is only one version of XSMP, so we don't 97126a8a12Smrg * have to check {xsmpMajorRev, xsmpMinorRev}. In the future, 98126a8a12Smrg * we will check against versions and generate the list 99126a8a12Smrg * of versions the application actually supports. 100126a8a12Smrg */ 101126a8a12Smrg 102126a8a12Smrg if ((_SmcOpcode = IceRegisterForProtocolSetup ("XSMP", 103126a8a12Smrg SmVendorString, SmReleaseString, version_count, versions, 104126a8a12Smrg auth_count, auth_names, auth_procs, NULL)) < 0) 105126a8a12Smrg { 106126a8a12Smrg if (errorStringRet && errorLength > 0) { 107126a8a12Smrg strncpy (errorStringRet, 108126a8a12Smrg "Could not register XSMP protocol with ICE", 109126a8a12Smrg errorLength); 110126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 111126a8a12Smrg } 112126a8a12Smrg 113126a8a12Smrg return (NULL); 114126a8a12Smrg } 115126a8a12Smrg } 116126a8a12Smrg 117126a8a12Smrg if (networkIdsList == NULL || *networkIdsList == '\0') 118126a8a12Smrg { 119126a8a12Smrg if ((ids = (char *) getenv ("SESSION_MANAGER")) == NULL) 120126a8a12Smrg { 121126a8a12Smrg if (errorStringRet && errorLength > 0) { 122126a8a12Smrg strncpy (errorStringRet, 123126a8a12Smrg "SESSION_MANAGER environment variable not defined", 124126a8a12Smrg errorLength); 125126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 126126a8a12Smrg } 127126a8a12Smrg return (NULL); 128126a8a12Smrg } 129126a8a12Smrg } 130126a8a12Smrg else 131126a8a12Smrg { 132126a8a12Smrg ids = networkIdsList; 133126a8a12Smrg } 134126a8a12Smrg 135126a8a12Smrg if ((iceConn = IceOpenConnection ( 136126a8a12Smrg ids, context, 0, _SmcOpcode, errorLength, errorStringRet)) == NULL) 137126a8a12Smrg { 138126a8a12Smrg return (NULL); 139126a8a12Smrg } 140126a8a12Smrg 141126a8a12Smrg if ((smcConn = (SmcConn) malloc (sizeof (struct _SmcConn))) == NULL) 142126a8a12Smrg { 143126a8a12Smrg if (errorStringRet && errorLength > 0) { 144126a8a12Smrg strncpy (errorStringRet, "Can't malloc", errorLength); 145126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 146126a8a12Smrg } 147126a8a12Smrg IceCloseConnection (iceConn); 148126a8a12Smrg return (NULL); 149126a8a12Smrg } 150126a8a12Smrg 151126a8a12Smrg setupstat = IceProtocolSetup (iceConn, _SmcOpcode, 152126a8a12Smrg (IcePointer) smcConn, 153126a8a12Smrg False /* mustAuthenticate */, 154126a8a12Smrg &majorVersion, &minorVersion, 155126a8a12Smrg &vendor, &release, errorLength, errorStringRet); 156126a8a12Smrg 157126a8a12Smrg if (setupstat == IceProtocolSetupFailure || 158126a8a12Smrg setupstat == IceProtocolSetupIOError) 159126a8a12Smrg { 160126a8a12Smrg IceCloseConnection (iceConn); 161126a8a12Smrg free ((char *) smcConn); 162126a8a12Smrg return (NULL); 163126a8a12Smrg } 164126a8a12Smrg else if (setupstat == IceProtocolAlreadyActive) 165126a8a12Smrg { 166126a8a12Smrg /* 167126a8a12Smrg * This case should never happen, because when we called 168126a8a12Smrg * IceOpenConnection, we required that the ICE connection 169126a8a12Smrg * may not already have XSMP active on it. 170126a8a12Smrg */ 171126a8a12Smrg 172126a8a12Smrg free ((char *) smcConn); 173126a8a12Smrg if (errorStringRet && errorLength > 0) { 174126a8a12Smrg strncpy (errorStringRet, "Internal error in IceOpenConnection", 175126a8a12Smrg errorLength); 176126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 177126a8a12Smrg } 178126a8a12Smrg return (NULL); 179126a8a12Smrg } 180126a8a12Smrg 181126a8a12Smrg smcConn->iceConn = iceConn; 182126a8a12Smrg smcConn->proto_major_version = majorVersion; 183126a8a12Smrg smcConn->proto_minor_version = minorVersion; 184126a8a12Smrg smcConn->vendor = vendor; 185126a8a12Smrg smcConn->release = release; 186126a8a12Smrg smcConn->client_id = NULL; 187126a8a12Smrg 188126a8a12Smrg bzero ((char *) &smcConn->callbacks, sizeof (SmcCallbacks)); 189126a8a12Smrg set_callbacks (smcConn, mask, callbacks); 190126a8a12Smrg 191126a8a12Smrg smcConn->interact_waits = NULL; 192126a8a12Smrg smcConn->phase2_wait = NULL; 193126a8a12Smrg smcConn->prop_reply_waits = NULL; 194126a8a12Smrg 195126a8a12Smrg smcConn->save_yourself_in_progress = False; 196126a8a12Smrg smcConn->shutdown_in_progress = False; 197126a8a12Smrg 198126a8a12Smrg 199126a8a12Smrg /* 200126a8a12Smrg * Now register the client 201126a8a12Smrg */ 202126a8a12Smrg 203d656433aSmrg if (!previousId) 204d656433aSmrg previousId = ""; 205d656433aSmrg len = strlen (previousId); 206126a8a12Smrg extra = ARRAY8_BYTES (len); 207126a8a12Smrg 208126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient, 209126a8a12Smrg SIZEOF (smRegisterClientMsg), WORD64COUNT (extra), 210126a8a12Smrg smRegisterClientMsg, pMsg, pData); 211126a8a12Smrg 212126a8a12Smrg STORE_ARRAY8 (pData, len, previousId); 213126a8a12Smrg 214126a8a12Smrg IceFlush (iceConn); 215126a8a12Smrg 216126a8a12Smrg replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn); 217126a8a12Smrg replyWait.major_opcode_of_request = _SmcOpcode; 218126a8a12Smrg replyWait.minor_opcode_of_request = SM_RegisterClient; 219126a8a12Smrg replyWait.reply = (IcePointer) &reply; 220126a8a12Smrg 221126a8a12Smrg gotReply = False; 222126a8a12Smrg ioErrorOccured = False; 223126a8a12Smrg 224126a8a12Smrg while (!gotReply && !ioErrorOccured) 225126a8a12Smrg { 226126a8a12Smrg ioErrorOccured = (IceProcessMessages ( 227126a8a12Smrg iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 228126a8a12Smrg 229126a8a12Smrg if (ioErrorOccured) 230126a8a12Smrg { 231126a8a12Smrg if (errorStringRet && errorLength > 0) { 232126a8a12Smrg strncpy (errorStringRet, "IO error occured opening connection", 233126a8a12Smrg errorLength); 234126a8a12Smrg errorStringRet[errorLength - 1] = '\0'; 235126a8a12Smrg } 236126a8a12Smrg free (smcConn->vendor); 237126a8a12Smrg free (smcConn->release); 238126a8a12Smrg free ((char *) smcConn); 239126a8a12Smrg 240126a8a12Smrg return (NULL); 241126a8a12Smrg } 242126a8a12Smrg else if (gotReply) 243126a8a12Smrg { 244126a8a12Smrg if (reply.status == 1) 245126a8a12Smrg { 246126a8a12Smrg /* 247126a8a12Smrg * The client successfully registered. 248126a8a12Smrg */ 249126a8a12Smrg 250126a8a12Smrg *clientIdRet = reply.client_id; 251126a8a12Smrg 252126a8a12Smrg smcConn->client_id = (char *) malloc ( 253126a8a12Smrg strlen (*clientIdRet) + 1); 254126a8a12Smrg 255126a8a12Smrg strcpy (smcConn->client_id, *clientIdRet); 256126a8a12Smrg } 257126a8a12Smrg else 258126a8a12Smrg { 259126a8a12Smrg /* 260126a8a12Smrg * Could not register the client because the previous ID 261126a8a12Smrg * was bad. So now we register the client with the 262126a8a12Smrg * previous ID set to NULL. 263126a8a12Smrg */ 264126a8a12Smrg 265126a8a12Smrg extra = ARRAY8_BYTES (0); 266126a8a12Smrg 267126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient, 268126a8a12Smrg SIZEOF (smRegisterClientMsg), WORD64COUNT (extra), 269126a8a12Smrg smRegisterClientMsg, pMsg, pData); 270126a8a12Smrg 271d656433aSmrg STORE_ARRAY8 (pData, 0, ""); 272126a8a12Smrg 273126a8a12Smrg IceFlush (iceConn); 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 307126a8a12Smrg STORE_CARD32 (pData, count); 308126a8a12Smrg pData += 4; 309126a8a12Smrg 310126a8a12Smrg for (i = 0; i < count; i++) 311126a8a12Smrg STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]); 312126a8a12Smrg 313126a8a12Smrg IceFlush (iceConn); 314126a8a12Smrg 315126a8a12Smrg IceProtocolShutdown (iceConn, _SmcOpcode); 316126a8a12Smrg IceSetShutdownNegotiation (iceConn, False); 317126a8a12Smrg closeStatus = IceCloseConnection (iceConn); 318126a8a12Smrg 319126a8a12Smrg if (smcConn->vendor) 320126a8a12Smrg free (smcConn->vendor); 321126a8a12Smrg 322126a8a12Smrg if (smcConn->release) 323126a8a12Smrg free (smcConn->release); 324126a8a12Smrg 325126a8a12Smrg if (smcConn->client_id) 326126a8a12Smrg free (smcConn->client_id); 327126a8a12Smrg 328126a8a12Smrg if (smcConn->prop_reply_waits) 329126a8a12Smrg { 330126a8a12Smrg _SmcPropReplyWait *ptr = smcConn->prop_reply_waits; 331126a8a12Smrg _SmcPropReplyWait *next; 332126a8a12Smrg 333126a8a12Smrg while (ptr) 334126a8a12Smrg { 335126a8a12Smrg next = ptr->next; 336126a8a12Smrg free ((char *) ptr); 337126a8a12Smrg ptr = next; 338126a8a12Smrg } 339126a8a12Smrg 340126a8a12Smrg } 341126a8a12Smrg 342126a8a12Smrg free ((char *) smcConn); 343126a8a12Smrg 344126a8a12Smrg if (closeStatus == IceClosedNow) 345126a8a12Smrg statusRet = SmcClosedNow; 346126a8a12Smrg else if (closeStatus == IceClosedASAP) 347126a8a12Smrg statusRet = SmcClosedASAP; 348126a8a12Smrg else 349126a8a12Smrg statusRet = SmcConnectionInUse; 350126a8a12Smrg 351126a8a12Smrg return (statusRet); 352126a8a12Smrg} 353126a8a12Smrg 354126a8a12Smrg 355126a8a12Smrg 356126a8a12Smrgvoid 357d656433aSmrgSmcModifyCallbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks) 358126a8a12Smrg{ 359126a8a12Smrg set_callbacks (smcConn, mask, callbacks); 360126a8a12Smrg} 361126a8a12Smrg 362126a8a12Smrg 363126a8a12Smrg 364126a8a12Smrgvoid 365d656433aSmrgSmcSetProperties(SmcConn smcConn, int numProps, SmProp **props) 366126a8a12Smrg{ 367126a8a12Smrg IceConn iceConn = smcConn->iceConn; 368126a8a12Smrg smSetPropertiesMsg *pMsg; 369126a8a12Smrg char *pBuf; 370126a8a12Smrg char *pStart; 371126a8a12Smrg int bytes; 372126a8a12Smrg 373126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties, 374126a8a12Smrg SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg); 375126a8a12Smrg 376126a8a12Smrg LISTOF_PROP_BYTES (numProps, props, bytes); 377126a8a12Smrg pMsg->length += WORD64COUNT (bytes); 378126a8a12Smrg 379126a8a12Smrg pBuf = pStart = IceAllocScratch (iceConn, bytes); 380d656433aSmrg memset(pStart, 0, bytes); 381126a8a12Smrg 382126a8a12Smrg STORE_LISTOF_PROPERTY (pBuf, numProps, props); 383126a8a12Smrg 384126a8a12Smrg IceWriteData (iceConn, bytes, pStart); 385126a8a12Smrg IceFlush (iceConn); 386126a8a12Smrg} 387126a8a12Smrg 388126a8a12Smrg 389126a8a12Smrg 390126a8a12Smrgvoid 391d656433aSmrgSmcDeleteProperties(SmcConn smcConn, int numProps, char **propNames) 392126a8a12Smrg{ 393126a8a12Smrg IceConn iceConn = smcConn->iceConn; 394126a8a12Smrg smDeletePropertiesMsg *pMsg; 395126a8a12Smrg char *pData; 396126a8a12Smrg int extra, i; 397126a8a12Smrg 398126a8a12Smrg extra = 8; 399126a8a12Smrg 400126a8a12Smrg for (i = 0; i < numProps; i++) 401126a8a12Smrg extra += ARRAY8_BYTES (strlen (propNames[i])); 402126a8a12Smrg 403126a8a12Smrg IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties, 404126a8a12Smrg SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra), 405126a8a12Smrg smDeletePropertiesMsg, pMsg, pData); 406126a8a12Smrg 407126a8a12Smrg STORE_CARD32 (pData, numProps); 408126a8a12Smrg pData += 4; 409126a8a12Smrg 410126a8a12Smrg for (i = 0; i < numProps; i++) 411126a8a12Smrg STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]); 412126a8a12Smrg 413126a8a12Smrg IceFlush (iceConn); 414126a8a12Smrg} 415126a8a12Smrg 416126a8a12Smrg 417126a8a12Smrg 418126a8a12SmrgStatus 419d656433aSmrgSmcGetProperties(SmcConn smcConn, SmcPropReplyProc propReplyProc, 420d656433aSmrg SmPointer clientData) 421126a8a12Smrg{ 422126a8a12Smrg IceConn iceConn = smcConn->iceConn; 423126a8a12Smrg _SmcPropReplyWait *wait, *ptr; 424126a8a12Smrg 425126a8a12Smrg if ((wait = (_SmcPropReplyWait *) malloc ( 426126a8a12Smrg sizeof (_SmcPropReplyWait))) == NULL) 427126a8a12Smrg { 428126a8a12Smrg return (0); 429126a8a12Smrg } 430126a8a12Smrg 431126a8a12Smrg wait->prop_reply_proc = propReplyProc; 432126a8a12Smrg wait->client_data = clientData; 433126a8a12Smrg wait->next = NULL; 434126a8a12Smrg 435126a8a12Smrg ptr = smcConn->prop_reply_waits; 436126a8a12Smrg while (ptr && ptr->next) 437126a8a12Smrg ptr = ptr->next; 438126a8a12Smrg 439126a8a12Smrg if (ptr == NULL) 440126a8a12Smrg smcConn->prop_reply_waits = wait; 441126a8a12Smrg else 442126a8a12Smrg ptr->next = wait; 443126a8a12Smrg 444126a8a12Smrg IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties); 445126a8a12Smrg IceFlush (iceConn); 446126a8a12Smrg 447126a8a12Smrg return (1); 448126a8a12Smrg} 449126a8a12Smrg 450126a8a12Smrg 451126a8a12Smrg 452126a8a12SmrgStatus 453d656433aSmrgSmcInteractRequest(SmcConn smcConn, int dialogType, 454d656433aSmrg SmcInteractProc interactProc, SmPointer clientData) 455126a8a12Smrg{ 456126a8a12Smrg IceConn iceConn = smcConn->iceConn; 457126a8a12Smrg smInteractRequestMsg *pMsg; 458126a8a12Smrg _SmcInteractWait *wait, *ptr; 459126a8a12Smrg 460126a8a12Smrg if ((wait = (_SmcInteractWait *) malloc ( 461126a8a12Smrg sizeof (_SmcInteractWait))) == NULL) 462126a8a12Smrg { 463126a8a12Smrg return (0); 464126a8a12Smrg } 465126a8a12Smrg 466126a8a12Smrg wait->interact_proc = interactProc; 467126a8a12Smrg wait->client_data = clientData; 468126a8a12Smrg wait->next = NULL; 469126a8a12Smrg 470126a8a12Smrg ptr = smcConn->interact_waits; 471126a8a12Smrg while (ptr && ptr->next) 472126a8a12Smrg ptr = ptr->next; 473126a8a12Smrg 474126a8a12Smrg if (ptr == NULL) 475126a8a12Smrg smcConn->interact_waits = wait; 476126a8a12Smrg else 477126a8a12Smrg ptr->next = wait; 478126a8a12Smrg 479126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest, 480126a8a12Smrg SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg); 481126a8a12Smrg 482126a8a12Smrg pMsg->dialogType = dialogType; 483126a8a12Smrg 484126a8a12Smrg IceFlush (iceConn); 485126a8a12Smrg 486126a8a12Smrg return (1); 487126a8a12Smrg} 488126a8a12Smrg 489126a8a12Smrg 490126a8a12Smrg 491126a8a12Smrgvoid 492d656433aSmrgSmcInteractDone(SmcConn smcConn, Bool cancelShutdown) 493126a8a12Smrg{ 494126a8a12Smrg IceConn iceConn = smcConn->iceConn; 495126a8a12Smrg smInteractDoneMsg *pMsg; 496126a8a12Smrg 497126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone, 498126a8a12Smrg SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg); 499126a8a12Smrg 500126a8a12Smrg pMsg->cancelShutdown = cancelShutdown; 501126a8a12Smrg 502126a8a12Smrg IceFlush (iceConn); 503126a8a12Smrg} 504126a8a12Smrg 505126a8a12Smrg 506126a8a12Smrg 507126a8a12Smrgvoid 508d656433aSmrgSmcRequestSaveYourself(SmcConn smcConn, int saveType, Bool shutdown, 509d656433aSmrg int interactStyle, Bool fast, Bool global) 510126a8a12Smrg{ 511126a8a12Smrg IceConn iceConn = smcConn->iceConn; 512126a8a12Smrg smSaveYourselfRequestMsg *pMsg; 513126a8a12Smrg 514126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest, 515126a8a12Smrg SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg); 516126a8a12Smrg 517126a8a12Smrg pMsg->saveType = saveType; 518126a8a12Smrg pMsg->shutdown = shutdown; 519126a8a12Smrg pMsg->interactStyle = interactStyle; 520126a8a12Smrg pMsg->fast = fast; 521126a8a12Smrg pMsg->global = global; 522126a8a12Smrg 523126a8a12Smrg IceFlush (iceConn); 524126a8a12Smrg} 525126a8a12Smrg 526126a8a12Smrg 527126a8a12Smrg 528126a8a12SmrgStatus 529d656433aSmrgSmcRequestSaveYourselfPhase2(SmcConn smcConn, 530d656433aSmrg SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc, 531d656433aSmrg SmPointer clientData) 532126a8a12Smrg{ 533126a8a12Smrg IceConn iceConn = smcConn->iceConn; 534126a8a12Smrg _SmcPhase2Wait *wait; 535126a8a12Smrg 536126a8a12Smrg if (smcConn->phase2_wait) 537126a8a12Smrg wait = smcConn->phase2_wait; 538126a8a12Smrg else 539126a8a12Smrg { 540126a8a12Smrg if ((wait = (_SmcPhase2Wait *) malloc ( 541126a8a12Smrg sizeof (_SmcPhase2Wait))) == NULL) 542126a8a12Smrg { 543126a8a12Smrg return (0); 544126a8a12Smrg } 545126a8a12Smrg } 546126a8a12Smrg 547126a8a12Smrg wait->phase2_proc = saveYourselfPhase2Proc; 548126a8a12Smrg wait->client_data = clientData; 549126a8a12Smrg 550126a8a12Smrg smcConn->phase2_wait = wait; 551126a8a12Smrg 552126a8a12Smrg IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request); 553126a8a12Smrg IceFlush (iceConn); 554126a8a12Smrg 555126a8a12Smrg return (1); 556126a8a12Smrg} 557126a8a12Smrg 558126a8a12Smrg 559126a8a12Smrg 560126a8a12Smrgvoid 561d656433aSmrgSmcSaveYourselfDone(SmcConn smcConn, Bool success) 562126a8a12Smrg{ 563126a8a12Smrg IceConn iceConn = smcConn->iceConn; 564126a8a12Smrg smSaveYourselfDoneMsg *pMsg; 565126a8a12Smrg 566126a8a12Smrg IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone, 567126a8a12Smrg SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg); 568126a8a12Smrg 569126a8a12Smrg pMsg->success = success; 570126a8a12Smrg 571126a8a12Smrg IceFlush (iceConn); 572126a8a12Smrg} 573126a8a12Smrg 574126a8a12Smrg 575126a8a12Smrg 576126a8a12Smrgstatic void 577d656433aSmrgset_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks) 578126a8a12Smrg{ 579126a8a12Smrg if (mask & SmcSaveYourselfProcMask) 580126a8a12Smrg { 581126a8a12Smrg smcConn->callbacks.save_yourself.callback = 582126a8a12Smrg callbacks->save_yourself.callback; 583126a8a12Smrg smcConn->callbacks.save_yourself.client_data = 584126a8a12Smrg callbacks->save_yourself.client_data; 585126a8a12Smrg } 586126a8a12Smrg 587126a8a12Smrg if (mask & SmcDieProcMask) 588126a8a12Smrg { 589126a8a12Smrg smcConn->callbacks.die.callback = callbacks->die.callback; 590126a8a12Smrg smcConn->callbacks.die.client_data = callbacks->die.client_data; 591126a8a12Smrg } 592126a8a12Smrg 593126a8a12Smrg if (mask & SmcSaveCompleteProcMask) 594126a8a12Smrg { 595126a8a12Smrg smcConn->callbacks.save_complete.callback = 596126a8a12Smrg callbacks->save_complete.callback; 597126a8a12Smrg smcConn->callbacks.save_complete.client_data = 598126a8a12Smrg callbacks->save_complete.client_data; 599126a8a12Smrg } 600126a8a12Smrg 601126a8a12Smrg if (mask & SmcShutdownCancelledProcMask) 602126a8a12Smrg { 603126a8a12Smrg smcConn->callbacks.shutdown_cancelled.callback = 604126a8a12Smrg callbacks->shutdown_cancelled.callback; 605126a8a12Smrg smcConn->callbacks.shutdown_cancelled.client_data = 606126a8a12Smrg callbacks->shutdown_cancelled.client_data; 607126a8a12Smrg } 608126a8a12Smrg} 609