1/* 2 3Copyright 1993, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27/* 28 * Author: Ralph Mor, X Consortium 29 */ 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34#include <X11/SM/SMlib.h> 35#include "SMlibint.h" 36#include <X11/Xtrans/Xtrans.h> 37 38static Status 39_SmsProtocolSetupProc (IceConn iceConn, 40 int majorVersion, 41 int minorVersion, 42 char *vendor, 43 char *release, 44 IcePointer *clientDataRet, 45 char **failureReasonRet) 46{ 47 SmsConn smsConn; 48 unsigned long mask; 49 Status status; 50 51 /* 52 * vendor/release are undefined for ProtocolSetup in XSMP. 53 */ 54 55 if (vendor) 56 free (vendor); 57 if (release) 58 free (release); 59 60 61 /* 62 * Allocate new SmsConn. 63 */ 64 65 if ((smsConn = malloc (sizeof (struct _SmsConn))) == NULL) 66 { 67 const char *str = "Memory allocation failed"; 68 69 *failureReasonRet = strdup (str); 70 71 return (0); 72 } 73 74 smsConn->iceConn = iceConn; 75 smsConn->proto_major_version = majorVersion; 76 smsConn->proto_minor_version = minorVersion; 77 smsConn->client_id = NULL; 78 79 smsConn->save_yourself_in_progress = False; 80 smsConn->interaction_allowed = SmInteractStyleNone; 81 smsConn->can_cancel_shutdown = False; 82 smsConn->interact_in_progress = False; 83 84 *clientDataRet = (IcePointer) smsConn; 85 86 87 /* 88 * Now give the session manager the new smsConn and get back the 89 * callbacks to invoke when messages arrive from the client. 90 * 91 * In the future, we can use the mask return value to check 92 * if the SM is expecting an older rev of SMlib. 93 */ 94 95 bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks)); 96 97 status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData, 98 &mask, &smsConn->callbacks, failureReasonRet); 99 100 return (status); 101} 102 103 104 105 106Status 107SmsInitialize(const char *vendor, const char *release, 108 SmsNewClientProc newClientProc, 109 SmPointer managerData, IceHostBasedAuthProc hostBasedAuthProc, 110 int errorLength, char *errorStringRet) 111{ 112 const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"}; 113 IcePaAuthProc auth_procs[] = {_IcePaMagicCookie1Proc}; 114 int auth_count = 1; 115 116 IcePaVersionRec versions[] = { 117 {SmProtoMajor, SmProtoMinor, _SmsProcessMessage} 118 }; 119 int version_count = 1; 120 121 if (errorStringRet && errorLength > 0) 122 *errorStringRet = '\0'; 123 124 if (!newClientProc) 125 { 126 if (errorStringRet && errorLength > 0) { 127 strncpy (errorStringRet, 128 "The SmsNewClientProc callback can't be NULL", 129 errorLength); 130 errorStringRet[errorLength - 1] = '\0'; 131 } 132 133 return (0); 134 } 135 136 if (!_SmsOpcode) 137 { 138 139 if ((_SmsOpcode = IceRegisterForProtocolReply ("XSMP", 140 vendor, release, version_count, versions, 141 auth_count, auth_names, auth_procs, hostBasedAuthProc, 142 _SmsProtocolSetupProc, 143 NULL, /* IceProtocolActivateProc - we don't care about 144 when the Protocol Reply is sent, because the 145 session manager can not immediately send a 146 message - it must wait for RegisterClient. */ 147 NULL /* IceIOErrorProc */ 148 )) < 0) 149 { 150 if (errorStringRet && errorLength > 0) { 151 strncpy (errorStringRet, 152 "Could not register XSMP protocol with ICE", 153 errorLength); 154 errorStringRet[errorLength - 1] = '\0'; 155 } 156 return (0); 157 } 158 } 159 160 _SmsNewClientProc = newClientProc; 161 _SmsNewClientData = managerData; 162 163 return (1); 164} 165 166 167 168char * 169SmsClientHostName(SmsConn smsConn) 170{ 171 return (IceGetPeerName (smsConn->iceConn)); 172} 173 174 175 176Status 177SmsRegisterClientReply(SmsConn smsConn, char *clientId) 178{ 179 IceConn iceConn = smsConn->iceConn; 180 size_t extra; 181 smRegisterClientReplyMsg *pMsg; 182 char *pData; 183 184 if ((smsConn->client_id = strdup (clientId)) == NULL) 185 { 186 return (0); 187 } 188 189 extra = ARRAY8_BYTES (strlen (clientId)); 190 191 IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply, 192 SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra), 193 smRegisterClientReplyMsg, pMsg, pData); 194 195 if (pData != NULL) { 196 STORE_ARRAY8 (pData, strlen (clientId), clientId); 197 IceFlush (iceConn); 198 } 199 else { 200 SEND_ARRAY8 (iceConn, strlen (clientId), clientId); 201 } 202 203 return (1); 204} 205 206 207 208void 209SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown, 210 int interactStyle, Bool fast) 211{ 212 IceConn iceConn = smsConn->iceConn; 213 smSaveYourselfMsg *pMsg; 214 215 IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself, 216 SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg); 217 218 pMsg->saveType = saveType; 219 pMsg->shutdown = shutdown; 220 pMsg->interactStyle = interactStyle; 221 pMsg->fast = fast; 222 223 IceFlush (iceConn); 224 225 smsConn->save_yourself_in_progress = True; 226 227 if (interactStyle == SmInteractStyleNone || 228 interactStyle == SmInteractStyleErrors || 229 interactStyle == SmInteractStyleAny) 230 { 231 smsConn->interaction_allowed = interactStyle; 232 } 233 else 234 { 235 smsConn->interaction_allowed = SmInteractStyleNone; 236 } 237 238 smsConn->can_cancel_shutdown = shutdown && 239 (interactStyle == SmInteractStyleAny || 240 interactStyle == SmInteractStyleErrors); 241} 242 243 244 245void 246SmsSaveYourselfPhase2(SmsConn smsConn) 247{ 248 IceConn iceConn = smsConn->iceConn; 249 250 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2); 251 IceFlush (iceConn); 252} 253 254 255 256void 257SmsInteract(SmsConn smsConn) 258{ 259 IceConn iceConn = smsConn->iceConn; 260 261 IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact); 262 IceFlush (iceConn); 263 264 smsConn->interact_in_progress = True; 265} 266 267 268 269void 270SmsDie(SmsConn smsConn) 271{ 272 IceConn iceConn = smsConn->iceConn; 273 274 IceSimpleMessage (iceConn, _SmsOpcode, SM_Die); 275 IceFlush (iceConn); 276} 277 278 279 280void 281SmsSaveComplete(SmsConn smsConn) 282{ 283 IceConn iceConn = smsConn->iceConn; 284 285 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete); 286 IceFlush (iceConn); 287} 288 289 290 291void 292SmsShutdownCancelled(SmsConn smsConn) 293{ 294 IceConn iceConn = smsConn->iceConn; 295 296 IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled); 297 IceFlush (iceConn); 298 299 smsConn->can_cancel_shutdown = False; 300} 301 302 303 304void 305SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props) 306{ 307 IceConn iceConn = smsConn->iceConn; 308 unsigned int bytes; 309 smPropertiesReplyMsg *pMsg; 310 char *pBuf; 311 char *pStart; 312 313 IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply, 314 SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg); 315 316 LISTOF_PROP_BYTES (numProps, props, bytes); 317 pMsg->length += WORD64COUNT (bytes); 318 319 pBuf = pStart = IceAllocScratch (iceConn, bytes); 320 321 STORE_LISTOF_PROPERTY (pBuf, numProps, props); 322 323 IceWriteData (iceConn, bytes, pStart); 324 IceFlush (iceConn); 325} 326 327 328 329void 330SmsCleanUp(SmsConn smsConn) 331{ 332 IceProtocolShutdown (smsConn->iceConn, _SmsOpcode); 333 334 if (smsConn->client_id) 335 free (smsConn->client_id); 336 337 free (smsConn); 338} 339