summaryrefslogtreecommitdiff
path: root/src
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
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
Diffstat (limited to 'src')
-rw-r--r--src/SMlibint.h520
-rw-r--r--src/globals.h62
-rw-r--r--src/sm_auth.c40
-rw-r--r--src/sm_client.c628
-rw-r--r--src/sm_error.c337
-rw-r--r--src/sm_genid.c171
-rw-r--r--src/sm_manager.c370
-rw-r--r--src/sm_misc.c214
-rw-r--r--src/sm_process.c875
9 files changed, 3217 insertions, 0 deletions
diff --git a/src/SMlibint.h b/src/SMlibint.h
new file mode 100644
index 0000000..030fc45
--- /dev/null
+++ b/src/SMlibint.h
@@ -0,0 +1,520 @@
+/* $Xorg: SMlibint.h,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
+ */
+
+#ifndef _SMLIBINT_H_
+#define _SMLIBINT_H_
+
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xmd.h>
+#include <X11/ICE/ICEmsg.h>
+#include <X11/ICE/ICEproto.h>
+#include <X11/SM/SMproto.h>
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/*
+ * Vendor & Release
+ */
+
+#define SmVendorString "MIT"
+#define SmReleaseString "1.0"
+
+
+/*
+ * Pad to a 64 bit boundary
+ */
+
+#define PAD64(_bytes) ((8 - ((unsigned int) (_bytes) % 8)) % 8)
+
+#define PADDED_BYTES64(_bytes) (_bytes + PAD64 (_bytes))
+
+
+/*
+ * Pad to 32 bit boundary
+ */
+
+#define PAD32(_bytes) ((4 - ((unsigned int) (_bytes) % 4)) % 4)
+
+#define PADDED_BYTES32(_bytes) (_bytes + PAD32 (_bytes))
+
+
+/*
+ * Number of 8 byte units in _bytes.
+ */
+
+#define WORD64COUNT(_bytes) (((unsigned int) ((_bytes) + 7)) >> 3)
+
+
+/*
+ * Compute the number of bytes for an ARRAY8 representation
+ */
+
+#define ARRAY8_BYTES(_len) (4 + _len + PAD64 (4 + _len))
+
+
+
+/*
+ * Byte swapping
+ */
+
+/* byte swap a long literal */
+#define lswapl(_val) ((((_val) & 0xff) << 24) |\
+ (((_val) & 0xff00) << 8) |\
+ (((_val) & 0xff0000) >> 8) |\
+ (((_val) >> 24) & 0xff))
+
+/* byte swap a short literal */
+#define lswaps(_val) ((((_val) & 0xff) << 8) | (((_val) >> 8) & 0xff))
+
+
+/*
+ * STORE macros
+ */
+
+#ifndef WORD64
+
+#define STORE_CARD32(_pBuf, _val) \
+{ \
+ *((CARD32 *) _pBuf) = _val; \
+ _pBuf += 4; \
+}
+
+#else /* WORD64 */
+
+#define STORE_CARD32(_pBuf, _val) \
+{ \
+ struct { \
+ int value :32; \
+ } _d; \
+ _d.value = _val; \
+ memcpy (_pBuf, &_d, 4); \
+ _pBuf += 4; \
+}
+
+#endif /* WORD64 */
+
+
+/*
+ * EXTRACT macros
+ */
+
+#ifndef WORD64
+
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD16 *) _pBuf); \
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_CARD32(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD32 *) _pBuf); \
+ _pBuf += 4; \
+ if (_swap) \
+ _val = lswapl (_val); \
+}
+
+#else /* WORD64 */
+
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \
+ _val <<= 8; \
+ _val |= *(_pBuf + 1) & 0xff;\
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_CARD32(_pBuf, _swap, _val) \
+{ \
+ _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \
+ _val <<= 8; \
+ _val |= *(_pBuf + 1) & 0xff;\
+ _val <<= 8; \
+ _val |= *(_pBuf + 2) & 0xff;\
+ _val <<= 8; \
+ _val |= *(_pBuf + 3) & 0xff;\
+ _pBuf += 4; \
+ if (_swap) \
+ _val = lswapl (_val); \
+}
+
+#endif /* WORD64 */
+
+
+/*
+ * Compute the number of bytes for a LISTofPROPERTY representation
+ */
+
+#define LISTOF_PROP_BYTES(_numProps, _props, _bytes) \
+{ \
+ int _i, _j; \
+ _bytes = 8; \
+ for (_i = 0; _i < _numProps; _i++) \
+ { \
+ _bytes += (8 + ARRAY8_BYTES (strlen (_props[_i]->name)) + \
+ ARRAY8_BYTES (strlen (_props[_i]->type))); \
+\
+ for (_j = 0; _j < _props[_i]->num_vals; _j++) \
+ _bytes += ARRAY8_BYTES (_props[_i]->vals[_j].length); \
+ } \
+}
+
+
+/*
+ * STORE FOO
+ */
+
+#define STORE_ARRAY8(_pBuf, _len, _array8) \
+{ \
+ STORE_CARD32 (_pBuf, _len); \
+ memcpy (_pBuf, _array8, _len); \
+ _pBuf += _len; \
+ if (PAD64 (4 + _len)) \
+ _pBuf += PAD64 (4 + _len); \
+}
+
+#define STORE_LISTOF_PROPERTY(_pBuf, _count, _props) \
+{ \
+ int _i, _j; \
+ STORE_CARD32 (_pBuf, _count); \
+ _pBuf += 4; \
+ for (_i = 0; _i < _count; _i++) \
+ { \
+ STORE_ARRAY8 (_pBuf, strlen (_props[_i]->name), _props[_i]->name); \
+ STORE_ARRAY8 (_pBuf, strlen (_props[_i]->type), _props[_i]->type); \
+ STORE_CARD32 (_pBuf, _props[_i]->num_vals); \
+ _pBuf += 4; \
+ for (_j = 0; _j < _props[_i]->num_vals; _j++) \
+ { \
+ STORE_ARRAY8 (_pBuf, _props[_i]->vals[_j].length, \
+ (char *) _props[_i]->vals[_j].value); \
+ } \
+ } \
+}
+
+
+/*
+ * EXTRACT FOO
+ */
+
+#define EXTRACT_ARRAY8(_pBuf, _swap, _len, _array8) \
+{ \
+ EXTRACT_CARD32 (_pBuf, _swap, _len); \
+ _array8 = (char *) malloc (_len + 1); \
+ memcpy (_array8, _pBuf, _len); \
+ _array8[_len] = '\0'; \
+ _pBuf += _len; \
+ if (PAD64 (4 + _len)) \
+ _pBuf += PAD64 (4 + _len); \
+}
+
+#define EXTRACT_ARRAY8_AS_STRING(_pBuf, _swap, _string) \
+{ \
+ CARD32 _len; \
+ EXTRACT_CARD32 (_pBuf, _swap, _len); \
+ _string = (char *) malloc (_len + 1); \
+ memcpy (_string, _pBuf, _len); \
+ _string[_len] = '\0'; \
+ _pBuf += _len; \
+ if (PAD64 (4 + _len)) \
+ _pBuf += PAD64 (4 + _len); \
+}
+
+#define EXTRACT_LISTOF_PROPERTY(_pBuf, _swap, _count, _props) \
+{ \
+ int _i, _j; \
+ EXTRACT_CARD32 (_pBuf, _swap, _count); \
+ _pBuf += 4; \
+ _props = (SmProp **) malloc (_count * sizeof (SmProp *)); \
+ for (_i = 0; _i < _count; _i++) \
+ { \
+ _props[_i] = (SmProp *) malloc (sizeof (SmProp)); \
+ EXTRACT_ARRAY8_AS_STRING (_pBuf, _swap, _props[_i]->name); \
+ EXTRACT_ARRAY8_AS_STRING (_pBuf, _swap, _props[_i]->type); \
+ EXTRACT_CARD32 (_pBuf, _swap, _props[_i]->num_vals); \
+ _pBuf += 4; \
+ _props[_i]->vals = (SmPropValue *) malloc ( \
+ _props[_i]->num_vals * sizeof (SmPropValue)); \
+ for (_j = 0; _j < _props[_i]->num_vals; _j++) \
+ { \
+ char *_temp; \
+ EXTRACT_ARRAY8 (_pBuf, _swap, _props[_i]->vals[_j].length, _temp);\
+ _props[_i]->vals[_j].value = (SmPointer) _temp; \
+ } \
+ } \
+}
+
+
+#define SKIP_ARRAY8(_pBuf, _swap) \
+{ \
+ CARD32 _len; \
+ EXTRACT_CARD32 (_pBuf, _swap, _len); \
+ _pBuf += _len; \
+ if (PAD64 (4 + _len)) \
+ _pBuf += PAD64 (4 + _len); \
+}
+
+#define SKIP_LISTOF_PROPERTY(_pBuf, _swap) \
+{ \
+ int _i, _j; \
+ CARD32 _count; \
+ EXTRACT_CARD32 (_pBuf, _swap, _count); \
+ _pBuf += 4; \
+ for (_i = 0; _i < _count; _i++) \
+ { \
+ CARD32 _numvals; \
+ SKIP_ARRAY8 (_pBuf, _swap); \
+ SKIP_ARRAY8 (_pBuf, _swap); \
+ EXTRACT_CARD32 (_pBuf, _swap, _numvals); \
+ _pBuf += 4; \
+ for (_j = 0; _j < _numvals; _j++) \
+ SKIP_ARRAY8 (_pBuf, _swap);\
+ } \
+}
+
+
+/*
+ * Client replies not processed by callbacks (we block for them).
+ */
+
+typedef struct {
+ Status status; /* if 1, client successfully registered */
+ char *client_id;
+} _SmcRegisterClientReply;
+
+
+/*
+ * Waiting for Interact
+ */
+
+typedef struct _SmcInteractWait {
+ SmcInteractProc interact_proc;
+ SmPointer client_data;
+ struct _SmcInteractWait *next;
+} _SmcInteractWait;
+
+
+/*
+ * Waiting for SaveYourselfPhase2
+ */
+
+typedef struct _SmcPhase2Wait {
+ SmcSaveYourselfPhase2Proc phase2_proc;
+ SmPointer client_data;
+} _SmcPhase2Wait;
+
+
+/*
+ * Waiting for Properties Reply
+ */
+
+typedef struct _SmcPropReplyWait {
+ SmcPropReplyProc prop_reply_proc;
+ SmPointer client_data;
+ struct _SmcPropReplyWait *next;
+} _SmcPropReplyWait;
+
+
+
+/*
+ * Client connection object
+ */
+
+struct _SmcConn {
+
+ /*
+ * Some state.
+ */
+
+ unsigned int save_yourself_in_progress : 1;
+ unsigned int shutdown_in_progress : 1;
+ unsigned int unused1 : 6; /* future use */
+ unsigned int unused2 : 8; /* future use */
+
+
+ /*
+ * We use ICE to esablish a connection with the SM.
+ */
+
+ IceConn iceConn;
+
+
+ /*
+ * Major and minor versions of the XSMP.
+ */
+
+ int proto_major_version;
+ int proto_minor_version;
+
+
+ /*
+ * The session manager vendor and release number.
+ */
+
+ char *vendor;
+ char *release;
+
+
+ /*
+ * The Client Id uniquely identifies this client to the session manager.
+ */
+
+ char *client_id;
+
+
+ /*
+ * Callbacks to be invoked when messages arrive from the session manager.
+ * These callbacks are specified at SmcOpenConnection time.
+ */
+
+ SmcCallbacks callbacks;
+
+
+ /*
+ * We keep track of all Interact Requests sent by the client. When the
+ * Interact message arrives, we remove it from the list (a FIFO list
+ * is maintained).
+ */
+
+ _SmcInteractWait *interact_waits;
+
+
+ /*
+ * If we send a SaveYourselfPhase2Request, we wait for SaveYourselfPhase2.
+ */
+
+ _SmcPhase2Wait *phase2_wait;
+
+
+ /*
+ * We keep track of all Get Properties sent by the client. When the
+ * Properties Reply arrives, we remove it from the list (a FIFO list
+ * is maintained).
+ */
+
+ _SmcPropReplyWait *prop_reply_waits;
+};
+
+
+
+/*
+ * Session manager connection object
+ */
+
+struct _SmsConn {
+
+ /*
+ * Some state.
+ */
+
+ unsigned int save_yourself_in_progress : 1;
+ unsigned int can_cancel_shutdown : 1;
+ unsigned int interact_in_progress : 1;
+ unsigned int unused1 : 5; /* future use */
+ unsigned int unused2 : 8; /* future use */
+
+
+ /*
+ * We use ICE to esablish a connection with the client.
+ */
+
+ IceConn iceConn;
+
+
+ /*
+ * Major and minor versions of the XSMP.
+ */
+
+ int proto_major_version;
+ int proto_minor_version;
+
+
+ /*
+ * The Client Id uniquely identifies this client to the session manager.
+ */
+
+ char *client_id;
+
+
+ /*
+ * Callbacks to be invoked when messages arrive from the client.
+ */
+
+ SmsCallbacks callbacks;
+
+
+ /*
+ * What type of interaction is allowed - SmInteractStyle{None,Errors,Any}
+ */
+
+ char interaction_allowed;
+};
+
+
+
+/*
+ * Extern declarations
+ */
+
+extern int _SmcOpcode;
+extern int _SmsOpcode;
+
+extern int _SmVersionCount;
+extern IcePoVersionRec _SmcVersions[];
+extern IcePaVersionRec _SmsVersions[];
+
+extern int _SmAuthCount;
+extern char *_SmAuthNames[];
+extern IcePoAuthProc _SmcAuthProcs[];
+extern IcePaAuthProc _SmsAuthProcs[];
+
+extern SmsNewClientProc _SmsNewClientProc;
+extern SmPointer _SmsNewClientData;
+
+extern SmcErrorHandler _SmcErrorHandler;
+extern SmsErrorHandler _SmsErrorHandler;
+
+#endif /* _SMLIBINT_H_ */
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 0000000..6cd12e4
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,62 @@
+/* $Xorg: globals.h,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
+ */
+
+extern void _SmcDefaultErrorHandler ();
+extern void _SmsDefaultErrorHandler ();
+
+extern IcePoAuthStatus _IcePoMagicCookie1Proc ();
+extern IcePaAuthStatus _IcePaMagicCookie1Proc ();
+
+extern void _SmcProcessMessage ();
+extern void _SmsProcessMessage ();
+
+int _SmcOpcode = 0;
+int _SmsOpcode = 0;
+
+int _SmVersionCount = 1;
+
+IcePoVersionRec _SmcVersions[] = {
+ {SmProtoMajor, SmProtoMinor, _SmcProcessMessage}};
+
+IcePaVersionRec _SmsVersions[] = {
+ {SmProtoMajor, SmProtoMinor, _SmsProcessMessage}};
+
+int _SmAuthCount = 1;
+char *_SmAuthNames[] = {"MIT-MAGIC-COOKIE-1"};
+IcePoAuthProc _SmcAuthProcs[] = {_IcePoMagicCookie1Proc};
+IcePaAuthProc _SmsAuthProcs[] = {_IcePaMagicCookie1Proc};
+
+SmsNewClientProc _SmsNewClientProc;
+SmPointer _SmsNewClientData;
+
+SmcErrorHandler _SmcErrorHandler = _SmcDefaultErrorHandler;
+SmsErrorHandler _SmsErrorHandler = _SmsDefaultErrorHandler;
diff --git a/src/sm_auth.c b/src/sm_auth.c
new file mode 100644
index 0000000..a709cda
--- /dev/null
+++ b/src/sm_auth.c
@@ -0,0 +1,40 @@
+/* $Xorg: sm_auth.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"
+
+/*
+ * For now, SMlib just supports MIT-MAGIC-COOKIE-1 (defined in ICElib).
+ */
+
+
diff --git a/src/sm_client.c b/src/sm_client.c
new file mode 100644
index 0000000..028262e
--- /dev/null
+++ b/src/sm_client.c
@@ -0,0 +1,628 @@
+/* $Xorg: sm_client.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"
+#include "globals.h"
+
+static void set_callbacks();
+
+
+SmcConn
+SmcOpenConnection (networkIdsList, context,
+ xsmpMajorRev, xsmpMinorRev, mask, callbacks,
+ previousId, clientIdRet, errorLength, errorStringRet)
+
+char *networkIdsList;
+SmPointer context;
+int xsmpMajorRev;
+int xsmpMinorRev;
+unsigned long mask;
+SmcCallbacks *callbacks;
+char *previousId;
+char **clientIdRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ SmcConn smcConn;
+ IceConn iceConn;
+ char *ids;
+ IceProtocolSetupStatus setupstat;
+ int majorVersion;
+ int minorVersion;
+ char *vendor = NULL;
+ char *release = NULL;
+ smRegisterClientMsg *pMsg;
+ char *pData;
+ int extra, len;
+ IceReplyWaitInfo replyWait;
+ _SmcRegisterClientReply reply;
+ Bool gotReply, ioErrorOccured;
+
+ *clientIdRet = NULL;
+
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ if (!_SmcOpcode)
+ {
+ /*
+ * For now, there is only one version of XSMP, so we don't
+ * have to check {xsmpMajorRev, xsmpMinorRev}. In the future,
+ * we will check against _SmcVersions and generate the list
+ * of versions the application actually supports.
+ */
+
+ if ((_SmcOpcode = IceRegisterForProtocolSetup ("XSMP",
+ SmVendorString, SmReleaseString, _SmVersionCount, _SmcVersions,
+ _SmAuthCount, _SmAuthNames, _SmcAuthProcs, NULL)) < 0)
+ {
+ strncpy (errorStringRet,
+ "Could not register XSMP protocol with ICE", errorLength);
+
+ return (NULL);
+ }
+ }
+
+ if (networkIdsList == NULL || *networkIdsList == '\0')
+ {
+ if ((ids = (char *) getenv ("SESSION_MANAGER")) == NULL)
+ {
+ strncpy (errorStringRet,
+ "SESSION_MANAGER environment variable not defined",
+ errorLength);
+
+ return (NULL);
+ }
+ }
+ else
+ {
+ ids = networkIdsList;
+ }
+
+ if ((iceConn = IceOpenConnection (
+ ids, context, 0, _SmcOpcode, errorLength, errorStringRet)) == NULL)
+ {
+ return (NULL);
+ }
+
+ if ((smcConn = (SmcConn) malloc (sizeof (struct _SmcConn))) == NULL)
+ {
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ IceCloseConnection (iceConn);
+ return (NULL);
+ }
+
+ setupstat = IceProtocolSetup (iceConn, _SmcOpcode,
+ (IcePointer) smcConn,
+ False /* mustAuthenticate */,
+ &majorVersion, &minorVersion,
+ &vendor, &release, errorLength, errorStringRet);
+
+ if (setupstat == IceProtocolSetupFailure ||
+ setupstat == IceProtocolSetupIOError)
+ {
+ IceCloseConnection (iceConn);
+ free ((char *) smcConn);
+ return (NULL);
+ }
+ else if (setupstat == IceProtocolAlreadyActive)
+ {
+ /*
+ * This case should never happen, because when we called
+ * IceOpenConnection, we required that the ICE connection
+ * may not already have XSMP active on it.
+ */
+
+ free ((char *) smcConn);
+ strncpy (errorStringRet, "Internal error in IceOpenConnection",
+ errorLength);
+ return (NULL);
+ }
+
+ smcConn->iceConn = iceConn;
+ smcConn->proto_major_version = majorVersion;
+ smcConn->proto_minor_version = minorVersion;
+ smcConn->vendor = vendor;
+ smcConn->release = release;
+ smcConn->client_id = NULL;
+
+ bzero ((char *) &smcConn->callbacks, sizeof (SmcCallbacks));
+ set_callbacks (smcConn, mask, callbacks);
+
+ smcConn->interact_waits = NULL;
+ smcConn->phase2_wait = NULL;
+ smcConn->prop_reply_waits = NULL;
+
+ smcConn->save_yourself_in_progress = False;
+ smcConn->shutdown_in_progress = False;
+
+
+ /*
+ * Now register the client
+ */
+
+ len = previousId ? strlen (previousId) : 0;
+ extra = ARRAY8_BYTES (len);
+
+ IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
+ SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
+ smRegisterClientMsg, pMsg, pData);
+
+ STORE_ARRAY8 (pData, len, previousId);
+
+ IceFlush (iceConn);
+
+ replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn);
+ replyWait.major_opcode_of_request = _SmcOpcode;
+ replyWait.minor_opcode_of_request = SM_RegisterClient;
+ replyWait.reply = (IcePointer) &reply;
+
+ gotReply = False;
+ ioErrorOccured = False;
+
+ while (!gotReply && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
+
+ if (ioErrorOccured)
+ {
+ strncpy (errorStringRet, "IO error occured opening connection",
+ errorLength);
+
+ free (smcConn->vendor);
+ free (smcConn->release);
+ free ((char *) smcConn);
+
+ return (NULL);
+ }
+ else if (gotReply)
+ {
+ if (reply.status == 1)
+ {
+ /*
+ * The client successfully registered.
+ */
+
+ *clientIdRet = reply.client_id;
+
+ smcConn->client_id = (char *) malloc (
+ strlen (*clientIdRet) + 1);
+
+ strcpy (smcConn->client_id, *clientIdRet);
+ }
+ else
+ {
+ /*
+ * Could not register the client because the previous ID
+ * was bad. So now we register the client with the
+ * previous ID set to NULL.
+ */
+
+ extra = ARRAY8_BYTES (0);
+
+ IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
+ SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
+ smRegisterClientMsg, pMsg, pData);
+
+ STORE_ARRAY8 (pData, 0, NULL);
+
+ IceFlush (iceConn);
+
+ replyWait.sequence_of_request =
+ IceLastSentSequenceNumber (iceConn);
+
+ gotReply = False;
+ }
+ }
+ }
+
+ return (smcConn);
+}
+
+
+
+SmcCloseStatus
+SmcCloseConnection (smcConn, count, reasonMsgs)
+
+SmcConn smcConn;
+int count;
+char **reasonMsgs;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smCloseConnectionMsg *pMsg;
+ char *pData;
+ int extra, i;
+ IceCloseStatus closeStatus;
+ SmcCloseStatus statusRet;
+
+ extra = 8;
+
+ for (i = 0; i < count; i++)
+ extra += ARRAY8_BYTES (strlen (reasonMsgs[i]));
+
+ IceGetHeaderExtra (iceConn, _SmcOpcode, SM_CloseConnection,
+ SIZEOF (smCloseConnectionMsg), WORD64COUNT (extra),
+ smCloseConnectionMsg, pMsg, pData);
+
+ STORE_CARD32 (pData, count);
+ pData += 4;
+
+ for (i = 0; i < count; i++)
+ STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]);
+
+ IceFlush (iceConn);
+
+ IceProtocolShutdown (iceConn, _SmcOpcode);
+ IceSetShutdownNegotiation (iceConn, False);
+ closeStatus = IceCloseConnection (iceConn);
+
+ if (smcConn->vendor)
+ free (smcConn->vendor);
+
+ if (smcConn->release)
+ free (smcConn->release);
+
+ if (smcConn->client_id)
+ free (smcConn->client_id);
+
+ if (smcConn->prop_reply_waits)
+ {
+ _SmcPropReplyWait *ptr = smcConn->prop_reply_waits;
+ _SmcPropReplyWait *next;
+
+ while (ptr)
+ {
+ next = ptr->next;
+ free ((char *) ptr);
+ ptr = next;
+ }
+
+ }
+
+ free ((char *) smcConn);
+
+ if (closeStatus == IceClosedNow)
+ statusRet = SmcClosedNow;
+ else if (closeStatus == IceClosedASAP)
+ statusRet = SmcClosedASAP;
+ else
+ statusRet = SmcConnectionInUse;
+
+ return (statusRet);
+}
+
+
+
+void
+SmcModifyCallbacks (smcConn, mask, callbacks)
+
+SmcConn smcConn;
+unsigned long mask;
+SmcCallbacks *callbacks;
+
+{
+ set_callbacks (smcConn, mask, callbacks);
+}
+
+
+
+void
+SmcSetProperties (smcConn, numProps, props)
+
+SmcConn smcConn;
+int numProps;
+SmProp **props;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smSetPropertiesMsg *pMsg;
+ char *pBuf;
+ char *pStart;
+ int bytes;
+
+ IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties,
+ SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg);
+
+ LISTOF_PROP_BYTES (numProps, props, bytes);
+ pMsg->length += WORD64COUNT (bytes);
+
+ pBuf = pStart = IceAllocScratch (iceConn, bytes);
+
+ STORE_LISTOF_PROPERTY (pBuf, numProps, props);
+
+ IceWriteData (iceConn, bytes, pStart);
+ IceFlush (iceConn);
+}
+
+
+
+void
+SmcDeleteProperties (smcConn, numProps, propNames)
+
+SmcConn smcConn;
+int numProps;
+char **propNames;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smDeletePropertiesMsg *pMsg;
+ char *pData;
+ int extra, i;
+
+ extra = 8;
+
+ for (i = 0; i < numProps; i++)
+ extra += ARRAY8_BYTES (strlen (propNames[i]));
+
+ IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties,
+ SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra),
+ smDeletePropertiesMsg, pMsg, pData);
+
+ STORE_CARD32 (pData, numProps);
+ pData += 4;
+
+ for (i = 0; i < numProps; i++)
+ STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]);
+
+ IceFlush (iceConn);
+}
+
+
+
+Status
+SmcGetProperties (smcConn, propReplyProc, clientData)
+
+SmcConn smcConn;
+SmcPropReplyProc propReplyProc;
+SmPointer clientData;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ _SmcPropReplyWait *wait, *ptr;
+
+ if ((wait = (_SmcPropReplyWait *) malloc (
+ sizeof (_SmcPropReplyWait))) == NULL)
+ {
+ return (0);
+ }
+
+ wait->prop_reply_proc = propReplyProc;
+ wait->client_data = clientData;
+ wait->next = NULL;
+
+ ptr = smcConn->prop_reply_waits;
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+
+ if (ptr == NULL)
+ smcConn->prop_reply_waits = wait;
+ else
+ ptr->next = wait;
+
+ IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties);
+ IceFlush (iceConn);
+
+ return (1);
+}
+
+
+
+Status
+SmcInteractRequest (smcConn, dialogType, interactProc, clientData)
+
+SmcConn smcConn;
+int dialogType;
+SmcInteractProc interactProc;
+SmPointer clientData;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smInteractRequestMsg *pMsg;
+ _SmcInteractWait *wait, *ptr;
+
+ if ((wait = (_SmcInteractWait *) malloc (
+ sizeof (_SmcInteractWait))) == NULL)
+ {
+ return (0);
+ }
+
+ wait->interact_proc = interactProc;
+ wait->client_data = clientData;
+ wait->next = NULL;
+
+ ptr = smcConn->interact_waits;
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+
+ if (ptr == NULL)
+ smcConn->interact_waits = wait;
+ else
+ ptr->next = wait;
+
+ IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest,
+ SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg);
+
+ pMsg->dialogType = dialogType;
+
+ IceFlush (iceConn);
+
+ return (1);
+}
+
+
+
+void
+SmcInteractDone (smcConn, cancelShutdown)
+
+SmcConn smcConn;
+Bool cancelShutdown;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smInteractDoneMsg *pMsg;
+
+ IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone,
+ SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg);
+
+ pMsg->cancelShutdown = cancelShutdown;
+
+ IceFlush (iceConn);
+}
+
+
+
+void
+SmcRequestSaveYourself (smcConn, saveType, shutdown, interactStyle,
+ fast, global)
+
+SmcConn smcConn;
+int saveType;
+Bool shutdown;
+int interactStyle;
+Bool fast;
+Bool global;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smSaveYourselfRequestMsg *pMsg;
+
+ IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest,
+ SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg);
+
+ pMsg->saveType = saveType;
+ pMsg->shutdown = shutdown;
+ pMsg->interactStyle = interactStyle;
+ pMsg->fast = fast;
+ pMsg->global = global;
+
+ IceFlush (iceConn);
+}
+
+
+
+Status
+SmcRequestSaveYourselfPhase2 (smcConn, saveYourselfPhase2Proc, clientData)
+
+SmcConn smcConn;
+SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc;
+SmPointer clientData;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ _SmcPhase2Wait *wait;
+
+ if (smcConn->phase2_wait)
+ wait = smcConn->phase2_wait;
+ else
+ {
+ if ((wait = (_SmcPhase2Wait *) malloc (
+ sizeof (_SmcPhase2Wait))) == NULL)
+ {
+ return (0);
+ }
+ }
+
+ wait->phase2_proc = saveYourselfPhase2Proc;
+ wait->client_data = clientData;
+
+ smcConn->phase2_wait = wait;
+
+ IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request);
+ IceFlush (iceConn);
+
+ return (1);
+}
+
+
+
+void
+SmcSaveYourselfDone (smcConn, success)
+
+SmcConn smcConn;
+Bool success;
+
+{
+ IceConn iceConn = smcConn->iceConn;
+ smSaveYourselfDoneMsg *pMsg;
+
+ IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone,
+ SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg);
+
+ pMsg->success = success;
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+set_callbacks (smcConn, mask, callbacks)
+
+SmcConn smcConn;
+unsigned long mask;
+SmcCallbacks *callbacks;
+
+{
+ if (mask & SmcSaveYourselfProcMask)
+ {
+ smcConn->callbacks.save_yourself.callback =
+ callbacks->save_yourself.callback;
+ smcConn->callbacks.save_yourself.client_data =
+ callbacks->save_yourself.client_data;
+ }
+
+ if (mask & SmcDieProcMask)
+ {
+ smcConn->callbacks.die.callback = callbacks->die.callback;
+ smcConn->callbacks.die.client_data = callbacks->die.client_data;
+ }
+
+ if (mask & SmcSaveCompleteProcMask)
+ {
+ smcConn->callbacks.save_complete.callback =
+ callbacks->save_complete.callback;
+ smcConn->callbacks.save_complete.client_data =
+ callbacks->save_complete.client_data;
+ }
+
+ if (mask & SmcShutdownCancelledProcMask)
+ {
+ smcConn->callbacks.shutdown_cancelled.callback =
+ callbacks->shutdown_cancelled.callback;
+ smcConn->callbacks.shutdown_cancelled.client_data =
+ callbacks->shutdown_cancelled.client_data;
+ }
+}
diff --git a/src/sm_error.c b/src/sm_error.c
new file mode 100644
index 0000000..241d587
--- /dev/null
+++ b/src/sm_error.c
@@ -0,0 +1,337 @@
+/* $Xorg: sm_error.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"
+#include <stdio.h>
+
+
+
+/*
+ * Default Smc error handler.
+ */
+
+void
+_SmcDefaultErrorHandler (smcConn, swap,
+ offendingMinorOpcode, offendingSequence,
+ errorClass, severity, values)
+
+SmcConn smcConn;
+Bool swap;
+int offendingMinorOpcode;
+unsigned long offendingSequence;
+int errorClass;
+int severity;
+SmPointer values;
+
+{
+ char *pData = (char *) values;
+ char *str;
+
+ switch (offendingMinorOpcode)
+ {
+ case SM_RegisterClient:
+ str = "RegisterClient";
+ break;
+ case SM_InteractRequest:
+ str = "InteractRequest";
+ break;
+ case SM_InteractDone:
+ str = "InteractDone";
+ break;
+ case SM_SaveYourselfDone:
+ str = "SaveYourselfDone";
+ break;
+ case SM_CloseConnection:
+ str = "CloseConnection";
+ break;
+ case SM_SetProperties:
+ str = "SetProperties";
+ break;
+ case SM_GetProperties:
+ str = "GetProperties";
+ break;
+ default:
+ str = "";
+ }
+
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, "XSMP error: Offending minor opcode = %d (%s)\n",
+ offendingMinorOpcode, str);
+
+ fprintf (stderr, " Offending sequence number = %d\n",
+ offendingSequence);
+
+ switch (errorClass)
+ {
+ case IceBadMinor:
+ str = "BadMinor";
+ break;
+ case IceBadState:
+ str = "BadState";
+ break;
+ case IceBadLength:
+ str = "BadLength";
+ break;
+ case IceBadValue:
+ str = "BadValue";
+ break;
+ default:
+ str = "???";
+ }
+
+ fprintf (stderr, " Error class = %s\n", str);
+
+ if (severity == IceCanContinue)
+ str = "CanContinue";
+ else if (severity == IceFatalToProtocol)
+ str = "FatalToProtocol";
+ else if (severity == IceFatalToConnection)
+ str = "FatalToConnection";
+ else
+ str = "???";
+
+ fprintf (stderr, " Severity = %s\n", str);
+
+ switch (errorClass)
+ {
+ case IceBadValue:
+ {
+ int offset, length, val;
+
+ EXTRACT_CARD32 (pData, swap, offset);
+ EXTRACT_CARD32 (pData, swap, length);
+
+ fprintf (stderr,
+ " BadValue Offset = %d\n", offset);
+ fprintf (stderr,
+ " BadValue Length = %d\n", length);
+
+ if (length <= 4)
+ {
+ if (length == 1)
+ val = (int) *pData;
+ else if (length == 2)
+ {
+ EXTRACT_CARD16 (pData, swap, val);
+ }
+ else
+ {
+ EXTRACT_CARD32 (pData, swap, val);
+ }
+
+ fprintf (stderr,
+ " BadValue = %d\n", val);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ fprintf (stderr, "\n");
+
+ if (severity != IceCanContinue)
+ exit (1);
+}
+
+
+
+/*
+ * Default Sms error handler.
+ */
+
+void
+_SmsDefaultErrorHandler (smsConn, swap,
+ offendingMinorOpcode, offendingSequence,
+ errorClass, severity, values)
+
+SmsConn smsConn;
+Bool swap;
+int offendingMinorOpcode;
+unsigned long offendingSequence;
+int errorClass;
+int severity;
+SmPointer values;
+
+{
+ char *pData = (char *) values;
+ char *str;
+
+ switch (offendingMinorOpcode)
+ {
+ case SM_SaveYourself:
+ str = "SaveYourself";
+ break;
+ case SM_Interact:
+ str = "Interact";
+ break;
+ case SM_Die:
+ str = "Die";
+ break;
+ case SM_ShutdownCancelled:
+ str = "ShutdownCancelled";
+ break;
+ default:
+ str = "";
+ }
+
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, "XSMP error: Offending minor opcode = %d (%s)\n",
+ offendingMinorOpcode, str);
+
+ fprintf (stderr, " Offending sequence number = %d\n",
+ offendingSequence);
+
+ switch (errorClass)
+ {
+ case IceBadMinor:
+ str = "BadMinor";
+ break;
+ case IceBadState:
+ str = "BadState";
+ break;
+ case IceBadLength:
+ str = "BadLength";
+ break;
+ case IceBadValue:
+ str = "BadValue";
+ break;
+ default:
+ str = "???";
+ }
+
+ fprintf (stderr, " Error class = %s\n", str);
+
+ if (severity == IceCanContinue)
+ str = "CanContinue";
+ else if (severity == IceFatalToProtocol)
+ str = "FatalToProtocol";
+ else if (severity == IceFatalToConnection)
+ str = "FatalToConnection";
+ else
+ str = "???";
+
+ fprintf (stderr, " Severity = %s\n", str);
+
+ switch (errorClass)
+ {
+ case IceBadValue:
+ {
+ int offset, length, val;
+
+ EXTRACT_CARD32 (pData, swap, offset);
+ EXTRACT_CARD32 (pData, swap, length);
+
+ fprintf (stderr,
+ " BadValue Offset = %d\n", offset);
+ fprintf (stderr,
+ " BadValue Length = %d\n", length);
+
+ if (length <= 4)
+ {
+ if (length == 1)
+ val = (int) *pData;
+ else if (length == 2)
+ {
+ EXTRACT_CARD16 (pData, swap, val);
+ }
+ else
+ {
+ EXTRACT_CARD32 (pData, swap, val);
+ }
+
+ fprintf (stderr,
+ " BadValue = %d\n", val);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ fprintf (stderr, "\n\n");
+
+ /* don't exit() - that would kill the SM - pretty devastating */
+}
+
+
+
+/*
+ * This procedure sets the Smc error handler to be the specified
+ * routine. If NULL is passed in the default error handler is restored.
+ * The function's return value is the previous error handler.
+ */
+
+SmcErrorHandler
+SmcSetErrorHandler (handler)
+
+SmcErrorHandler handler;
+
+{
+ SmcErrorHandler oldHandler = _SmcErrorHandler;
+
+ if (handler != NULL)
+ _SmcErrorHandler = handler;
+ else
+ _SmcErrorHandler = _SmcDefaultErrorHandler;
+
+ return (oldHandler);
+}
+
+
+
+/*
+ * This procedure sets the Sms error handler to be the specified
+ * routine. If NULL is passed in the default error handler is restored.
+ * The function's return value is the previous error handler.
+ */
+
+SmsErrorHandler
+SmsSetErrorHandler (handler)
+
+SmsErrorHandler handler;
+
+{
+ SmsErrorHandler oldHandler = _SmsErrorHandler;
+
+ if (handler != NULL)
+ _SmsErrorHandler = handler;
+ else
+ _SmsErrorHandler = _SmsDefaultErrorHandler;
+
+ return (oldHandler);
+}
diff --git a/src/sm_genid.c b/src/sm_genid.c
new file mode 100644
index 0000000..024e24f
--- /dev/null
+++ b/src/sm_genid.c
@@ -0,0 +1,171 @@
+/* $Xorg: sm_genid.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
+ */
+
+#ifdef WIN32
+#define _WILLWINSOCK_
+#endif
+#include <X11/SM/SMlib.h>
+#include "SMlibint.h"
+#include <X11/Xtrans.h>
+#ifdef XTHREADS
+#include <X11/Xthreads.h>
+#endif
+#include <stdio.h>
+
+#ifdef X_NOT_STDC_ENV
+#define Time_t long
+extern Time_t time ();
+#else
+#include <time.h>
+#define Time_t time_t
+#endif
+
+#ifndef WIN32
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#define XOS_USE_NO_LOCKING
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+#endif
+
+#else /* WIN32 */
+
+#include <X11/Xwinsock.h>
+#include <X11/Xw32defs.h>
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_MTSAFE_NETDBAPI
+#include <X11/Xos_r.h>
+
+#endif /* WIN32 */
+
+
+static char *hex_table[] = { /* for generating client IDs */
+ "00", "01", "02", "03", "04", "05", "06", "07",
+ "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
+ "10", "11", "12", "13", "14", "15", "16", "17",
+ "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
+ "20", "21", "22", "23", "24", "25", "26", "27",
+ "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
+ "30", "31", "32", "33", "34", "35", "36", "37",
+ "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
+ "40", "41", "42", "43", "44", "45", "46", "47",
+ "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
+ "50", "51", "52", "53", "54", "55", "56", "57",
+ "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
+ "60", "61", "62", "63", "64", "65", "66", "67",
+ "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
+ "70", "71", "72", "73", "74", "75", "76", "77",
+ "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
+ "80", "81", "82", "83", "84", "85", "86", "87",
+ "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
+ "90", "91", "92", "93", "94", "95", "96", "97",
+ "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
+ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
+ "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
+ "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
+ "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "da", "db", "dc", "dd", "de", "df",
+ "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
+ "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
+};
+
+
+
+char *
+SmsGenerateClientID (smsConn)
+
+SmsConn smsConn;
+
+{
+ char hostname[256];
+ char address[14];
+ char temp[256];
+ char *id;
+ static int sequence = 0;
+
+ if (gethostname (hostname, sizeof (hostname)))
+ return (NULL);
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ {
+ char* inet_addr;
+ char temp[4], *ptr1, *ptr2;
+ unsigned char decimal[4];
+ int i, len;
+ _Xgethostbynameparams hparams;
+ struct hostent *hostp;
+
+ if ((hostp = _XGethostbyname (hostname,hparams)) != NULL)
+ inet_addr = (char *) inet_ntoa (*(struct in_addr *)(hostp->h_addr));
+ else
+ return NULL;
+ for (i = 0, ptr1 = inet_addr; i < 3; i++)
+ {
+ ptr2 = strchr (ptr1, '.');
+ len = ptr2 - ptr1;
+ if (!ptr2 || len > 3)
+ return (NULL);
+ strncpy (temp, ptr1, len);
+ temp[len] = '\0';
+ decimal[i] = atoi (temp);
+ ptr1 = ptr2 + 1;
+ }
+
+ decimal[3] = atoi (ptr1);
+
+ address[0] = '1';
+ address[1] = '\0';
+ for (i = 0; i < 4; i++)
+ strcat (address, hex_table[decimal[i]]);
+ }
+#else
+ return (NULL);
+#endif
+
+ sprintf (temp, "1%s%.13ld%.10d%.4d", address, time((Time_t*)0),
+ getpid (), sequence);
+
+ if (++sequence > 9999)
+ sequence = 0;
+
+ if ((id = malloc (strlen (temp) + 1)) != NULL)
+ strcpy (id, temp);
+
+ return (id);
+}
diff --git a/src/sm_manager.c b/src/sm_manager.c
new file mode 100644
index 0000000..2f62b15
--- /dev/null
+++ b/src/sm_manager.c
@@ -0,0 +1,370 @@
+/* $Xorg: sm_manager.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"
+#include <X11/Xtrans.h>
+
+
+
+Status
+SmsInitialize (vendor, release, newClientProc, managerData,
+ hostBasedAuthProc, errorLength, errorStringRet)
+
+char *vendor;
+char *release;
+SmsNewClientProc newClientProc;
+SmPointer managerData;
+IceHostBasedAuthProc hostBasedAuthProc;
+int errorLength;
+char *errorStringRet;
+
+{
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ if (!newClientProc)
+ {
+ strncpy (errorStringRet,
+ "The SmsNewClientProc callback can't be NULL", errorLength);
+
+ return (0);
+ }
+
+ if (!_SmsOpcode)
+ {
+ Status _SmsProtocolSetupProc ();
+
+ if ((_SmsOpcode = IceRegisterForProtocolReply ("XSMP",
+ vendor, release, _SmVersionCount, _SmsVersions,
+ _SmAuthCount, _SmAuthNames, _SmsAuthProcs, hostBasedAuthProc,
+ _SmsProtocolSetupProc,
+ NULL, /* IceProtocolActivateProc - we don't care about
+ when the Protocol Reply is sent, because the
+ session manager can not immediately send a
+ message - it must wait for RegisterClient. */
+ NULL /* IceIOErrorProc */
+ )) < 0)
+ {
+ strncpy (errorStringRet,
+ "Could not register XSMP protocol with ICE", errorLength);
+
+ return (0);
+ }
+ }
+
+ _SmsNewClientProc = newClientProc;
+ _SmsNewClientData = managerData;
+
+ return (1);
+}
+
+
+
+Status
+_SmsProtocolSetupProc (iceConn,
+ majorVersion, minorVersion, vendor, release,
+ clientDataRet, failureReasonRet)
+
+IceConn iceConn;
+int majorVersion;
+int minorVersion;
+char *vendor;
+char *release;
+IcePointer *clientDataRet;
+char **failureReasonRet;
+
+{
+ SmsConn smsConn;
+ unsigned long mask;
+ Status status;
+
+ /*
+ * vendor/release are undefined for ProtocolSetup in XSMP.
+ */
+
+ if (vendor)
+ free (vendor);
+ if (release)
+ free (release);
+
+
+ /*
+ * Allocate new SmsConn.
+ */
+
+ if ((smsConn = (SmsConn) malloc (sizeof (struct _SmsConn))) == NULL)
+ {
+ char *str = "Memory allocation failed";
+
+ if ((*failureReasonRet = (char *) malloc (strlen (str) + 1)) != NULL)
+ strcpy (*failureReasonRet, str);
+
+ return (0);
+ }
+
+ smsConn->iceConn = iceConn;
+ smsConn->proto_major_version = majorVersion;
+ smsConn->proto_minor_version = minorVersion;
+ smsConn->client_id = NULL;
+
+ smsConn->save_yourself_in_progress = False;
+ smsConn->interaction_allowed = SmInteractStyleNone;
+ smsConn->can_cancel_shutdown = False;
+ smsConn->interact_in_progress = False;
+
+ *clientDataRet = (IcePointer) smsConn;
+
+
+ /*
+ * Now give the session manager the new smsConn and get back the
+ * callbacks to invoke when messages arrive from the client.
+ *
+ * In the future, we can use the mask return value to check
+ * if the SM is expecting an older rev of SMlib.
+ */
+
+ bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks));
+
+ status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData,
+ &mask, &smsConn->callbacks, failureReasonRet);
+
+ return (status);
+}
+
+
+
+char *
+SmsClientHostName (smsConn)
+
+SmsConn smsConn;
+
+{
+ return (_IceTransGetPeerNetworkId (smsConn->iceConn->trans_conn));
+}
+
+
+
+Status
+SmsRegisterClientReply (smsConn, clientId)
+
+SmsConn smsConn;
+char *clientId;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+ int extra;
+ smRegisterClientReplyMsg *pMsg;
+ char *pData;
+
+ if ((smsConn->client_id = (char *) malloc (strlen (clientId) + 1)) == NULL)
+ {
+ return (0);
+ }
+
+ strcpy (smsConn->client_id, clientId);
+
+ extra = ARRAY8_BYTES (strlen (clientId));
+
+ IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply,
+ SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra),
+ smRegisterClientReplyMsg, pMsg, pData);
+
+ STORE_ARRAY8 (pData, strlen (clientId), clientId);
+
+ IceFlush (iceConn);
+
+ return (1);
+}
+
+
+
+void
+SmsSaveYourself (smsConn, saveType, shutdown, interactStyle, fast)
+
+SmsConn smsConn;
+int saveType;
+Bool shutdown;
+int interactStyle;
+Bool fast;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+ smSaveYourselfMsg *pMsg;
+
+ IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself,
+ SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg);
+
+ pMsg->saveType = saveType;
+ pMsg->shutdown = shutdown;
+ pMsg->interactStyle = interactStyle;
+ pMsg->fast = fast;
+
+ IceFlush (iceConn);
+
+ smsConn->save_yourself_in_progress = True;
+
+ if (interactStyle == SmInteractStyleNone ||
+ interactStyle == SmInteractStyleErrors ||
+ interactStyle == SmInteractStyleAny)
+ {
+ smsConn->interaction_allowed = interactStyle;
+ }
+ else
+ {
+ smsConn->interaction_allowed = SmInteractStyleNone;
+ }
+
+ smsConn->can_cancel_shutdown = shutdown &&
+ (interactStyle == SmInteractStyleAny ||
+ interactStyle == SmInteractStyleErrors);
+}
+
+
+
+void
+SmsSaveYourselfPhase2 (smsConn)
+
+SmsConn smsConn;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+
+ IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
+ IceFlush (iceConn);
+}
+
+
+
+void
+SmsInteract (smsConn)
+
+SmsConn smsConn;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+
+ IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact);
+ IceFlush (iceConn);
+
+ smsConn->interact_in_progress = True;
+}
+
+
+
+void
+SmsDie (smsConn)
+
+SmsConn smsConn;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+
+ IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
+ IceFlush (iceConn);
+}
+
+
+
+void
+SmsSaveComplete (smsConn)
+
+SmsConn smsConn;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+
+ IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
+ IceFlush (iceConn);
+}
+
+
+
+void
+SmsShutdownCancelled (smsConn)
+
+SmsConn smsConn;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+
+ IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled);
+ IceFlush (iceConn);
+
+ smsConn->can_cancel_shutdown = False;
+}
+
+
+
+void
+SmsReturnProperties (smsConn, numProps, props)
+
+SmsConn smsConn;
+int numProps;
+SmProp **props;
+
+{
+ IceConn iceConn = smsConn->iceConn;
+ int bytes;
+ smPropertiesReplyMsg *pMsg;
+ char *pBuf;
+ char *pStart;
+
+ IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply,
+ SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg);
+
+ LISTOF_PROP_BYTES (numProps, props, bytes);
+ pMsg->length += WORD64COUNT (bytes);
+
+ pBuf = pStart = IceAllocScratch (iceConn, bytes);
+
+ STORE_LISTOF_PROPERTY (pBuf, numProps, props);
+
+ IceWriteData (iceConn, bytes, pStart);
+ IceFlush (iceConn);
+}
+
+
+
+void
+SmsCleanUp (smsConn)
+
+SmsConn smsConn;
+
+{
+ IceProtocolShutdown (smsConn->iceConn, _SmsOpcode);
+
+ if (smsConn->client_id)
+ free (smsConn->client_id);
+
+ free ((char *) smsConn);
+}
diff --git a/src/sm_misc.c b/src/sm_misc.c
new file mode 100644
index 0000000..9fc3e90
--- /dev/null
+++ b/src/sm_misc.c
@@ -0,0 +1,214 @@
+/* $Xorg: sm_misc.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"
+#include <stdio.h>
+
+/*
+ * Free property
+ */
+
+void
+SmFreeProperty (prop)
+
+SmProp *prop;
+
+{
+ if (prop)
+ {
+ int i;
+
+ if (prop->name)
+ free (prop->name);
+ if (prop->type)
+ free (prop->type);
+ if (prop->vals)
+ {
+ for (i = 0; i < prop->num_vals; i++)
+ if (prop->vals[i].value)
+ free ((char *) prop->vals[i].value);
+ free ((char *) prop->vals);
+ }
+
+ free ((char *) prop);
+ }
+}
+
+
+/*
+ * Free reason messages
+ */
+
+void
+SmFreeReasons (count, reasonMsgs)
+
+int count;
+char **reasonMsgs;
+
+{
+ if (reasonMsgs)
+ {
+ int i;
+
+ for (i = 0; i < count; i++)
+ free (reasonMsgs[i]);
+
+ free ((char *) reasonMsgs);
+ }
+}
+
+
+
+/*
+ * Smc informational functions
+ */
+
+int
+SmcProtocolVersion (smcConn)
+
+SmcConn smcConn;
+
+{
+ return (smcConn->proto_major_version);
+}
+
+
+int
+SmcProtocolRevision (smcConn)
+
+SmcConn smcConn;
+
+{
+ return (smcConn->proto_minor_version);
+}
+
+
+char *
+SmcVendor (smcConn)
+
+SmcConn smcConn;
+
+{
+ char *string = (char *) malloc (strlen (smcConn->vendor) + 1);
+
+ strcpy (string, smcConn->vendor);
+
+ return (string);
+}
+
+
+char *
+SmcRelease (smcConn)
+
+SmcConn smcConn;
+
+{
+ char *string = (char *) malloc (strlen (smcConn->release) + 1);
+
+ strcpy (string, smcConn->release);
+
+ return (string);
+}
+
+
+char *
+SmcClientID (smcConn)
+
+SmcConn smcConn;
+
+{
+ char *clientId = (char *) malloc (strlen (smcConn->client_id) + 1);
+
+ strcpy (clientId, smcConn->client_id);
+
+ return (clientId);
+}
+
+
+IceConn
+SmcGetIceConnection (smcConn)
+
+SmcConn smcConn;
+
+{
+ return (smcConn->iceConn);
+}
+
+
+
+/*
+ * Sms informational functions
+ */
+
+int
+SmsProtocolVersion (smsConn)
+
+SmsConn smsConn;
+
+{
+ return (smsConn->proto_major_version);
+}
+
+
+int
+SmsProtocolRevision (smsConn)
+
+SmsConn smsConn;
+
+{
+ return (smsConn->proto_minor_version);
+}
+
+
+char *
+SmsClientID (smsConn)
+
+SmsConn smsConn;
+
+{
+ char *clientId = (char *) malloc (strlen (smsConn->client_id) + 1);
+
+ strcpy (clientId, smsConn->client_id);
+
+ return (clientId);
+}
+
+
+IceConn
+SmsGetIceConnection (smsConn)
+
+SmsConn smsConn;
+
+{
+ return (smsConn->iceConn);
+}
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;
+ }
+ }
+}