sm_manager.c revision 3fb97780
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 38#ifdef __UNIXWARE__ 39#undef shutdown 40#endif 41 42 43 44static Status 45_SmsProtocolSetupProc (IceConn iceConn, 46 int majorVersion, 47 int minorVersion, 48 char *vendor, 49 char *release, 50 IcePointer *clientDataRet, 51 char **failureReasonRet) 52{ 53 SmsConn smsConn; 54 unsigned long mask; 55 Status status; 56 57 /* 58 * vendor/release are undefined for ProtocolSetup in XSMP. 59 */ 60 61 if (vendor) 62 free (vendor); 63 if (release) 64 free (release); 65 66 67 /* 68 * Allocate new SmsConn. 69 */ 70 71 if ((smsConn = malloc (sizeof (struct _SmsConn))) == NULL) 72 { 73 const char *str = "Memory allocation failed"; 74 75 *failureReasonRet = strdup (str); 76 77 return (0); 78 } 79 80 smsConn->iceConn = iceConn; 81 smsConn->proto_major_version = majorVersion; 82 smsConn->proto_minor_version = minorVersion; 83 smsConn->client_id = NULL; 84 85 smsConn->save_yourself_in_progress = False; 86 smsConn->interaction_allowed = SmInteractStyleNone; 87 smsConn->can_cancel_shutdown = False; 88 smsConn->interact_in_progress = False; 89 90 *clientDataRet = (IcePointer) smsConn; 91 92 93 /* 94 * Now give the session manager the new smsConn and get back the 95 * callbacks to invoke when messages arrive from the client. 96 * 97 * In the future, we can use the mask return value to check 98 * if the SM is expecting an older rev of SMlib. 99 */ 100 101 bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks)); 102 103 status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData, 104 &mask, &smsConn->callbacks, failureReasonRet); 105 106 return (status); 107} 108 109 110 111 112Status 113SmsInitialize(const char *vendor, const char *release, 114 SmsNewClientProc newClientProc, 115 SmPointer managerData, IceHostBasedAuthProc hostBasedAuthProc, 116 int errorLength, char *errorStringRet) 117{ 118 const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"}; 119 IcePaAuthProc auth_procs[] = {_IcePaMagicCookie1Proc}; 120 int auth_count = 1; 121 122 IcePaVersionRec versions[] = { 123 {SmProtoMajor, SmProtoMinor, _SmsProcessMessage} 124 }; 125 int version_count = 1; 126 127 if (errorStringRet && errorLength > 0) 128 *errorStringRet = '\0'; 129 130 if (!newClientProc) 131 { 132 if (errorStringRet && errorLength > 0) { 133 strncpy (errorStringRet, 134 "The SmsNewClientProc callback can't be NULL", 135 errorLength); 136 errorStringRet[errorLength - 1] = '\0'; 137 } 138 139 return (0); 140 } 141 142 if (!_SmsOpcode) 143 { 144 145 if ((_SmsOpcode = IceRegisterForProtocolReply ("XSMP", 146 vendor, release, version_count, versions, 147 auth_count, auth_names, auth_procs, hostBasedAuthProc, 148 _SmsProtocolSetupProc, 149 NULL, /* IceProtocolActivateProc - we don't care about 150 when the Protocol Reply is sent, because the 151 session manager can not immediately send a 152 message - it must wait for RegisterClient. */ 153 NULL /* IceIOErrorProc */ 154 )) < 0) 155 { 156 if (errorStringRet && errorLength > 0) { 157 strncpy (errorStringRet, 158 "Could not register XSMP protocol with ICE", 159 errorLength); 160 errorStringRet[errorLength - 1] = '\0'; 161 } 162 return (0); 163 } 164 } 165 166 _SmsNewClientProc = newClientProc; 167 _SmsNewClientData = managerData; 168 169 return (1); 170} 171 172 173 174char * 175SmsClientHostName(SmsConn smsConn) 176{ 177 return (IceGetPeerName (smsConn->iceConn)); 178} 179 180 181 182Status 183SmsRegisterClientReply(SmsConn smsConn, char *clientId) 184{ 185 IceConn iceConn = smsConn->iceConn; 186 size_t extra; 187 smRegisterClientReplyMsg *pMsg; 188 char *pData; 189 190 if ((smsConn->client_id = strdup (clientId)) == NULL) 191 { 192 return (0); 193 } 194 195 extra = ARRAY8_BYTES (strlen (clientId)); 196 197 IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply, 198 SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra), 199 smRegisterClientReplyMsg, pMsg, pData); 200 201 if (pData != NULL) { 202 STORE_ARRAY8 (pData, strlen (clientId), clientId); 203 IceFlush (iceConn); 204 } 205 else { 206 SEND_ARRAY8 (iceConn, strlen (clientId), clientId); 207 } 208 209 return (1); 210} 211 212 213 214void 215SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown, 216 int interactStyle, Bool fast) 217{ 218 IceConn iceConn = smsConn->iceConn; 219 smSaveYourselfMsg *pMsg; 220 221 IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself, 222 SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg); 223 224 pMsg->saveType = saveType; 225 pMsg->shutdown = shutdown; 226 pMsg->interactStyle = interactStyle; 227 pMsg->fast = fast; 228 229 IceFlush (iceConn); 230 231 smsConn->save_yourself_in_progress = True; 232 233 if (interactStyle == SmInteractStyleNone || 234 interactStyle == SmInteractStyleErrors || 235 interactStyle == SmInteractStyleAny) 236 { 237 smsConn->interaction_allowed = interactStyle; 238 } 239 else 240 { 241 smsConn->interaction_allowed = SmInteractStyleNone; 242 } 243 244 smsConn->can_cancel_shutdown = shutdown && 245 (interactStyle == SmInteractStyleAny || 246 interactStyle == SmInteractStyleErrors); 247} 248 249 250 251void 252SmsSaveYourselfPhase2(SmsConn smsConn) 253{ 254 IceConn iceConn = smsConn->iceConn; 255 256 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2); 257 IceFlush (iceConn); 258} 259 260 261 262void 263SmsInteract(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 275void 276SmsDie(SmsConn smsConn) 277{ 278 IceConn iceConn = smsConn->iceConn; 279 280 IceSimpleMessage (iceConn, _SmsOpcode, SM_Die); 281 IceFlush (iceConn); 282} 283 284 285 286void 287SmsSaveComplete(SmsConn smsConn) 288{ 289 IceConn iceConn = smsConn->iceConn; 290 291 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete); 292 IceFlush (iceConn); 293} 294 295 296 297void 298SmsShutdownCancelled(SmsConn smsConn) 299{ 300 IceConn iceConn = smsConn->iceConn; 301 302 IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled); 303 IceFlush (iceConn); 304 305 smsConn->can_cancel_shutdown = False; 306} 307 308 309 310void 311SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props) 312{ 313 IceConn iceConn = smsConn->iceConn; 314 unsigned int bytes; 315 smPropertiesReplyMsg *pMsg; 316 char *pBuf; 317 char *pStart; 318 319 IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply, 320 SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg); 321 322 LISTOF_PROP_BYTES (numProps, props, bytes); 323 pMsg->length += WORD64COUNT (bytes); 324 325 pBuf = pStart = IceAllocScratch (iceConn, bytes); 326 327 STORE_LISTOF_PROPERTY (pBuf, numProps, props); 328 329 IceWriteData (iceConn, bytes, pStart); 330 IceFlush (iceConn); 331} 332 333 334 335void 336SmsCleanUp(SmsConn smsConn) 337{ 338 IceProtocolShutdown (smsConn->iceConn, _SmsOpcode); 339 340 if (smsConn->client_id) 341 free (smsConn->client_id); 342 343 free (smsConn); 344} 345