diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/SMlibint.h | 520 | ||||
-rw-r--r-- | src/globals.h | 62 | ||||
-rw-r--r-- | src/sm_auth.c | 40 | ||||
-rw-r--r-- | src/sm_client.c | 628 | ||||
-rw-r--r-- | src/sm_error.c | 337 | ||||
-rw-r--r-- | src/sm_genid.c | 171 | ||||
-rw-r--r-- | src/sm_manager.c | 370 | ||||
-rw-r--r-- | src/sm_misc.c | 214 | ||||
-rw-r--r-- | src/sm_process.c | 875 |
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; + } + } +} |