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 = (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);
161 free ((char *) smcConn);
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.
172 free ((char *) smcConn);
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);
238 free ((char *) smcConn);
244 if (reply.status == 1)
247 * The client successfully registered.
250 *clientIdRet = reply.client_id;
252 smcConn->client_id = (char *) malloc (
253 strlen (*clientIdRet) + 1);
255 strcpy (smcConn->client_id, *clientIdRet);
260 * Could not register the client because the previous ID
261 * was bad. So now we register the client with the
262 * previous ID set to NULL.
265 extra = ARRAY8_BYTES (0);
267 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
268 SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
269 smRegisterClientMsg, pMsg, pData);
271 STORE_ARRAY8 (pData, 0, "");
275 replyWait.sequence_of_request =
276 IceLastSentSequenceNumber (iceConn);
289 SmcCloseConnection(SmcConn smcConn, int count, char **reasonMsgs)
291 IceConn iceConn = smcConn->iceConn;
292 smCloseConnectionMsg *pMsg;
295 IceCloseStatus closeStatus;
296 SmcCloseStatus statusRet;
300 for (i = 0; i < count; i++)
301 extra += ARRAY8_BYTES (strlen (reasonMsgs[i]));
303 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_CloseConnection,
304 SIZEOF (smCloseConnectionMsg), WORD64COUNT (extra),
305 smCloseConnectionMsg, pMsg, pData);
307 STORE_CARD32 (pData, count);
310 for (i = 0; i < count; i++)
311 STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]);
315 IceProtocolShutdown (iceConn, _SmcOpcode);
316 IceSetShutdownNegotiation (iceConn, False);
317 closeStatus = IceCloseConnection (iceConn);
320 free (smcConn->vendor);
322 if (smcConn->release)
323 free (smcConn->release);
325 if (smcConn->client_id)
326 free (smcConn->client_id);
328 if (smcConn->prop_reply_waits)
330 _SmcPropReplyWait *ptr = smcConn->prop_reply_waits;
331 _SmcPropReplyWait *next;
342 free ((char *) smcConn);
344 if (closeStatus == IceClosedNow)
345 statusRet = SmcClosedNow;
346 else if (closeStatus == IceClosedASAP)
347 statusRet = SmcClosedASAP;
349 statusRet = SmcConnectionInUse;
357 SmcModifyCallbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks)
359 set_callbacks (smcConn, mask, callbacks);
365 SmcSetProperties(SmcConn smcConn, int numProps, SmProp **props)
367 IceConn iceConn = smcConn->iceConn;
368 smSetPropertiesMsg *pMsg;
373 IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties,
374 SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg);
376 LISTOF_PROP_BYTES (numProps, props, bytes);
377 pMsg->length += WORD64COUNT (bytes);
379 pBuf = pStart = IceAllocScratch (iceConn, bytes);
380 memset(pStart, 0, bytes);
382 STORE_LISTOF_PROPERTY (pBuf, numProps, props);
384 IceWriteData (iceConn, bytes, pStart);
391 SmcDeleteProperties(SmcConn smcConn, int numProps, char **propNames)
393 IceConn iceConn = smcConn->iceConn;
394 smDeletePropertiesMsg *pMsg;
400 for (i = 0; i < numProps; i++)
401 extra += ARRAY8_BYTES (strlen (propNames[i]));
403 IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties,
404 SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra),
405 smDeletePropertiesMsg, pMsg, pData);
407 STORE_CARD32 (pData, numProps);
410 for (i = 0; i < numProps; i++)
411 STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]);
419 SmcGetProperties(SmcConn smcConn, SmcPropReplyProc propReplyProc,
420 SmPointer clientData)
422 IceConn iceConn = smcConn->iceConn;
423 _SmcPropReplyWait *wait, *ptr;
425 if ((wait = (_SmcPropReplyWait *) malloc (
426 sizeof (_SmcPropReplyWait))) == NULL)
431 wait->prop_reply_proc = propReplyProc;
432 wait->client_data = clientData;
435 ptr = smcConn->prop_reply_waits;
436 while (ptr && ptr->next)
440 smcConn->prop_reply_waits = wait;
444 IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties);
453 SmcInteractRequest(SmcConn smcConn, int dialogType,
454 SmcInteractProc interactProc, SmPointer clientData)
456 IceConn iceConn = smcConn->iceConn;
457 smInteractRequestMsg *pMsg;
458 _SmcInteractWait *wait, *ptr;
460 if ((wait = (_SmcInteractWait *) malloc (
461 sizeof (_SmcInteractWait))) == NULL)
466 wait->interact_proc = interactProc;
467 wait->client_data = clientData;
470 ptr = smcConn->interact_waits;
471 while (ptr && ptr->next)
475 smcConn->interact_waits = wait;
479 IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest,
480 SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg);
482 pMsg->dialogType = dialogType;
492 SmcInteractDone(SmcConn smcConn, Bool cancelShutdown)
494 IceConn iceConn = smcConn->iceConn;
495 smInteractDoneMsg *pMsg;
497 IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone,
498 SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg);
500 pMsg->cancelShutdown = cancelShutdown;
508 SmcRequestSaveYourself(SmcConn smcConn, int saveType, Bool shutdown,
509 int interactStyle, Bool fast, Bool global)
511 IceConn iceConn = smcConn->iceConn;
512 smSaveYourselfRequestMsg *pMsg;
514 IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest,
515 SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg);
517 pMsg->saveType = saveType;
518 pMsg->shutdown = shutdown;
519 pMsg->interactStyle = interactStyle;
521 pMsg->global = global;
529 SmcRequestSaveYourselfPhase2(SmcConn smcConn,
530 SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc,
531 SmPointer clientData)
533 IceConn iceConn = smcConn->iceConn;
534 _SmcPhase2Wait *wait;
536 if (smcConn->phase2_wait)
537 wait = smcConn->phase2_wait;
540 if ((wait = (_SmcPhase2Wait *) malloc (
541 sizeof (_SmcPhase2Wait))) == NULL)
547 wait->phase2_proc = saveYourselfPhase2Proc;
548 wait->client_data = clientData;
550 smcConn->phase2_wait = wait;
552 IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request);
561 SmcSaveYourselfDone(SmcConn smcConn, Bool success)
563 IceConn iceConn = smcConn->iceConn;
564 smSaveYourselfDoneMsg *pMsg;
566 IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone,
567 SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg);
569 pMsg->success = success;
577 set_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks)
579 if (mask & SmcSaveYourselfProcMask)
581 smcConn->callbacks.save_yourself.callback =
582 callbacks->save_yourself.callback;
583 smcConn->callbacks.save_yourself.client_data =
584 callbacks->save_yourself.client_data;
587 if (mask & SmcDieProcMask)
589 smcConn->callbacks.die.callback = callbacks->die.callback;
590 smcConn->callbacks.die.client_data = callbacks->die.client_data;
593 if (mask & SmcSaveCompleteProcMask)
595 smcConn->callbacks.save_complete.callback =
596 callbacks->save_complete.callback;
597 smcConn->callbacks.save_complete.client_data =
598 callbacks->save_complete.client_data;
601 if (mask & SmcShutdownCancelledProcMask)
603 smcConn->callbacks.shutdown_cancelled.callback =
604 callbacks->shutdown_cancelled.callback;
605 smcConn->callbacks.shutdown_cancelled.client_data =
606 callbacks->shutdown_cancelled.client_data;