3 Copyright 1993, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
28 * Author: Ralph Mor, X Consortium
34 #include <X11/SM/SMlib.h>
41 SmsNewClientProc _SmsNewClientProc;
42 SmPointer _SmsNewClientData;
44 SmsNewClientProc _SmsNewClientProc = 0;
45 SmPointer _SmsNewClientData = 0;
48 SmcErrorHandler _SmcErrorHandler = _SmcDefaultErrorHandler;
49 SmsErrorHandler _SmsErrorHandler = _SmsDefaultErrorHandler;
53 set_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks);
57 SmcOpenConnection(char *networkIdsList, SmPointer context,
58 int xsmpMajorRev, int xsmpMinorRev,
59 unsigned long mask, SmcCallbacks *callbacks,
60 char *previousId, char **clientIdRet,
61 int errorLength, char *errorStringRet)
66 IceProtocolSetupStatus setupstat;
71 smRegisterClientMsg *pMsg;
74 IceReplyWaitInfo replyWait;
75 _SmcRegisterClientReply reply;
76 Bool gotReply, ioErrorOccured;
78 const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"};
79 IcePoAuthProc auth_procs[] = {_IcePoMagicCookie1Proc};
82 IcePoVersionRec versions[] = {
83 {SmProtoMajor, SmProtoMinor, _SmcProcessMessage}
85 int version_count = 1;
90 if (errorStringRet && errorLength > 0)
91 *errorStringRet = '\0';
96 * For now, there is only one version of XSMP, so we don't
97 * have to check {xsmpMajorRev, xsmpMinorRev}. In the future,
98 * we will check against versions and generate the list
99 * of versions the application actually supports.
102 if ((_SmcOpcode = IceRegisterForProtocolSetup ("XSMP",
103 SmVendorString, SmReleaseString, version_count, versions,
104 auth_count, auth_names, auth_procs, NULL)) < 0)
106 if (errorStringRet && errorLength > 0) {
107 strncpy (errorStringRet,
108 "Could not register XSMP protocol with ICE",
110 errorStringRet[errorLength - 1] = '\0';
117 if (networkIdsList == NULL || *networkIdsList == '\0')
119 if ((ids = (char *) getenv ("SESSION_MANAGER")) == NULL)
121 if (errorStringRet && errorLength > 0) {
122 strncpy (errorStringRet,
123 "SESSION_MANAGER environment variable not defined",
125 errorStringRet[errorLength - 1] = '\0';
132 ids = networkIdsList;
135 if ((iceConn = IceOpenConnection (
136 ids, context, 0, _SmcOpcode, errorLength, errorStringRet)) == NULL)
141 if ((smcConn = malloc (sizeof (struct _SmcConn))) == NULL)
143 if (errorStringRet && errorLength > 0) {
144 strncpy (errorStringRet, "Can't malloc", errorLength);
145 errorStringRet[errorLength - 1] = '\0';
147 IceCloseConnection (iceConn);
151 setupstat = IceProtocolSetup (iceConn, _SmcOpcode,
152 (IcePointer) smcConn,
153 False /* mustAuthenticate */,
154 &majorVersion, &minorVersion,
155 &vendor, &release, errorLength, errorStringRet);
157 if (setupstat == IceProtocolSetupFailure ||
158 setupstat == IceProtocolSetupIOError)
160 IceCloseConnection (iceConn);
164 else if (setupstat == IceProtocolAlreadyActive)
167 * This case should never happen, because when we called
168 * IceOpenConnection, we required that the ICE connection
169 * may not already have XSMP active on it.
173 if (errorStringRet && errorLength > 0) {
174 strncpy (errorStringRet, "Internal error in IceOpenConnection",
176 errorStringRet[errorLength - 1] = '\0';
181 smcConn->iceConn = iceConn;
182 smcConn->proto_major_version = majorVersion;
183 smcConn->proto_minor_version = minorVersion;
184 smcConn->vendor = vendor;
185 smcConn->release = release;
186 smcConn->client_id = NULL;
188 bzero ((char *) &smcConn->callbacks, sizeof (SmcCallbacks));
189 set_callbacks (smcConn, mask, callbacks);
191 smcConn->interact_waits = NULL;
192 smcConn->phase2_wait = NULL;
193 smcConn->prop_reply_waits = NULL;
195 smcConn->save_yourself_in_progress = False;
196 smcConn->shutdown_in_progress = False;
200 * Now register the client
205 len = strlen (previousId);
206 extra = ARRAY8_BYTES (len);
208 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
209 SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
210 smRegisterClientMsg, pMsg, pData);
212 STORE_ARRAY8 (pData, len, previousId);
216 replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn);
217 replyWait.major_opcode_of_request = _SmcOpcode;
218 replyWait.minor_opcode_of_request = SM_RegisterClient;
219 replyWait.reply = (IcePointer) &reply;
222 ioErrorOccured = False;
224 while (!gotReply && !ioErrorOccured)
226 ioErrorOccured = (IceProcessMessages (
227 iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
231 if (errorStringRet && errorLength > 0) {
232 strncpy (errorStringRet, "IO error occured opening connection",
234 errorStringRet[errorLength - 1] = '\0';
236 free (smcConn->vendor);
237 free (smcConn->release);
244 if (reply.status == 1)
247 * The client successfully registered.
250 *clientIdRet = reply.client_id;
252 smcConn->client_id = strdup (*clientIdRet);
257 * Could not register the client because the previous ID
258 * was bad. So now we register the client with the
259 * previous ID set to NULL.
262 extra = ARRAY8_BYTES (0);
264 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
265 SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
266 smRegisterClientMsg, pMsg, pData);
268 STORE_ARRAY8 (pData, 0, "");
272 replyWait.sequence_of_request =
273 IceLastSentSequenceNumber (iceConn);
286 SmcCloseConnection(SmcConn smcConn, int count, char **reasonMsgs)
288 IceConn iceConn = smcConn->iceConn;
289 smCloseConnectionMsg *pMsg;
292 IceCloseStatus closeStatus;
293 SmcCloseStatus statusRet;
297 for (i = 0; i < count; i++)
298 extra += ARRAY8_BYTES (strlen (reasonMsgs[i]));
300 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_CloseConnection,
301 SIZEOF (smCloseConnectionMsg), WORD64COUNT (extra),
302 smCloseConnectionMsg, pMsg, pData);
304 STORE_CARD32 (pData, count);
307 for (i = 0; i < count; i++)
308 STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]);
312 IceProtocolShutdown (iceConn, _SmcOpcode);
313 IceSetShutdownNegotiation (iceConn, False);
314 closeStatus = IceCloseConnection (iceConn);
317 free (smcConn->vendor);
319 if (smcConn->release)
320 free (smcConn->release);
322 if (smcConn->client_id)
323 free (smcConn->client_id);
325 if (smcConn->prop_reply_waits)
327 _SmcPropReplyWait *ptr = smcConn->prop_reply_waits;
328 _SmcPropReplyWait *next;
341 if (closeStatus == IceClosedNow)
342 statusRet = SmcClosedNow;
343 else if (closeStatus == IceClosedASAP)
344 statusRet = SmcClosedASAP;
346 statusRet = SmcConnectionInUse;
354 SmcModifyCallbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks)
356 set_callbacks (smcConn, mask, callbacks);
362 SmcSetProperties(SmcConn smcConn, int numProps, SmProp **props)
364 IceConn iceConn = smcConn->iceConn;
365 smSetPropertiesMsg *pMsg;
370 IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties,
371 SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg);
373 LISTOF_PROP_BYTES (numProps, props, bytes);
374 pMsg->length += WORD64COUNT (bytes);
376 pBuf = pStart = IceAllocScratch (iceConn, bytes);
377 memset(pStart, 0, bytes);
379 STORE_LISTOF_PROPERTY (pBuf, numProps, props);
381 IceWriteData (iceConn, bytes, pStart);
388 SmcDeleteProperties(SmcConn smcConn, int numProps, char **propNames)
390 IceConn iceConn = smcConn->iceConn;
391 smDeletePropertiesMsg *pMsg;
397 for (i = 0; i < numProps; i++)
398 extra += ARRAY8_BYTES (strlen (propNames[i]));
400 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties,
401 SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra),
402 smDeletePropertiesMsg, pMsg, pData);
404 STORE_CARD32 (pData, numProps);
407 for (i = 0; i < numProps; i++)
408 STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]);
416 SmcGetProperties(SmcConn smcConn, SmcPropReplyProc propReplyProc,
417 SmPointer clientData)
419 IceConn iceConn = smcConn->iceConn;
420 _SmcPropReplyWait *wait, *ptr;
422 if ((wait = malloc (sizeof (_SmcPropReplyWait))) == NULL)
427 wait->prop_reply_proc = propReplyProc;
428 wait->client_data = clientData;
431 ptr = smcConn->prop_reply_waits;
432 while (ptr && ptr->next)
436 smcConn->prop_reply_waits = wait;
440 IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties);
449 SmcInteractRequest(SmcConn smcConn, int dialogType,
450 SmcInteractProc interactProc, SmPointer clientData)
452 IceConn iceConn = smcConn->iceConn;
453 smInteractRequestMsg *pMsg;
454 _SmcInteractWait *wait, *ptr;
456 if ((wait = malloc (sizeof (_SmcInteractWait))) == NULL)
461 wait->interact_proc = interactProc;
462 wait->client_data = clientData;
465 ptr = smcConn->interact_waits;
466 while (ptr && ptr->next)
470 smcConn->interact_waits = wait;
474 IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest,
475 SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg);
477 pMsg->dialogType = dialogType;
487 SmcInteractDone(SmcConn smcConn, Bool cancelShutdown)
489 IceConn iceConn = smcConn->iceConn;
490 smInteractDoneMsg *pMsg;
492 IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone,
493 SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg);
495 pMsg->cancelShutdown = cancelShutdown;
503 SmcRequestSaveYourself(SmcConn smcConn, int saveType, Bool shutdown,
504 int interactStyle, Bool fast, Bool global)
506 IceConn iceConn = smcConn->iceConn;
507 smSaveYourselfRequestMsg *pMsg;
509 IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest,
510 SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg);
512 pMsg->saveType = saveType;
513 pMsg->shutdown = shutdown;
514 pMsg->interactStyle = interactStyle;
516 pMsg->global = global;
524 SmcRequestSaveYourselfPhase2(SmcConn smcConn,
525 SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc,
526 SmPointer clientData)
528 IceConn iceConn = smcConn->iceConn;
529 _SmcPhase2Wait *wait;
531 if (smcConn->phase2_wait)
532 wait = smcConn->phase2_wait;
535 if ((wait = malloc (sizeof (_SmcPhase2Wait))) == NULL)
541 wait->phase2_proc = saveYourselfPhase2Proc;
542 wait->client_data = clientData;
544 smcConn->phase2_wait = wait;
546 IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request);
555 SmcSaveYourselfDone(SmcConn smcConn, Bool success)
557 IceConn iceConn = smcConn->iceConn;
558 smSaveYourselfDoneMsg *pMsg;
560 IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone,
561 SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg);
563 pMsg->success = success;
571 set_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks)
573 if (mask & SmcSaveYourselfProcMask)
575 smcConn->callbacks.save_yourself.callback =
576 callbacks->save_yourself.callback;
577 smcConn->callbacks.save_yourself.client_data =
578 callbacks->save_yourself.client_data;
581 if (mask & SmcDieProcMask)
583 smcConn->callbacks.die.callback = callbacks->die.callback;
584 smcConn->callbacks.die.client_data = callbacks->die.client_data;
587 if (mask & SmcSaveCompleteProcMask)
589 smcConn->callbacks.save_complete.callback =
590 callbacks->save_complete.callback;
591 smcConn->callbacks.save_complete.client_data =
592 callbacks->save_complete.client_data;
595 if (mask & SmcShutdownCancelledProcMask)
597 smcConn->callbacks.shutdown_cancelled.callback =
598 callbacks->shutdown_cancelled.callback;
599 smcConn->callbacks.shutdown_cancelled.client_data =
600 callbacks->shutdown_cancelled.client_data;