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>
39 * Check for bad length
42 #define CHECK_SIZE_MATCH(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
43 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
45 _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
49 #define CHECK_AT_LEAST_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
50 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
52 _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
56 #define CHECK_COMPLETE_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _pStart, _severity) \
57 if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
60 _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
61 IceDisposeCompleteMessage (iceConn, _pStart); \
68 _SmcProcessMessage(IceConn iceConn, IcePointer clientData, int opcode,
69 unsigned long length, Bool swap,
70 IceReplyWaitInfo *replyWait, Bool *replyReadyRet)
72 SmcConn smcConn = (SmcConn) clientData;
75 *replyReadyRet = False;
77 if (!smcConn->client_id &&
78 opcode != SM_RegisterClientReply && opcode != SM_Error)
80 _IceReadSkip (iceConn, length << 3);
82 _IceErrorBadState (iceConn, _SmcOpcode, opcode, IceFatalToProtocol);
93 CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
94 length, SIZEOF (iceErrorMsg), IceFatalToProtocol);
96 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
97 iceErrorMsg, pMsg, pData);
99 if (!IceValidIO (iceConn))
101 IceDisposeCompleteMessage (iceConn, pData);
107 pMsg->errorClass = lswaps (pMsg->errorClass);
108 pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
112 replyWait->minor_opcode_of_request == SM_RegisterClient &&
113 pMsg->errorClass == IceBadValue &&
114 pMsg->offendingMinorOpcode == SM_RegisterClient &&
115 pMsg->offendingSequenceNum == replyWait->sequence_of_request)
118 * For Register Client, the previous ID was bad.
121 _SmcRegisterClientReply *reply =
122 (_SmcRegisterClientReply *) (replyWait->reply);
126 *replyReadyRet = True;
130 (*_SmcErrorHandler) (smcConn, swap,
131 pMsg->offendingMinorOpcode,
132 pMsg->offendingSequenceNum,
133 pMsg->errorClass, pMsg->severity,
137 IceDisposeCompleteMessage (iceConn, pData);
141 case SM_RegisterClientReply:
144 replyWait->minor_opcode_of_request != SM_RegisterClient)
146 _IceReadSkip (iceConn, length << 3);
148 _IceErrorBadState (iceConn, _SmcOpcode,
149 SM_RegisterClientReply, IceFatalToProtocol);
153 smRegisterClientReplyMsg *pMsg;
154 char *pData, *pStart;
155 _SmcRegisterClientReply *reply =
156 (_SmcRegisterClientReply *) (replyWait->reply);
159 CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
160 length, SIZEOF (smRegisterClientReplyMsg), IceFatalToProtocol);
163 IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientReplyMsg),
164 smRegisterClientReplyMsg, pMsg, pStart);
166 if (!IceValidIO (iceConn))
168 IceDisposeCompleteMessage (iceConn, pStart);
174 SKIP_ARRAY8 (pData, swap); /* client id */
176 CHECK_COMPLETE_SIZE (iceConn, _SmcOpcode, opcode,
177 length, pData - pStart + SIZEOF (smRegisterClientReplyMsg),
178 pStart, IceFatalToProtocol);
182 EXTRACT_ARRAY8_AS_STRING (pData, swap, reply->client_id);
185 *replyReadyRet = True;
187 IceDisposeCompleteMessage (iceConn, pStart);
191 case SM_SaveYourself:
193 smSaveYourselfMsg *pMsg;
194 unsigned char errVal;
197 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
198 length, SIZEOF (smSaveYourselfMsg),
201 IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfMsg),
202 smSaveYourselfMsg, pMsg);
204 if (!IceValidIO (iceConn))
209 if (pMsg->saveType != SmSaveGlobal &&
210 pMsg->saveType != SmSaveLocal &&
211 pMsg->saveType != SmSaveBoth)
213 errVal = pMsg->saveType;
216 else if (pMsg->shutdown != 1 && pMsg->shutdown != 0)
218 errVal = pMsg->shutdown;
221 else if (pMsg->interactStyle != SmInteractStyleNone &&
222 pMsg->interactStyle != SmInteractStyleErrors &&
223 pMsg->interactStyle != SmInteractStyleAny)
225 errVal = pMsg->interactStyle;
228 else if (pMsg->fast != 1 && pMsg->fast != 0)
236 _IceErrorBadValue (iceConn, _SmcOpcode,
237 SM_SaveYourself, errOffset, 1, (IcePointer) &errVal);
241 (*smcConn->callbacks.save_yourself.callback) (smcConn,
242 smcConn->callbacks.save_yourself.client_data,
243 pMsg->saveType, pMsg->shutdown,
244 pMsg->interactStyle, pMsg->fast);
246 smcConn->save_yourself_in_progress = True;
249 smcConn->shutdown_in_progress = True;
254 case SM_SaveYourselfPhase2:
256 if (!smcConn->phase2_wait)
258 _IceErrorBadState (iceConn, _SmcOpcode,
259 SM_SaveYourselfPhase2, IceCanContinue);
263 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
264 length, SIZEOF (smSaveYourselfPhase2Msg),
267 (*smcConn->phase2_wait->phase2_proc) (smcConn,
268 smcConn->phase2_wait->client_data);
270 free (smcConn->phase2_wait);
271 smcConn->phase2_wait = NULL;
277 if (!smcConn->interact_waits)
279 _IceErrorBadState (iceConn, _SmcOpcode,
280 SM_Interact, IceCanContinue);
284 _SmcInteractWait *next = smcConn->interact_waits->next;
286 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
287 length, SIZEOF (smInteractMsg),
290 (*smcConn->interact_waits->interact_proc) (smcConn,
291 smcConn->interact_waits->client_data);
293 free (smcConn->interact_waits);
294 smcConn->interact_waits = next;
298 case SM_SaveComplete:
300 if (!smcConn->save_yourself_in_progress)
302 _IceErrorBadState (iceConn, _SmcOpcode,
303 SM_SaveComplete, IceCanContinue);
307 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
308 length, SIZEOF (smSaveCompleteMsg),
311 smcConn->save_yourself_in_progress = False;
313 (*smcConn->callbacks.save_complete.callback) (smcConn,
314 smcConn->callbacks.save_complete.client_data);
320 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
321 length, SIZEOF (smDieMsg),
324 (*smcConn->callbacks.die.callback) (smcConn,
325 smcConn->callbacks.die.client_data);
328 case SM_ShutdownCancelled:
330 if (!smcConn->shutdown_in_progress)
332 _IceErrorBadState (iceConn, _SmcOpcode,
333 SM_ShutdownCancelled, IceCanContinue);
337 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
338 length, SIZEOF (smShutdownCancelledMsg),
341 smcConn->shutdown_in_progress = False;
343 (*smcConn->callbacks.shutdown_cancelled.callback) (smcConn,
344 smcConn->callbacks.shutdown_cancelled.client_data);
348 case SM_PropertiesReply:
350 if (!smcConn->prop_reply_waits)
352 _IceReadSkip (iceConn, length << 3);
354 _IceErrorBadState (iceConn, _SmcOpcode,
355 SM_PropertiesReply, IceCanContinue);
359 smPropertiesReplyMsg *pMsg;
360 char *pData, *pStart;
362 SmProp **props = NULL;
363 _SmcPropReplyWait *next;
366 CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
367 length, SIZEOF (smPropertiesReplyMsg), IceFatalToProtocol);
370 IceReadCompleteMessage (iceConn, SIZEOF (smPropertiesReplyMsg),
371 smPropertiesReplyMsg, pMsg, pStart);
373 if (!IceValidIO (iceConn))
375 IceDisposeCompleteMessage (iceConn, pStart);
381 SKIP_LISTOF_PROPERTY (pData, swap);
383 CHECK_COMPLETE_SIZE (iceConn, _SmcOpcode, opcode,
384 length, pData - pStart + SIZEOF (smPropertiesReplyMsg),
385 pStart, IceFatalToProtocol);
389 EXTRACT_LISTOF_PROPERTY (pData, swap, numProps, props);
391 next = smcConn->prop_reply_waits->next;
393 (*smcConn->prop_reply_waits->prop_reply_proc) (smcConn,
394 smcConn->prop_reply_waits->client_data, numProps, props);
396 free (smcConn->prop_reply_waits);
397 smcConn->prop_reply_waits = next;
399 IceDisposeCompleteMessage (iceConn, pStart);
405 _IceErrorBadMinor (iceConn, _SmcOpcode, opcode, IceCanContinue);
406 _IceReadSkip (iceConn, length << 3);
415 _SmsProcessMessage(IceConn iceConn, IcePointer clientData, int opcode,
416 unsigned long length, Bool swap)
418 SmsConn smsConn = (SmsConn) clientData;
420 if (!smsConn->client_id &&
421 opcode != SM_RegisterClient && opcode != SM_Error)
423 _IceReadSkip (iceConn, length << 3);
425 _IceErrorBadState (iceConn, _SmsOpcode, opcode, IceFatalToProtocol);
437 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
438 length, SIZEOF (iceErrorMsg), IceFatalToProtocol);
440 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
441 iceErrorMsg, pMsg, pData);
443 if (!IceValidIO (iceConn))
445 IceDisposeCompleteMessage (iceConn, pData);
451 pMsg->errorClass = lswaps (pMsg->errorClass);
452 pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
455 (*_SmsErrorHandler) (smsConn, swap,
456 pMsg->offendingMinorOpcode,
457 pMsg->offendingSequenceNum,
458 pMsg->errorClass, pMsg->severity,
461 IceDisposeCompleteMessage (iceConn, pData);
465 case SM_RegisterClient:
467 smRegisterClientMsg *pMsg;
468 char *pData, *pStart;
473 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
474 length, SIZEOF (smRegisterClientMsg), IceFatalToProtocol);
477 IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientMsg),
478 smRegisterClientMsg, pMsg, pStart);
480 if (!IceValidIO (iceConn))
482 IceDisposeCompleteMessage (iceConn, pStart);
488 SKIP_ARRAY8 (pData, swap); /* previous id */
490 CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
491 length, pData - pStart + SIZEOF (smRegisterClientMsg),
492 pStart, IceFatalToProtocol);
496 EXTRACT_ARRAY8 (pData, swap, idLen, previousId);
498 if (*previousId == '\0')
504 if (!(*smsConn->callbacks.register_client.callback) (smsConn,
505 smsConn->callbacks.register_client.manager_data, previousId))
508 * The previoudId was bad. Generate BadValue error.
511 _IceErrorBadValue (smsConn->iceConn, _SmsOpcode, SM_RegisterClient,
512 8, ARRAY8_BYTES (idLen), (IcePointer) pStart);
515 IceDisposeCompleteMessage (iceConn, pStart);
519 case SM_InteractRequest:
521 if (!smsConn->save_yourself_in_progress ||
522 smsConn->interaction_allowed == SmInteractStyleNone)
524 _IceErrorBadState (iceConn, _SmsOpcode,
525 SM_InteractRequest, IceCanContinue);
529 smInteractRequestMsg *pMsg;
531 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
532 length, SIZEOF (smInteractRequestMsg),
535 IceReadSimpleMessage (iceConn, smInteractRequestMsg, pMsg);
537 if (pMsg->dialogType != SmDialogNormal &&
538 pMsg->dialogType != SmDialogError)
540 unsigned char errVal = pMsg->dialogType;
542 _IceErrorBadValue (iceConn, _SmsOpcode,
543 SM_InteractRequest, 2, 1, (IcePointer) &errVal);
545 else if (pMsg->dialogType == SmDialogNormal &&
546 smsConn->interaction_allowed != SmInteractStyleAny)
548 _IceErrorBadState (iceConn, _SmsOpcode,
549 SM_InteractRequest, IceCanContinue);
553 (*smsConn->callbacks.interact_request.callback) (smsConn,
554 smsConn->callbacks.interact_request.manager_data,
560 case SM_InteractDone:
562 if (!smsConn->interact_in_progress)
564 _IceErrorBadState (iceConn, _SmsOpcode,
565 SM_InteractDone, IceCanContinue);
569 smInteractDoneMsg *pMsg;
571 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
572 length, SIZEOF (smInteractDoneMsg),
575 IceReadSimpleMessage (iceConn, smInteractDoneMsg, pMsg);
577 if (pMsg->cancelShutdown != 1 &&
578 pMsg->cancelShutdown != 0)
580 unsigned char errVal = pMsg->cancelShutdown;
582 _IceErrorBadValue (iceConn, _SmsOpcode,
583 SM_InteractDone, 2, 1, (IcePointer) &errVal);
585 else if (pMsg->cancelShutdown && !smsConn->can_cancel_shutdown)
587 _IceErrorBadState (iceConn, _SmsOpcode,
588 SM_InteractDone, IceCanContinue);
592 smsConn->interact_in_progress = False;
594 (*smsConn->callbacks.interact_done.callback) (smsConn,
595 smsConn->callbacks.interact_done.manager_data,
596 pMsg->cancelShutdown);
601 case SM_SaveYourselfRequest:
603 smSaveYourselfRequestMsg *pMsg;
604 unsigned char errVal;
607 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
608 length, SIZEOF (smSaveYourselfRequestMsg),
611 IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfRequestMsg),
612 smSaveYourselfRequestMsg, pMsg);
614 if (!IceValidIO (iceConn))
616 IceDisposeCompleteMessage (iceConn, pMsg);
620 if (pMsg->saveType != SmSaveGlobal &&
621 pMsg->saveType != SmSaveLocal &&
622 pMsg->saveType != SmSaveBoth)
624 errVal = pMsg->saveType;
627 else if (pMsg->shutdown != 1 && pMsg->shutdown != 0)
629 errVal = pMsg->shutdown;
632 else if (pMsg->interactStyle != SmInteractStyleNone &&
633 pMsg->interactStyle != SmInteractStyleErrors &&
634 pMsg->interactStyle != SmInteractStyleAny)
636 errVal = pMsg->interactStyle;
639 else if (pMsg->fast != 1 && pMsg->fast != 0)
644 else if (pMsg->global != 1 && pMsg->global != 0)
652 _IceErrorBadValue (iceConn, _SmsOpcode,
653 SM_SaveYourselfRequest, errOffset, 1, (IcePointer) &errVal);
657 (*smsConn->callbacks.save_yourself_request.callback) (smsConn,
658 smsConn->callbacks.save_yourself_request.manager_data,
659 pMsg->saveType, pMsg->shutdown, pMsg->interactStyle,
660 pMsg->fast, pMsg->global);
665 case SM_SaveYourselfPhase2Request:
667 if (!smsConn->save_yourself_in_progress)
669 _IceErrorBadState (iceConn, _SmsOpcode,
670 SM_SaveYourselfPhase2Request, IceCanContinue);
674 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
675 length, SIZEOF (smSaveYourselfPhase2RequestMsg),
678 (*smsConn->callbacks.save_yourself_phase2_request.callback) (
679 smsConn, smsConn->callbacks.
680 save_yourself_phase2_request.manager_data);
684 case SM_SaveYourselfDone:
686 if (!smsConn->save_yourself_in_progress)
688 _IceErrorBadState (iceConn, _SmsOpcode,
689 SM_SaveYourselfDone, IceCanContinue);
693 smSaveYourselfDoneMsg *pMsg;
695 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
696 length, SIZEOF (smSaveYourselfDoneMsg),
699 IceReadSimpleMessage (iceConn, smSaveYourselfDoneMsg, pMsg);
701 if (pMsg->success != 1 && pMsg->success != 0)
703 unsigned char errVal = pMsg->success;
705 _IceErrorBadValue (iceConn, _SmsOpcode,
706 SM_SaveYourselfDone, 2, 1, (IcePointer) &errVal);
710 smsConn->save_yourself_in_progress = False;
711 smsConn->interaction_allowed = SmInteractStyleNone;
713 (*smsConn->callbacks.save_yourself_done.callback) (smsConn,
714 smsConn->callbacks.save_yourself_done.manager_data,
720 case SM_CloseConnection:
722 smCloseConnectionMsg *pMsg;
723 char *pData, *pStart;
725 char **reasonMsgs = NULL;
728 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
729 length, SIZEOF (smCloseConnectionMsg), IceFatalToProtocol);
732 IceReadCompleteMessage (iceConn, SIZEOF (smCloseConnectionMsg),
733 smCloseConnectionMsg, pMsg, pStart);
735 if (!IceValidIO (iceConn))
737 IceDisposeCompleteMessage (iceConn, pStart);
743 EXTRACT_CARD32 (pData, swap, count);
746 for (i = 0; i < count; i++)
747 SKIP_ARRAY8 (pData, swap);
749 CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
750 length, pData - pStart + SIZEOF (smCloseConnectionMsg),
751 pStart, IceFatalToProtocol);
755 reasonMsgs = malloc (count * sizeof (char *));
756 for (i = 0; i < count; i++)
757 EXTRACT_ARRAY8_AS_STRING (pData, swap, reasonMsgs[i]);
759 IceDisposeCompleteMessage (iceConn, pStart);
761 (*smsConn->callbacks.close_connection.callback) (smsConn,
762 smsConn->callbacks.close_connection.manager_data,
767 case SM_SetProperties:
769 smSetPropertiesMsg *pMsg;
770 char *pData, *pStart;
771 SmProp **props = NULL;
775 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
776 length, SIZEOF (smSetPropertiesMsg), IceFatalToProtocol);
779 IceReadCompleteMessage (iceConn, SIZEOF (smSetPropertiesMsg),
780 smSetPropertiesMsg, pMsg, pStart);
782 if (!IceValidIO (iceConn))
784 IceDisposeCompleteMessage (iceConn, pStart);
790 SKIP_LISTOF_PROPERTY (pData, swap);
792 CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
793 length, pData - pStart + SIZEOF (smSetPropertiesMsg),
794 pStart, IceFatalToProtocol);
798 EXTRACT_LISTOF_PROPERTY (pData, swap, numProps, props);
800 (*smsConn->callbacks.set_properties.callback) (smsConn,
801 smsConn->callbacks.set_properties.manager_data, numProps, props);
803 IceDisposeCompleteMessage (iceConn, pStart);
807 case SM_DeleteProperties:
809 smDeletePropertiesMsg *pMsg;
810 char *pData, *pStart;
812 char **propNames = NULL;
815 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
816 length, SIZEOF (smDeletePropertiesMsg), IceFatalToProtocol);
819 IceReadCompleteMessage (iceConn, SIZEOF (smDeletePropertiesMsg),
820 smDeletePropertiesMsg, pMsg, pStart);
822 if (!IceValidIO (iceConn))
824 IceDisposeCompleteMessage (iceConn, pStart);
830 EXTRACT_CARD32 (pData, swap, count);
833 for (i = 0; i < count; i++)
834 SKIP_ARRAY8 (pData, swap); /* prop names */
836 CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
837 length, pData - pStart + SIZEOF (smDeletePropertiesMsg),
838 pStart, IceFatalToProtocol);
842 propNames = malloc (count * sizeof (char *));
843 for (i = 0; i < count; i++)
844 EXTRACT_ARRAY8_AS_STRING (pData, swap, propNames[i]);
846 IceDisposeCompleteMessage (iceConn, pStart);
848 (*smsConn->callbacks.delete_properties.callback) (smsConn,
849 smsConn->callbacks.delete_properties.manager_data,
855 case SM_GetProperties:
857 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
858 length, SIZEOF (smGetPropertiesMsg),
861 (*smsConn->callbacks.get_properties.callback) (smsConn,
862 smsConn->callbacks.get_properties.manager_data);
867 _IceErrorBadMinor (iceConn, _SmsOpcode, opcode, IceCanContinue);
868 _IceReadSkip (iceConn, length << 3);