1 /* 2 3 Copyright 1993, 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 */ 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 38 static 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 107 Status 108 SmsInitialize(const char *vendor, const char *release, 109 SmsNewClientProc newClientProc, 110 SmPointer managerData, IceHostBasedAuthProc hostBasedAuthProc, 111 int errorLength, char *errorStringRet) 112 { 113 const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"}; 114 IcePaAuthProc auth_procs[] = {_IcePaMagicCookie1Proc}; 115 int auth_count = 1; 116 117 IcePaVersionRec versions[] = { 118 {SmProtoMajor, SmProtoMinor, _SmsProcessMessage} 119 }; 120 int version_count = 1; 121 122 if (errorStringRet && errorLength > 0) 123 *errorStringRet = '\0'; 124 125 if (!newClientProc) 126 { 127 if (errorStringRet && errorLength > 0) { 128 strncpy (errorStringRet, 129 "The SmsNewClientProc callback can't be NULL", 130 errorLength); 131 errorStringRet[errorLength - 1] = '\0'; 132 } 133 134 return (0); 135 } 136 137 if (!_SmsOpcode) 138 { 139 140 if ((_SmsOpcode = IceRegisterForProtocolReply ("XSMP", 141 vendor, release, version_count, versions, 142 auth_count, auth_names, auth_procs, hostBasedAuthProc, 143 _SmsProtocolSetupProc, 144 NULL, /* IceProtocolActivateProc - we don't care about 145 when the Protocol Reply is sent, because the 146 session manager can not immediately send a 147 message - it must wait for RegisterClient. */ 148 NULL /* IceIOErrorProc */ 149 )) < 0) 150 { 151 if (errorStringRet && errorLength > 0) { 152 strncpy (errorStringRet, 153 "Could not register XSMP protocol with ICE", 154 errorLength); 155 errorStringRet[errorLength - 1] = '\0'; 156 } 157 return (0); 158 } 159 } 160 161 _SmsNewClientProc = newClientProc; 162 _SmsNewClientData = managerData; 163 164 return (1); 165 } 166 167 168 169 char * 171 SmsClientHostName(SmsConn smsConn) 172 { 173 return (IceGetPeerName (smsConn->iceConn)); 174 } 175 176 177 178 Status 180 SmsRegisterClientReply(SmsConn smsConn, char *clientId) 181 { 182 IceConn iceConn = smsConn->iceConn; 183 size_t extra; 184 smRegisterClientReplyMsg *pMsg; 185 char *pData; 186 187 if ((smsConn->client_id = strdup (clientId)) == NULL) 188 { 189 return (0); 190 } 191 192 extra = ARRAY8_BYTES (strlen (clientId)); 193 194 IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply, 195 SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra), 196 smRegisterClientReplyMsg, pMsg, pData); 197 198 if (pData != NULL) { 199 STORE_ARRAY8 (pData, strlen (clientId), clientId); 200 IceFlush (iceConn); 201 } 202 else { 203 SEND_ARRAY8 (iceConn, strlen (clientId), clientId); 204 } 205 206 return (1); 207 } 208 209 210 211 void 213 SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown, 214 int interactStyle, Bool fast) 215 { 216 IceConn iceConn = smsConn->iceConn; 217 smSaveYourselfMsg *pMsg; 218 219 IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself, 220 SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg); 221 222 pMsg->saveType = saveType; 223 pMsg->shutdown = shutdown; 224 pMsg->interactStyle = interactStyle; 225 pMsg->fast = fast; 226 227 IceFlush (iceConn); 228 229 smsConn->save_yourself_in_progress = True; 230 231 if (interactStyle == SmInteractStyleNone || 232 interactStyle == SmInteractStyleErrors || 233 interactStyle == SmInteractStyleAny) 234 { 235 smsConn->interaction_allowed = interactStyle; 236 } 237 else 238 { 239 smsConn->interaction_allowed = SmInteractStyleNone; 240 } 241 242 smsConn->can_cancel_shutdown = shutdown && 243 (interactStyle == SmInteractStyleAny || 244 interactStyle == SmInteractStyleErrors); 245 } 246 247 248 249 void 251 SmsSaveYourselfPhase2(SmsConn smsConn) 252 { 253 IceConn iceConn = smsConn->iceConn; 254 255 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2); 256 IceFlush (iceConn); 257 } 258 259 260 261 void 263 SmsInteract(SmsConn smsConn) 264 { 265 IceConn iceConn = smsConn->iceConn; 266 267 IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact); 268 IceFlush (iceConn); 269 270 smsConn->interact_in_progress = True; 271 } 272 273 274 275 void 277 SmsDie(SmsConn smsConn) 278 { 279 IceConn iceConn = smsConn->iceConn; 280 281 IceSimpleMessage (iceConn, _SmsOpcode, SM_Die); 282 IceFlush (iceConn); 283 } 284 285 286 287 void 289 SmsSaveComplete(SmsConn smsConn) 290 { 291 IceConn iceConn = smsConn->iceConn; 292 293 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete); 294 IceFlush (iceConn); 295 } 296 297 298 299 void 301 SmsShutdownCancelled(SmsConn smsConn) 302 { 303 IceConn iceConn = smsConn->iceConn; 304 305 IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled); 306 IceFlush (iceConn); 307 308 smsConn->can_cancel_shutdown = False; 309 } 310 311 312 313 void 315 SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props) 316 { 317 IceConn iceConn = smsConn->iceConn; 318 unsigned int bytes; 319 smPropertiesReplyMsg *pMsg; 320 char *pBuf; 321 char *pStart; 322 323 IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply, 324 SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg); 325 326 LISTOF_PROP_BYTES (numProps, props, bytes); 327 pMsg->length += WORD64COUNT (bytes); 328 329 pBuf = pStart = IceAllocScratch (iceConn, bytes); 330 331 STORE_LISTOF_PROPERTY (pBuf, numProps, props); 332 333 IceWriteData (iceConn, bytes, pStart); 334 IceFlush (iceConn); 335 } 336 337 338 339 void 341 SmsCleanUp(SmsConn smsConn) 342 { 343 IceProtocolShutdown (smsConn->iceConn, _SmsOpcode); 344 345 if (smsConn->client_id) 346 free (smsConn->client_id); 347 348 free (smsConn); 349 } 350