summaryrefslogtreecommitdiff
path: root/src/sm_process.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:36 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:36 +0000
commitabe0fd5d586b52a851a423a79b95070da418eb10 (patch)
tree7755dc0bbc85775e65fc39281e3b89d594767c94 /src/sm_process.c
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
Diffstat (limited to 'src/sm_process.c')
-rw-r--r--src/sm_process.c875
1 files changed, 875 insertions, 0 deletions
diff --git a/src/sm_process.c b/src/sm_process.c
new file mode 100644
index 0000000..cb15ebc
--- /dev/null
+++ b/src/sm_process.c
@@ -0,0 +1,875 @@
+/* $Xorg: sm_process.c,v 1.4 2001/02/09 02:03:30 xorgcvs Exp $ */
+
+/*
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+/*
+ * Author: Ralph Mor, X Consortium
+ */
+
+#include <X11/SM/SMlib.h>
+#include "SMlibint.h"
+
+
+/*
+ * Check for bad length
+ */
+
+#define CHECK_SIZE_MATCH(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
+ return; \
+ }
+
+#define CHECK_AT_LEAST_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
+ return; \
+ }
+
+#define CHECK_COMPLETE_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _pStart, _severity) \
+ if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
+ != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
+ IceDisposeCompleteMessage (iceConn, _pStart); \
+ return; \
+ }
+
+
+
+void
+_SmcProcessMessage (iceConn, clientData, opcode,
+ length, swap, replyWait, replyReadyRet)
+
+IceConn iceConn;
+IcePointer clientData;
+int opcode;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+Bool *replyReadyRet;
+
+{
+ SmcConn smcConn = (SmcConn) clientData;
+
+ if (replyWait)
+ *replyReadyRet = False;
+
+ if (!smcConn->client_id &&
+ opcode != SM_RegisterClientReply && opcode != SM_Error)
+ {
+ _IceReadSkip (iceConn, length << 3);
+
+ _IceErrorBadState (iceConn, _SmcOpcode, opcode, IceFatalToProtocol);
+ return;
+ }
+
+ switch (opcode)
+ {
+ case SM_Error:
+ {
+ iceErrorMsg *pMsg;
+ char *pData;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (iceErrorMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
+ iceErrorMsg, pMsg, pData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pData);
+ return;
+ }
+
+ if (swap)
+ {
+ pMsg->errorClass = lswaps (pMsg->errorClass);
+ pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
+ }
+
+ if (replyWait &&
+ replyWait->minor_opcode_of_request == SM_RegisterClient &&
+ pMsg->errorClass == IceBadValue &&
+ pMsg->offendingMinorOpcode == SM_RegisterClient &&
+ pMsg->offendingSequenceNum == replyWait->sequence_of_request)
+ {
+ /*
+ * For Register Client, the previous ID was bad.
+ */
+
+ _SmcRegisterClientReply *reply =
+ (_SmcRegisterClientReply *) (replyWait->reply);
+
+ reply->status = 0;
+
+ *replyReadyRet = True;
+ }
+ else
+ {
+ (*_SmcErrorHandler) (smcConn, swap,
+ pMsg->offendingMinorOpcode,
+ pMsg->offendingSequenceNum,
+ pMsg->errorClass, pMsg->severity,
+ (SmPointer) pData);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pData);
+ break;
+ }
+
+ case SM_RegisterClientReply:
+
+ if (!replyWait ||
+ replyWait->minor_opcode_of_request != SM_RegisterClient)
+ {
+ _IceReadSkip (iceConn, length << 3);
+
+ _IceErrorBadState (iceConn, _SmcOpcode,
+ SM_RegisterClientReply, IceFatalToProtocol);
+ }
+ else
+ {
+ smRegisterClientReplyMsg *pMsg;
+ char *pData, *pStart;
+ _SmcRegisterClientReply *reply =
+ (_SmcRegisterClientReply *) (replyWait->reply);
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smRegisterClientReplyMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientReplyMsg),
+ smRegisterClientReplyMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ pData = pStart;
+
+ SKIP_ARRAY8 (pData, swap); /* client id */
+
+ CHECK_COMPLETE_SIZE (iceConn, _SmcOpcode, opcode,
+ length, pData - pStart + SIZEOF (smRegisterClientReplyMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ EXTRACT_ARRAY8_AS_STRING (pData, swap, reply->client_id);
+
+ reply->status = 1;
+ *replyReadyRet = True;
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ }
+ break;
+
+ case SM_SaveYourself:
+ {
+ smSaveYourselfMsg *pMsg;
+ unsigned char errVal;
+ int errOffset = -1;
+
+ CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smSaveYourselfMsg),
+ IceFatalToProtocol);
+
+ IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfMsg),
+ smSaveYourselfMsg, pMsg);
+
+ if (!IceValidIO (iceConn))
+ {
+ return;
+ }
+
+ if (pMsg->saveType != SmSaveGlobal &&
+ pMsg->saveType != SmSaveLocal &&
+ pMsg->saveType != SmSaveBoth)
+ {
+ errVal = pMsg->saveType;
+ errOffset = 8;
+ }
+ else if (pMsg->shutdown != 1 && pMsg->shutdown != 0)
+ {
+ errVal = pMsg->shutdown;
+ errOffset = 9;
+ }
+ else if (pMsg->interactStyle != SmInteractStyleNone &&
+ pMsg->interactStyle != SmInteractStyleErrors &&
+ pMsg->interactStyle != SmInteractStyleAny)
+ {
+ errVal = pMsg->interactStyle;
+ errOffset = 10;
+ }
+ else if (pMsg->fast != 1 && pMsg->fast != 0)
+ {
+ errVal = pMsg->fast;
+ errOffset = 11;
+ }
+
+ if (errOffset >= 0)
+ {
+ _IceErrorBadValue (iceConn, _SmcOpcode,
+ SM_SaveYourself, errOffset, 1, (IcePointer) &errVal);
+ }
+ else
+ {
+ (*smcConn->callbacks.save_yourself.callback) (smcConn,
+ smcConn->callbacks.save_yourself.client_data,
+ pMsg->saveType, pMsg->shutdown,
+ pMsg->interactStyle, pMsg->fast);
+
+ smcConn->save_yourself_in_progress = True;
+
+ if (pMsg->shutdown)
+ smcConn->shutdown_in_progress = True;
+ }
+ break;
+ }
+
+ case SM_SaveYourselfPhase2:
+
+ if (!smcConn->phase2_wait)
+ {
+ _IceErrorBadState (iceConn, _SmcOpcode,
+ SM_SaveYourselfPhase2, IceCanContinue);
+ }
+ else
+ {
+ CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smSaveYourselfPhase2Msg),
+ IceFatalToProtocol);
+
+ (*smcConn->phase2_wait->phase2_proc) (smcConn,
+ smcConn->phase2_wait->client_data);
+
+ free ((char *) smcConn->phase2_wait);
+ smcConn->phase2_wait = NULL;
+ }
+ break;
+
+ case SM_Interact:
+
+ if (!smcConn->interact_waits)
+ {
+ _IceErrorBadState (iceConn, _SmcOpcode,
+ SM_Interact, IceCanContinue);
+ }
+ else
+ {
+ _SmcInteractWait *next = smcConn->interact_waits->next;
+
+ CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smInteractMsg),
+ IceFatalToProtocol);
+
+ (*smcConn->interact_waits->interact_proc) (smcConn,
+ smcConn->interact_waits->client_data);
+
+ free ((char *) smcConn->interact_waits);
+ smcConn->interact_waits = next;
+ }
+ break;
+
+ case SM_SaveComplete:
+
+ if (!smcConn->save_yourself_in_progress)
+ {
+ _IceErrorBadState (iceConn, _SmcOpcode,
+ SM_SaveComplete, IceCanContinue);
+ }
+ else
+ {
+ CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smSaveCompleteMsg),
+ IceFatalToProtocol);
+
+ smcConn->save_yourself_in_progress = False;
+
+ (*smcConn->callbacks.save_complete.callback) (smcConn,
+ smcConn->callbacks.save_complete.client_data);
+ }
+ break;
+
+ case SM_Die:
+
+ CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smDieMsg),
+ IceFatalToProtocol);
+
+ (*smcConn->callbacks.die.callback) (smcConn,
+ smcConn->callbacks.die.client_data);
+ break;
+
+ case SM_ShutdownCancelled:
+
+ if (!smcConn->shutdown_in_progress)
+ {
+ _IceErrorBadState (iceConn, _SmcOpcode,
+ SM_ShutdownCancelled, IceCanContinue);
+ }
+ else
+ {
+ CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smShutdownCancelledMsg),
+ IceFatalToProtocol);
+
+ smcConn->shutdown_in_progress = False;
+
+ (*smcConn->callbacks.shutdown_cancelled.callback) (smcConn,
+ smcConn->callbacks.shutdown_cancelled.client_data);
+ }
+ break;
+
+ case SM_PropertiesReply:
+
+ if (!smcConn->prop_reply_waits)
+ {
+ _IceReadSkip (iceConn, length << 3);
+
+ _IceErrorBadState (iceConn, _SmcOpcode,
+ SM_PropertiesReply, IceCanContinue);
+ }
+ else
+ {
+ smPropertiesReplyMsg *pMsg;
+ char *pData, *pStart;
+ int numProps;
+ SmProp **props = NULL;
+ _SmcPropReplyWait *next;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
+ length, SIZEOF (smPropertiesReplyMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (smPropertiesReplyMsg),
+ smPropertiesReplyMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ pData = pStart;
+
+ SKIP_LISTOF_PROPERTY (pData, swap);
+
+ CHECK_COMPLETE_SIZE (iceConn, _SmcOpcode, opcode,
+ length, pData - pStart + SIZEOF (smPropertiesReplyMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ EXTRACT_LISTOF_PROPERTY (pData, swap, numProps, props);
+
+ next = smcConn->prop_reply_waits->next;
+
+ (*smcConn->prop_reply_waits->prop_reply_proc) (smcConn,
+ smcConn->prop_reply_waits->client_data, numProps, props);
+
+ free ((char *) smcConn->prop_reply_waits);
+ smcConn->prop_reply_waits = next;
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ }
+ break;
+
+ default:
+ {
+ _IceErrorBadMinor (iceConn, _SmcOpcode, opcode, IceCanContinue);
+ _IceReadSkip (iceConn, length << 3);
+ break;
+ }
+ }
+}
+
+
+
+void
+_SmsProcessMessage (iceConn, clientData, opcode, length, swap)
+
+IceConn iceConn;
+IcePointer clientData;
+int opcode;
+unsigned long length;
+Bool swap;
+
+{
+ SmsConn smsConn = (SmsConn) clientData;
+
+ if (!smsConn->client_id &&
+ opcode != SM_RegisterClient && opcode != SM_Error)
+ {
+ _IceReadSkip (iceConn, length << 3);
+
+ _IceErrorBadState (iceConn, _SmsOpcode, opcode, IceFatalToProtocol);
+
+ return;
+ }
+
+ switch (opcode)
+ {
+ case SM_Error:
+ {
+ iceErrorMsg *pMsg;
+ char *pData;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (iceErrorMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
+ iceErrorMsg, pMsg, pData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pData);
+ return;
+ }
+
+ if (swap)
+ {
+ pMsg->errorClass = lswaps (pMsg->errorClass);
+ pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
+ }
+
+ (*_SmsErrorHandler) (smsConn, swap,
+ pMsg->offendingMinorOpcode,
+ pMsg->offendingSequenceNum,
+ pMsg->errorClass, pMsg->severity,
+ (SmPointer) pData);
+
+ IceDisposeCompleteMessage (iceConn, pData);
+ break;
+ }
+
+ case SM_RegisterClient:
+ {
+ smRegisterClientMsg *pMsg;
+ char *pData, *pStart;
+ char *previousId;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smRegisterClientMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientMsg),
+ smRegisterClientMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ pData = pStart;
+
+ SKIP_ARRAY8 (pData, swap); /* previous id */
+
+ CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
+ length, pData - pStart + SIZEOF (smRegisterClientMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ EXTRACT_ARRAY8_AS_STRING (pData, swap, previousId);
+
+ if (*previousId == '\0')
+ {
+ free (previousId);
+ previousId = NULL;
+ }
+
+ if (!(*smsConn->callbacks.register_client.callback) (smsConn,
+ smsConn->callbacks.register_client.manager_data, previousId))
+ {
+ /*
+ * The previoudId was bad. Generate BadValue error.
+ */
+
+ int length = previousId ? strlen (previousId) : 0;
+ int bytes = ARRAY8_BYTES (length);
+
+ _IceErrorBadValue (smsConn->iceConn, _SmsOpcode, SM_RegisterClient,
+ 8, bytes, (IcePointer) pStart);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ break;
+ }
+
+ case SM_InteractRequest:
+
+ if (!smsConn->save_yourself_in_progress ||
+ smsConn->interaction_allowed == SmInteractStyleNone)
+ {
+ _IceErrorBadState (iceConn, _SmsOpcode,
+ SM_InteractRequest, IceCanContinue);
+ }
+ else
+ {
+ smInteractRequestMsg *pMsg;
+
+ CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smInteractRequestMsg),
+ IceFatalToProtocol);
+
+ IceReadSimpleMessage (iceConn, smInteractRequestMsg, pMsg);
+
+ if (pMsg->dialogType != SmDialogNormal &&
+ pMsg->dialogType != SmDialogError)
+ {
+ unsigned char errVal = pMsg->dialogType;
+
+ _IceErrorBadValue (iceConn, _SmsOpcode,
+ SM_InteractRequest, 2, 1, (IcePointer) &errVal);
+ }
+ else if (pMsg->dialogType == SmDialogNormal &&
+ smsConn->interaction_allowed != SmInteractStyleAny)
+ {
+ _IceErrorBadState (iceConn, _SmsOpcode,
+ SM_InteractRequest, IceCanContinue);
+ }
+ else
+ {
+ (*smsConn->callbacks.interact_request.callback) (smsConn,
+ smsConn->callbacks.interact_request.manager_data,
+ pMsg->dialogType);
+ }
+ }
+ break;
+
+ case SM_InteractDone:
+
+ if (!smsConn->interact_in_progress)
+ {
+ _IceErrorBadState (iceConn, _SmsOpcode,
+ SM_InteractDone, IceCanContinue);
+ }
+ else
+ {
+ smInteractDoneMsg *pMsg;
+
+ CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smInteractDoneMsg),
+ IceFatalToProtocol);
+
+ IceReadSimpleMessage (iceConn, smInteractDoneMsg, pMsg);
+
+ if (pMsg->cancelShutdown != 1 &&
+ pMsg->cancelShutdown != 0)
+ {
+ unsigned char errVal = pMsg->cancelShutdown;
+
+ _IceErrorBadValue (iceConn, _SmsOpcode,
+ SM_InteractDone, 2, 1, (IcePointer) &errVal);
+ }
+ else if (pMsg->cancelShutdown && !smsConn->can_cancel_shutdown)
+ {
+ _IceErrorBadState (iceConn, _SmsOpcode,
+ SM_InteractDone, IceCanContinue);
+ }
+ else
+ {
+ smsConn->interact_in_progress = False;
+
+ (*smsConn->callbacks.interact_done.callback) (smsConn,
+ smsConn->callbacks.interact_done.manager_data,
+ pMsg->cancelShutdown);
+ }
+ }
+ break;
+
+ case SM_SaveYourselfRequest:
+ {
+ smSaveYourselfRequestMsg *pMsg;
+ unsigned char errVal;
+ int errOffset = -1;
+
+ CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smSaveYourselfRequestMsg),
+ IceFatalToProtocol);
+
+ IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfRequestMsg),
+ smSaveYourselfRequestMsg, pMsg);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pMsg);
+ return;
+ }
+
+ if (pMsg->saveType != SmSaveGlobal &&
+ pMsg->saveType != SmSaveLocal &&
+ pMsg->saveType != SmSaveBoth)
+ {
+ errVal = pMsg->saveType;
+ errOffset = 8;
+ }
+ else if (pMsg->shutdown != 1 && pMsg->shutdown != 0)
+ {
+ errVal = pMsg->shutdown;
+ errOffset = 9;
+ }
+ else if (pMsg->interactStyle != SmInteractStyleNone &&
+ pMsg->interactStyle != SmInteractStyleErrors &&
+ pMsg->interactStyle != SmInteractStyleAny)
+ {
+ errVal = pMsg->interactStyle;
+ errOffset = 10;
+ }
+ else if (pMsg->fast != 1 && pMsg->fast != 0)
+ {
+ errVal = pMsg->fast;
+ errOffset = 11;
+ }
+ else if (pMsg->global != 1 && pMsg->global != 0)
+ {
+ errVal = pMsg->fast;
+ errOffset = 11;
+ }
+
+ if (errOffset >= 0)
+ {
+ _IceErrorBadValue (iceConn, _SmsOpcode,
+ SM_SaveYourselfRequest, errOffset, 1, (IcePointer) &errVal);
+ }
+ else
+ {
+ (*smsConn->callbacks.save_yourself_request.callback) (smsConn,
+ smsConn->callbacks.save_yourself_request.manager_data,
+ pMsg->saveType, pMsg->shutdown, pMsg->interactStyle,
+ pMsg->fast, pMsg->global);
+ }
+ break;
+ }
+
+ case SM_SaveYourselfPhase2Request:
+
+ if (!smsConn->save_yourself_in_progress)
+ {
+ _IceErrorBadState (iceConn, _SmsOpcode,
+ SM_SaveYourselfPhase2Request, IceCanContinue);
+ }
+ else
+ {
+ CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smSaveYourselfPhase2RequestMsg),
+ IceFatalToProtocol);
+
+ (*smsConn->callbacks.save_yourself_phase2_request.callback) (
+ smsConn, smsConn->callbacks.
+ save_yourself_phase2_request.manager_data);
+ }
+ break;
+
+ case SM_SaveYourselfDone:
+
+ if (!smsConn->save_yourself_in_progress)
+ {
+ _IceErrorBadState (iceConn, _SmsOpcode,
+ SM_SaveYourselfDone, IceCanContinue);
+ }
+ else
+ {
+ smSaveYourselfDoneMsg *pMsg;
+
+ CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smSaveYourselfDoneMsg),
+ IceFatalToProtocol);
+
+ IceReadSimpleMessage (iceConn, smSaveYourselfDoneMsg, pMsg);
+
+ if (pMsg->success != 1 && pMsg->success != 0)
+ {
+ unsigned char errVal = pMsg->success;
+
+ _IceErrorBadValue (iceConn, _SmsOpcode,
+ SM_SaveYourselfDone, 2, 1, (IcePointer) &errVal);
+ }
+ else
+ {
+ smsConn->save_yourself_in_progress = False;
+ smsConn->interaction_allowed = SmInteractStyleNone;
+
+ (*smsConn->callbacks.save_yourself_done.callback) (smsConn,
+ smsConn->callbacks.save_yourself_done.manager_data,
+ pMsg->success);
+ }
+ }
+ break;
+
+ case SM_CloseConnection:
+ {
+ smCloseConnectionMsg *pMsg;
+ char *pData, *pStart;
+ int count, i;
+ char **reasonMsgs = NULL;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smCloseConnectionMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (smCloseConnectionMsg),
+ smCloseConnectionMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ pData = pStart;
+
+ EXTRACT_CARD32 (pData, swap, count);
+ pData += 4;
+
+ for (i = 0; i < count; i++)
+ SKIP_ARRAY8 (pData, swap);
+
+ CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
+ length, pData - pStart + SIZEOF (smCloseConnectionMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart + 8;
+
+ reasonMsgs = (char **) malloc (count * sizeof (char *));
+ for (i = 0; i < count; i++)
+ EXTRACT_ARRAY8_AS_STRING (pData, swap, reasonMsgs[i]);
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ (*smsConn->callbacks.close_connection.callback) (smsConn,
+ smsConn->callbacks.close_connection.manager_data,
+ count, reasonMsgs);
+ break;
+ }
+
+ case SM_SetProperties:
+ {
+ smSetPropertiesMsg *pMsg;
+ char *pData, *pStart;
+ SmProp **props = NULL;
+ int numProps;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smSetPropertiesMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (smSetPropertiesMsg),
+ smSetPropertiesMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ pData = pStart;
+
+ SKIP_LISTOF_PROPERTY (pData, swap);
+
+ CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
+ length, pData - pStart + SIZEOF (smSetPropertiesMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ EXTRACT_LISTOF_PROPERTY (pData, swap, numProps, props);
+
+ (*smsConn->callbacks.set_properties.callback) (smsConn,
+ smsConn->callbacks.set_properties.manager_data, numProps, props);
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ break;
+ }
+
+ case SM_DeleteProperties:
+ {
+ smDeletePropertiesMsg *pMsg;
+ char *pData, *pStart;
+ int count, i;
+ char **propNames = NULL;
+
+ CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smDeletePropertiesMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (smDeletePropertiesMsg),
+ smDeletePropertiesMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ pData = pStart;
+
+ EXTRACT_CARD32 (pData, swap, count);
+ pData += 4;
+
+ for (i = 0; i < count; i++)
+ SKIP_ARRAY8 (pData, swap); /* prop names */
+
+ CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
+ length, pData - pStart + SIZEOF (smDeletePropertiesMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart + 8;
+
+ propNames = (char **) malloc (count * sizeof (char *));
+ for (i = 0; i < count; i++)
+ EXTRACT_ARRAY8_AS_STRING (pData, swap, propNames[i]);
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ (*smsConn->callbacks.delete_properties.callback) (smsConn,
+ smsConn->callbacks.delete_properties.manager_data,
+ count, propNames);
+
+ break;
+ }
+
+ case SM_GetProperties:
+
+ CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
+ length, SIZEOF (smGetPropertiesMsg),
+ IceFatalToProtocol);
+
+ (*smsConn->callbacks.get_properties.callback) (smsConn,
+ smsConn->callbacks.get_properties.manager_data);
+ break;
+
+ default:
+ {
+ _IceErrorBadMinor (iceConn, _SmsOpcode, opcode, IceCanContinue);
+ _IceReadSkip (iceConn, length << 3);
+ break;
+ }
+ }
+}