sm_manager.c revision 555991fd
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 = (SmsConn) malloc (sizeof (struct _SmsConn))) == NULL) 72 { 73 const char *str = "Memory allocation failed"; 74 75 if ((*failureReasonRet = (char *) malloc (strlen (str) + 1)) != NULL) 76 strcpy (*failureReasonRet, str); 77 78 return (0); 79 } 80 81 smsConn->iceConn = iceConn; 82 smsConn->proto_major_version = majorVersion; 83 smsConn->proto_minor_version = minorVersion; 84 smsConn->client_id = NULL; 85 86 smsConn->save_yourself_in_progress = False; 87 smsConn->interaction_allowed = SmInteractStyleNone; 88 smsConn->can_cancel_shutdown = False; 89 smsConn->interact_in_progress = False; 90 91 *clientDataRet = (IcePointer) smsConn; 92 93 94 /* 95 * Now give the session manager the new smsConn and get back the 96 * callbacks to invoke when messages arrive from the client. 97 * 98 * In the future, we can use the mask return value to check 99 * if the SM is expecting an older rev of SMlib. 100 */ 101 102 bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks)); 103 104 status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData, 105 &mask, &smsConn->callbacks, failureReasonRet); 106 107 return (status); 108} 109 110 111 112 113Status 114SmsInitialize(char *vendor, char *release, 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 int extra; 187 smRegisterClientReplyMsg *pMsg; 188 char *pData; 189 190 if ((smsConn->client_id = (char *) malloc (strlen (clientId) + 1)) == NULL) 191 { 192 return (0); 193 } 194 195 strcpy (smsConn->client_id, clientId); 196 197 extra = ARRAY8_BYTES (strlen (clientId)); 198 199 IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply, 200 SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra), 201 smRegisterClientReplyMsg, pMsg, pData); 202 203 STORE_ARRAY8 (pData, strlen (clientId), clientId); 204 205 IceFlush (iceConn); 206 207 return (1); 208} 209 210 211 212void 213SmsSaveYourself(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 249void 250SmsSaveYourselfPhase2(SmsConn smsConn) 251{ 252 IceConn iceConn = smsConn->iceConn; 253 254 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2); 255 IceFlush (iceConn); 256} 257 258 259 260void 261SmsInteract(SmsConn smsConn) 262{ 263 IceConn iceConn = smsConn->iceConn; 264 265 IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact); 266 IceFlush (iceConn); 267 268 smsConn->interact_in_progress = True; 269} 270 271 272 273void 274SmsDie(SmsConn smsConn) 275{ 276 IceConn iceConn = smsConn->iceConn; 277 278 IceSimpleMessage (iceConn, _SmsOpcode, SM_Die); 279 IceFlush (iceConn); 280} 281 282 283 284void 285SmsSaveComplete(SmsConn smsConn) 286{ 287 IceConn iceConn = smsConn->iceConn; 288 289 IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete); 290 IceFlush (iceConn); 291} 292 293 294 295void 296SmsShutdownCancelled(SmsConn smsConn) 297{ 298 IceConn iceConn = smsConn->iceConn; 299 300 IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled); 301 IceFlush (iceConn); 302 303 smsConn->can_cancel_shutdown = False; 304} 305 306 307 308void 309SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props) 310{ 311 IceConn iceConn = smsConn->iceConn; 312 int bytes; 313 smPropertiesReplyMsg *pMsg; 314 char *pBuf; 315 char *pStart; 316 317 IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply, 318 SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg); 319 320 LISTOF_PROP_BYTES (numProps, props, bytes); 321 pMsg->length += WORD64COUNT (bytes); 322 323 pBuf = pStart = IceAllocScratch (iceConn, bytes); 324 325 STORE_LISTOF_PROPERTY (pBuf, numProps, props); 326 327 IceWriteData (iceConn, bytes, pStart); 328 IceFlush (iceConn); 329} 330 331 332 333void 334SmsCleanUp(SmsConn smsConn) 335{ 336 IceProtocolShutdown (smsConn->iceConn, _SmsOpcode); 337 338 if (smsConn->client_id) 339 free (smsConn->client_id); 340 341 free ((char *) smsConn); 342} 343