1126a8a12Smrg/*
2126a8a12Smrg
3126a8a12SmrgCopyright 1993, 1998  The Open Group
4126a8a12Smrg
5126a8a12SmrgPermission to use, copy, modify, distribute, and sell this software and its
6126a8a12Smrgdocumentation for any purpose is hereby granted without fee, provided that
7126a8a12Smrgthe above copyright notice appear in all copies and that both that
8126a8a12Smrgcopyright notice and this permission notice appear in supporting
9126a8a12Smrgdocumentation.
10126a8a12Smrg
11126a8a12SmrgThe above copyright notice and this permission notice shall be included in
12126a8a12Smrgall copies or substantial portions of the Software.
13126a8a12Smrg
14126a8a12SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15126a8a12SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16126a8a12SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17126a8a12SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18126a8a12SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19126a8a12SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20126a8a12Smrg
21126a8a12SmrgExcept as contained in this notice, the name of The Open Group shall not be
22126a8a12Smrgused in advertising or otherwise to promote the sale, use or other dealings
23126a8a12Smrgin this Software without prior written authorization from The Open Group.
24126a8a12Smrg
25126a8a12Smrg*/
26126a8a12Smrg
27126a8a12Smrg/*
28126a8a12Smrg * Author: Ralph Mor, X Consortium
29126a8a12Smrg */
30126a8a12Smrg
31126a8a12Smrg#ifdef HAVE_CONFIG_H
32126a8a12Smrg#include <config.h>
33126a8a12Smrg#endif
34126a8a12Smrg#include <X11/SM/SMlib.h>
35126a8a12Smrg#include "SMlibint.h"
36126a8a12Smrg
37d656433aSmrgint 	_SmcOpcode = 0;
38d656433aSmrgint 	_SmsOpcode = 0;
39d656433aSmrg
40d656433aSmrgSmsNewClientProc _SmsNewClientProc;
41d656433aSmrgSmPointer        _SmsNewClientData;
42d656433aSmrg
43d656433aSmrgSmcErrorHandler _SmcErrorHandler = _SmcDefaultErrorHandler;
44d656433aSmrgSmsErrorHandler _SmsErrorHandler = _SmsDefaultErrorHandler;
45d656433aSmrg
46d656433aSmrg
47d656433aSmrgstatic void
48d656433aSmrgset_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks);
49126a8a12Smrg
50126a8a12Smrg
51126a8a12SmrgSmcConn
52d656433aSmrgSmcOpenConnection(char *networkIdsList, SmPointer context,
53d656433aSmrg		  int xsmpMajorRev, int xsmpMinorRev,
54d656433aSmrg		  unsigned long mask, SmcCallbacks *callbacks,
550a6b08f8Smrg		  const char *previousId, char **clientIdRet,
56d656433aSmrg		  int errorLength, char *errorStringRet)
57126a8a12Smrg{
58126a8a12Smrg    SmcConn			smcConn;
59126a8a12Smrg    IceConn			iceConn;
60126a8a12Smrg    char 			*ids;
61126a8a12Smrg    IceProtocolSetupStatus	setupstat;
62126a8a12Smrg    int				majorVersion;
63126a8a12Smrg    int				minorVersion;
64126a8a12Smrg    char			*vendor = NULL;
65126a8a12Smrg    char			*release = NULL;
66126a8a12Smrg    smRegisterClientMsg 	*pMsg;
67126a8a12Smrg    char 			*pData;
680a6b08f8Smrg    unsigned int		extra, len;
69126a8a12Smrg    IceReplyWaitInfo		replyWait;
70126a8a12Smrg    _SmcRegisterClientReply	reply;
71126a8a12Smrg    Bool			gotReply, ioErrorOccured;
72126a8a12Smrg
73126a8a12Smrg    const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"};
74126a8a12Smrg    IcePoAuthProc auth_procs[] = {_IcePoMagicCookie1Proc};
75126a8a12Smrg    int auth_count = 1;
76126a8a12Smrg
77126a8a12Smrg    IcePoVersionRec versions[] = {
78126a8a12Smrg        {SmProtoMajor, SmProtoMinor, _SmcProcessMessage}
79126a8a12Smrg    };
80126a8a12Smrg    int version_count = 1;
81126a8a12Smrg
82126a8a12Smrg
83126a8a12Smrg    *clientIdRet = NULL;
84126a8a12Smrg
85126a8a12Smrg    if (errorStringRet && errorLength > 0)
86126a8a12Smrg	*errorStringRet = '\0';
87126a8a12Smrg
88126a8a12Smrg    if (!_SmcOpcode)
89126a8a12Smrg    {
90126a8a12Smrg	/*
91126a8a12Smrg	 * For now, there is only one version of XSMP, so we don't
92126a8a12Smrg	 * have to check {xsmpMajorRev, xsmpMinorRev}.  In the future,
93126a8a12Smrg	 * we will check against versions and generate the list
94126a8a12Smrg	 * of versions the application actually supports.
95126a8a12Smrg	 */
96126a8a12Smrg
97126a8a12Smrg	if ((_SmcOpcode = IceRegisterForProtocolSetup ("XSMP",
98126a8a12Smrg	    SmVendorString, SmReleaseString, version_count, versions,
99126a8a12Smrg            auth_count, auth_names, auth_procs, NULL)) < 0)
100126a8a12Smrg	{
101126a8a12Smrg	    if (errorStringRet && errorLength > 0) {
102126a8a12Smrg		strncpy (errorStringRet,
103126a8a12Smrg			 "Could not register XSMP protocol with ICE",
104126a8a12Smrg			 errorLength);
105126a8a12Smrg		errorStringRet[errorLength - 1] = '\0';
106126a8a12Smrg	    }
107126a8a12Smrg
108126a8a12Smrg	    return (NULL);
109126a8a12Smrg	}
110126a8a12Smrg    }
111126a8a12Smrg
112126a8a12Smrg    if (networkIdsList == NULL || *networkIdsList == '\0')
113126a8a12Smrg    {
1146bea0e4fSmrg	if ((ids = getenv ("SESSION_MANAGER")) == NULL)
115126a8a12Smrg	{
116126a8a12Smrg	    if (errorStringRet && errorLength > 0) {
117126a8a12Smrg		strncpy (errorStringRet,
118126a8a12Smrg			 "SESSION_MANAGER environment variable not defined",
119126a8a12Smrg			 errorLength);
120126a8a12Smrg		errorStringRet[errorLength - 1] = '\0';
121126a8a12Smrg	    }
122126a8a12Smrg	    return (NULL);
123126a8a12Smrg	}
124126a8a12Smrg    }
125126a8a12Smrg    else
126126a8a12Smrg    {
127126a8a12Smrg	ids = networkIdsList;
128126a8a12Smrg    }
129126a8a12Smrg
130126a8a12Smrg    if ((iceConn = IceOpenConnection (
131126a8a12Smrg	ids, context, 0, _SmcOpcode, errorLength, errorStringRet)) == NULL)
132126a8a12Smrg    {
133126a8a12Smrg	return (NULL);
134126a8a12Smrg    }
135126a8a12Smrg
1363c15da26Smrg    if ((smcConn = malloc (sizeof (struct _SmcConn))) == NULL)
137126a8a12Smrg    {
138126a8a12Smrg	if (errorStringRet && errorLength > 0) {
139126a8a12Smrg	    strncpy (errorStringRet, "Can't malloc", errorLength);
140126a8a12Smrg	    errorStringRet[errorLength - 1] = '\0';
141126a8a12Smrg	}
142126a8a12Smrg	IceCloseConnection (iceConn);
143126a8a12Smrg	return (NULL);
144126a8a12Smrg    }
145126a8a12Smrg
146126a8a12Smrg    setupstat = IceProtocolSetup (iceConn, _SmcOpcode,
147126a8a12Smrg	(IcePointer) smcConn,
148126a8a12Smrg	False /* mustAuthenticate */,
149126a8a12Smrg	&majorVersion, &minorVersion,
150126a8a12Smrg	&vendor, &release, errorLength, errorStringRet);
151126a8a12Smrg
152126a8a12Smrg    if (setupstat == IceProtocolSetupFailure ||
153126a8a12Smrg	setupstat == IceProtocolSetupIOError)
154126a8a12Smrg    {
155126a8a12Smrg	IceCloseConnection (iceConn);
1563c15da26Smrg	free (smcConn);
157126a8a12Smrg	return (NULL);
158126a8a12Smrg    }
159126a8a12Smrg    else if (setupstat == IceProtocolAlreadyActive)
160126a8a12Smrg    {
161126a8a12Smrg	/*
162126a8a12Smrg	 * This case should never happen, because when we called
163126a8a12Smrg	 * IceOpenConnection, we required that the ICE connection
164126a8a12Smrg	 * may not already have XSMP active on it.
165126a8a12Smrg	 */
166126a8a12Smrg
1673c15da26Smrg	free (smcConn);
168126a8a12Smrg	if (errorStringRet && errorLength > 0) {
169126a8a12Smrg	    strncpy (errorStringRet, "Internal error in IceOpenConnection",
170126a8a12Smrg		     errorLength);
171126a8a12Smrg	    errorStringRet[errorLength - 1] = '\0';
172126a8a12Smrg	}
173126a8a12Smrg	return (NULL);
174126a8a12Smrg    }
175126a8a12Smrg
176126a8a12Smrg    smcConn->iceConn = iceConn;
177126a8a12Smrg    smcConn->proto_major_version = majorVersion;
178126a8a12Smrg    smcConn->proto_minor_version = minorVersion;
179126a8a12Smrg    smcConn->vendor = vendor;
180126a8a12Smrg    smcConn->release = release;
181126a8a12Smrg    smcConn->client_id = NULL;
182126a8a12Smrg
183126a8a12Smrg    bzero ((char *) &smcConn->callbacks, sizeof (SmcCallbacks));
184126a8a12Smrg    set_callbacks (smcConn, mask, callbacks);
185126a8a12Smrg
186126a8a12Smrg    smcConn->interact_waits = NULL;
187126a8a12Smrg    smcConn->phase2_wait = NULL;
188126a8a12Smrg    smcConn->prop_reply_waits = NULL;
189126a8a12Smrg
190126a8a12Smrg    smcConn->save_yourself_in_progress = False;
191126a8a12Smrg    smcConn->shutdown_in_progress = False;
192126a8a12Smrg
193126a8a12Smrg
194126a8a12Smrg    /*
195126a8a12Smrg     * Now register the client
196126a8a12Smrg     */
197126a8a12Smrg
198d656433aSmrg    if (!previousId)
199d656433aSmrg	previousId = "";
200d656433aSmrg    len = strlen (previousId);
201126a8a12Smrg    extra = ARRAY8_BYTES (len);
202126a8a12Smrg
203126a8a12Smrg    IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
204126a8a12Smrg	SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
205126a8a12Smrg	smRegisterClientMsg, pMsg, pData);
206126a8a12Smrg
2073fb97780Smrg    if (pData != NULL) {
2083fb97780Smrg	STORE_ARRAY8 (pData, len, previousId);
2093fb97780Smrg	IceFlush (iceConn);
2103fb97780Smrg    }
2113fb97780Smrg    else {
2123fb97780Smrg	SEND_ARRAY8 (iceConn, len, previousId);
2133fb97780Smrg    }
214126a8a12Smrg
215126a8a12Smrg    replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn);
216126a8a12Smrg    replyWait.major_opcode_of_request = _SmcOpcode;
217126a8a12Smrg    replyWait.minor_opcode_of_request = SM_RegisterClient;
218126a8a12Smrg    replyWait.reply = (IcePointer) &reply;
219126a8a12Smrg
220126a8a12Smrg    gotReply = False;
221126a8a12Smrg    ioErrorOccured = False;
222126a8a12Smrg
223126a8a12Smrg    while (!gotReply && !ioErrorOccured)
224126a8a12Smrg    {
225126a8a12Smrg	ioErrorOccured = (IceProcessMessages (
226126a8a12Smrg	    iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
227126a8a12Smrg
228126a8a12Smrg	if (ioErrorOccured)
229126a8a12Smrg	{
230126a8a12Smrg	    if (errorStringRet && errorLength > 0) {
2313fb97780Smrg		strncpy (errorStringRet, "IO error occurred opening connection",
232126a8a12Smrg			 errorLength);
233126a8a12Smrg		errorStringRet[errorLength - 1] = '\0';
234126a8a12Smrg	    }
235126a8a12Smrg	    free (smcConn->vendor);
236126a8a12Smrg	    free (smcConn->release);
2373c15da26Smrg	    free (smcConn);
238126a8a12Smrg
239126a8a12Smrg	    return (NULL);
240126a8a12Smrg	}
241126a8a12Smrg	else if (gotReply)
242126a8a12Smrg	{
243126a8a12Smrg	    if (reply.status == 1)
244126a8a12Smrg	    {
245126a8a12Smrg		/*
246126a8a12Smrg		 * The client successfully registered.
247126a8a12Smrg		 */
248126a8a12Smrg
249126a8a12Smrg		*clientIdRet = reply.client_id;
250126a8a12Smrg
2513c15da26Smrg		smcConn->client_id = strdup (*clientIdRet);
252126a8a12Smrg	    }
253126a8a12Smrg	    else
254126a8a12Smrg	    {
255126a8a12Smrg		/*
256126a8a12Smrg		 * Could not register the client because the previous ID
257126a8a12Smrg		 * was bad.  So now we register the client with the
258126a8a12Smrg		 * previous ID set to NULL.
259126a8a12Smrg		 */
260126a8a12Smrg
261126a8a12Smrg		extra = ARRAY8_BYTES (0);
262126a8a12Smrg
263126a8a12Smrg		IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
264126a8a12Smrg		    SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
265126a8a12Smrg		    smRegisterClientMsg, pMsg, pData);
266126a8a12Smrg
2673fb97780Smrg		if (pData != NULL) {
2683fb97780Smrg		    STORE_ARRAY8 (pData, 0, "");
2693fb97780Smrg		    IceFlush (iceConn);
2703fb97780Smrg		}
2713fb97780Smrg		else {
2723fb97780Smrg		    SEND_ARRAY8 (iceConn, 0, "");
2733fb97780Smrg		}
274126a8a12Smrg
275126a8a12Smrg		replyWait.sequence_of_request =
276126a8a12Smrg		    IceLastSentSequenceNumber (iceConn);
277126a8a12Smrg
278126a8a12Smrg		gotReply = False;
279126a8a12Smrg	    }
280126a8a12Smrg	}
281126a8a12Smrg    }
282126a8a12Smrg
283126a8a12Smrg    return (smcConn);
284126a8a12Smrg}
285126a8a12Smrg
286126a8a12Smrg
287126a8a12Smrg
288126a8a12SmrgSmcCloseStatus
289d656433aSmrgSmcCloseConnection(SmcConn smcConn, int count, char **reasonMsgs)
290126a8a12Smrg{
291126a8a12Smrg    IceConn			iceConn = smcConn->iceConn;
292126a8a12Smrg    smCloseConnectionMsg 	*pMsg;
293126a8a12Smrg    char 			*pData;
294126a8a12Smrg    int				extra, i;
295126a8a12Smrg    IceCloseStatus	        closeStatus;
296126a8a12Smrg    SmcCloseStatus		statusRet;
297126a8a12Smrg
298126a8a12Smrg    extra = 8;
299126a8a12Smrg
300126a8a12Smrg    for (i = 0; i < count; i++)
301126a8a12Smrg	extra += ARRAY8_BYTES (strlen (reasonMsgs[i]));
302126a8a12Smrg
303126a8a12Smrg    IceGetHeaderExtra (iceConn, _SmcOpcode, SM_CloseConnection,
304126a8a12Smrg	SIZEOF (smCloseConnectionMsg), WORD64COUNT (extra),
305126a8a12Smrg	smCloseConnectionMsg, pMsg, pData);
306126a8a12Smrg
3073fb97780Smrg    if (pData != NULL) {
3083fb97780Smrg	STORE_CARD32 (pData, (CARD32) count);
3093fb97780Smrg	STORE_CARD32 (pData, (CARD32) 0); /* padding */
310126a8a12Smrg
3113fb97780Smrg	for (i = 0; i < count; i++)
3123fb97780Smrg	    STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]);
313126a8a12Smrg
3143fb97780Smrg	IceFlush (iceConn);
3153fb97780Smrg    } else {
3163fb97780Smrg	CARD32 count_header[2] = {
3173fb97780Smrg	    (CARD32) count,
3183fb97780Smrg	    (CARD32) 0 /* padding */
3193fb97780Smrg	};
3203fb97780Smrg	IceWriteData32 (iceConn, 8, count_header);
3213fb97780Smrg
3223fb97780Smrg	for (i = 0; i < count; i++)
3233fb97780Smrg	    SEND_ARRAY8 (iceConn, strlen (reasonMsgs[i]), reasonMsgs[i]);
3243fb97780Smrg    }
325126a8a12Smrg
326126a8a12Smrg    IceProtocolShutdown (iceConn, _SmcOpcode);
327126a8a12Smrg    IceSetShutdownNegotiation (iceConn, False);
328126a8a12Smrg    closeStatus = IceCloseConnection (iceConn);
329126a8a12Smrg
330126a8a12Smrg    if (smcConn->vendor)
331126a8a12Smrg	free (smcConn->vendor);
332126a8a12Smrg
333126a8a12Smrg    if (smcConn->release)
334126a8a12Smrg	free (smcConn->release);
335126a8a12Smrg
336126a8a12Smrg    if (smcConn->client_id)
337126a8a12Smrg	free (smcConn->client_id);
338126a8a12Smrg
3393fb97780Smrg    if (smcConn->interact_waits)
3403fb97780Smrg    {
3413fb97780Smrg	_SmcInteractWait *ptr = smcConn->interact_waits;
3423fb97780Smrg	_SmcInteractWait *next;
3433fb97780Smrg
3443fb97780Smrg	while (ptr)
3453fb97780Smrg	{
3463fb97780Smrg	    next = ptr->next;
3473fb97780Smrg	    free (ptr);
3483fb97780Smrg	    ptr = next;
3493fb97780Smrg	}
3503fb97780Smrg    }
3513fb97780Smrg
3523fb97780Smrg    if (smcConn->phase2_wait)
3533fb97780Smrg	free (smcConn->phase2_wait);
3543fb97780Smrg
355126a8a12Smrg    if (smcConn->prop_reply_waits)
356126a8a12Smrg    {
357126a8a12Smrg	_SmcPropReplyWait *ptr = smcConn->prop_reply_waits;
358126a8a12Smrg	_SmcPropReplyWait *next;
359126a8a12Smrg
360126a8a12Smrg	while (ptr)
361126a8a12Smrg	{
362126a8a12Smrg	    next = ptr->next;
3633c15da26Smrg	    free (ptr);
364126a8a12Smrg	    ptr = next;
365126a8a12Smrg	}
3663c15da26Smrg
367126a8a12Smrg    }
368126a8a12Smrg
3693c15da26Smrg    free (smcConn);
370126a8a12Smrg
371126a8a12Smrg    if (closeStatus == IceClosedNow)
372126a8a12Smrg	statusRet = SmcClosedNow;
373126a8a12Smrg    else if (closeStatus == IceClosedASAP)
374126a8a12Smrg	statusRet = SmcClosedASAP;
375126a8a12Smrg    else
376126a8a12Smrg	statusRet = SmcConnectionInUse;
377126a8a12Smrg
378126a8a12Smrg    return (statusRet);
379126a8a12Smrg}
380126a8a12Smrg
381126a8a12Smrg
382126a8a12Smrg
383126a8a12Smrgvoid
384d656433aSmrgSmcModifyCallbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks)
385126a8a12Smrg{
386126a8a12Smrg    set_callbacks (smcConn, mask, callbacks);
387126a8a12Smrg}
388126a8a12Smrg
389126a8a12Smrg
390126a8a12Smrg
391126a8a12Smrgvoid
392d656433aSmrgSmcSetProperties(SmcConn smcConn, int numProps, SmProp **props)
393126a8a12Smrg{
394126a8a12Smrg    IceConn		iceConn = smcConn->iceConn;
395126a8a12Smrg    smSetPropertiesMsg	*pMsg;
396126a8a12Smrg    char		*pBuf;
397126a8a12Smrg    char		*pStart;
3980a6b08f8Smrg    unsigned int	bytes;
399126a8a12Smrg
400126a8a12Smrg    IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties,
401126a8a12Smrg	SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg);
402126a8a12Smrg
403126a8a12Smrg    LISTOF_PROP_BYTES (numProps, props, bytes);
404126a8a12Smrg    pMsg->length += WORD64COUNT (bytes);
405126a8a12Smrg
406126a8a12Smrg    pBuf = pStart = IceAllocScratch (iceConn, bytes);
407d656433aSmrg    memset(pStart, 0, bytes);
408126a8a12Smrg
409126a8a12Smrg    STORE_LISTOF_PROPERTY (pBuf, numProps, props);
410126a8a12Smrg
411126a8a12Smrg    IceWriteData (iceConn, bytes, pStart);
412126a8a12Smrg    IceFlush (iceConn);
413126a8a12Smrg}
414126a8a12Smrg
415126a8a12Smrg
416126a8a12Smrg
417126a8a12Smrgvoid
418d656433aSmrgSmcDeleteProperties(SmcConn smcConn, int numProps, char **propNames)
419126a8a12Smrg{
420126a8a12Smrg    IceConn			iceConn = smcConn->iceConn;
421126a8a12Smrg    smDeletePropertiesMsg 	*pMsg;
422126a8a12Smrg    char 			*pData;
423126a8a12Smrg    int				extra, i;
424126a8a12Smrg
425126a8a12Smrg    extra = 8;
426126a8a12Smrg
427126a8a12Smrg    for (i = 0; i < numProps; i++)
428126a8a12Smrg	extra += ARRAY8_BYTES (strlen (propNames[i]));
429126a8a12Smrg
430126a8a12Smrg    IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties,
431126a8a12Smrg	SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra),
432126a8a12Smrg	smDeletePropertiesMsg, pMsg, pData);
433126a8a12Smrg
4343fb97780Smrg    if (pData != NULL) {
4353fb97780Smrg	STORE_CARD32 (pData, (CARD32) numProps);
4363fb97780Smrg	STORE_CARD32 (pData, (CARD32) 0); /* padding */
437126a8a12Smrg
4383fb97780Smrg	for (i = 0; i < numProps; i++)
4393fb97780Smrg	    STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]);
440126a8a12Smrg
4413fb97780Smrg	IceFlush (iceConn);
4423fb97780Smrg    }
4433fb97780Smrg    else {
4443fb97780Smrg	CARD32 count_header[2] = {
4453fb97780Smrg	    (CARD32) numProps,
4463fb97780Smrg	    (CARD32) 0 /* padding */
4473fb97780Smrg	};
4483fb97780Smrg	IceWriteData32 (iceConn, 8, count_header);
4493fb97780Smrg
4503fb97780Smrg	for (i = 0; i < numProps; i++)
4513fb97780Smrg	    SEND_ARRAY8 (iceConn, strlen (propNames[i]), propNames[i]);
4523fb97780Smrg    }
453126a8a12Smrg}
454126a8a12Smrg
455126a8a12Smrg
456126a8a12Smrg
457126a8a12SmrgStatus
458d656433aSmrgSmcGetProperties(SmcConn smcConn, SmcPropReplyProc propReplyProc,
459d656433aSmrg		 SmPointer clientData)
460126a8a12Smrg{
461126a8a12Smrg    IceConn		iceConn = smcConn->iceConn;
462126a8a12Smrg    _SmcPropReplyWait 	*wait, *ptr;
463126a8a12Smrg
4643c15da26Smrg    if ((wait = malloc (sizeof (_SmcPropReplyWait))) == NULL)
465126a8a12Smrg    {
466126a8a12Smrg	return (0);
467126a8a12Smrg    }
468126a8a12Smrg
469126a8a12Smrg    wait->prop_reply_proc = propReplyProc;
470126a8a12Smrg    wait->client_data = clientData;
471126a8a12Smrg    wait->next = NULL;
472126a8a12Smrg
473126a8a12Smrg    ptr = smcConn->prop_reply_waits;
474126a8a12Smrg    while (ptr && ptr->next)
475126a8a12Smrg	ptr = ptr->next;
476126a8a12Smrg
477126a8a12Smrg    if (ptr == NULL)
478126a8a12Smrg	smcConn->prop_reply_waits = wait;
479126a8a12Smrg    else
480126a8a12Smrg	ptr->next = wait;
481126a8a12Smrg
482126a8a12Smrg    IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties);
483126a8a12Smrg    IceFlush (iceConn);
484126a8a12Smrg
485126a8a12Smrg    return (1);
486126a8a12Smrg}
487126a8a12Smrg
488126a8a12Smrg
489126a8a12Smrg
490126a8a12SmrgStatus
491d656433aSmrgSmcInteractRequest(SmcConn smcConn, int dialogType,
492d656433aSmrg		   SmcInteractProc interactProc, SmPointer clientData)
493126a8a12Smrg{
494126a8a12Smrg    IceConn			iceConn = smcConn->iceConn;
495126a8a12Smrg    smInteractRequestMsg	*pMsg;
496126a8a12Smrg    _SmcInteractWait 		*wait, *ptr;
497126a8a12Smrg
4983c15da26Smrg    if ((wait = malloc (sizeof (_SmcInteractWait))) == NULL)
499126a8a12Smrg    {
500126a8a12Smrg	return (0);
501126a8a12Smrg    }
502126a8a12Smrg
503126a8a12Smrg    wait->interact_proc = interactProc;
504126a8a12Smrg    wait->client_data = clientData;
505126a8a12Smrg    wait->next = NULL;
506126a8a12Smrg
507126a8a12Smrg    ptr = smcConn->interact_waits;
508126a8a12Smrg    while (ptr && ptr->next)
509126a8a12Smrg	ptr = ptr->next;
510126a8a12Smrg
511126a8a12Smrg    if (ptr == NULL)
512126a8a12Smrg	smcConn->interact_waits = wait;
513126a8a12Smrg    else
514126a8a12Smrg	ptr->next = wait;
515126a8a12Smrg
516126a8a12Smrg    IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest,
517126a8a12Smrg	SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg);
518126a8a12Smrg
519126a8a12Smrg    pMsg->dialogType = dialogType;
520126a8a12Smrg
521126a8a12Smrg    IceFlush (iceConn);
522126a8a12Smrg
523126a8a12Smrg    return (1);
524126a8a12Smrg}
525126a8a12Smrg
526126a8a12Smrg
527126a8a12Smrg
528126a8a12Smrgvoid
529d656433aSmrgSmcInteractDone(SmcConn smcConn, Bool cancelShutdown)
530126a8a12Smrg{
531126a8a12Smrg    IceConn		iceConn = smcConn->iceConn;
532126a8a12Smrg    smInteractDoneMsg	*pMsg;
533126a8a12Smrg
534126a8a12Smrg    IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone,
535126a8a12Smrg	SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg);
536126a8a12Smrg
537126a8a12Smrg    pMsg->cancelShutdown = cancelShutdown;
538126a8a12Smrg
539126a8a12Smrg    IceFlush (iceConn);
540126a8a12Smrg}
541126a8a12Smrg
542126a8a12Smrg
543126a8a12Smrg
544126a8a12Smrgvoid
545d656433aSmrgSmcRequestSaveYourself(SmcConn smcConn, int saveType, Bool shutdown,
546d656433aSmrg		       int interactStyle, Bool fast, Bool global)
547126a8a12Smrg{
548126a8a12Smrg    IceConn			iceConn = smcConn->iceConn;
549126a8a12Smrg    smSaveYourselfRequestMsg	*pMsg;
550126a8a12Smrg
551126a8a12Smrg    IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest,
552126a8a12Smrg	SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg);
553126a8a12Smrg
554126a8a12Smrg    pMsg->saveType = saveType;
555126a8a12Smrg    pMsg->shutdown = shutdown;
556126a8a12Smrg    pMsg->interactStyle = interactStyle;
557126a8a12Smrg    pMsg->fast = fast;
558126a8a12Smrg    pMsg->global = global;
559126a8a12Smrg
560126a8a12Smrg    IceFlush (iceConn);
561126a8a12Smrg}
562126a8a12Smrg
563126a8a12Smrg
564126a8a12Smrg
565126a8a12SmrgStatus
566d656433aSmrgSmcRequestSaveYourselfPhase2(SmcConn smcConn,
567d656433aSmrg			     SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc,
568d656433aSmrg			     SmPointer clientData)
569126a8a12Smrg{
570126a8a12Smrg    IceConn		iceConn = smcConn->iceConn;
571126a8a12Smrg    _SmcPhase2Wait 	*wait;
572126a8a12Smrg
573126a8a12Smrg    if (smcConn->phase2_wait)
574126a8a12Smrg	wait = smcConn->phase2_wait;
575126a8a12Smrg    else
576126a8a12Smrg    {
5773c15da26Smrg	if ((wait = malloc (sizeof (_SmcPhase2Wait))) == NULL)
578126a8a12Smrg	{
579126a8a12Smrg	    return (0);
580126a8a12Smrg	}
581126a8a12Smrg    }
582126a8a12Smrg
583126a8a12Smrg    wait->phase2_proc = saveYourselfPhase2Proc;
584126a8a12Smrg    wait->client_data = clientData;
585126a8a12Smrg
586126a8a12Smrg    smcConn->phase2_wait = wait;
587126a8a12Smrg
588126a8a12Smrg    IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request);
589126a8a12Smrg    IceFlush (iceConn);
590126a8a12Smrg
591126a8a12Smrg    return (1);
592126a8a12Smrg}
593126a8a12Smrg
594126a8a12Smrg
595126a8a12Smrg
596126a8a12Smrgvoid
597d656433aSmrgSmcSaveYourselfDone(SmcConn smcConn, Bool success)
598126a8a12Smrg{
599126a8a12Smrg    IceConn			iceConn = smcConn->iceConn;
600126a8a12Smrg    smSaveYourselfDoneMsg	*pMsg;
601126a8a12Smrg
602126a8a12Smrg    IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone,
603126a8a12Smrg	SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg);
604126a8a12Smrg
605126a8a12Smrg    pMsg->success = success;
606126a8a12Smrg
607126a8a12Smrg    IceFlush (iceConn);
608126a8a12Smrg}
609126a8a12Smrg
610126a8a12Smrg
611126a8a12Smrg
612126a8a12Smrgstatic void
613d656433aSmrgset_callbacks(SmcConn smcConn, unsigned long mask, SmcCallbacks *callbacks)
614126a8a12Smrg{
615126a8a12Smrg    if (mask & SmcSaveYourselfProcMask)
616126a8a12Smrg    {
617126a8a12Smrg	smcConn->callbacks.save_yourself.callback =
618126a8a12Smrg	    callbacks->save_yourself.callback;
619126a8a12Smrg	smcConn->callbacks.save_yourself.client_data =
620126a8a12Smrg	    callbacks->save_yourself.client_data;
621126a8a12Smrg    }
622126a8a12Smrg
623126a8a12Smrg    if (mask & SmcDieProcMask)
624126a8a12Smrg    {
625126a8a12Smrg	smcConn->callbacks.die.callback = callbacks->die.callback;
626126a8a12Smrg	smcConn->callbacks.die.client_data = callbacks->die.client_data;
627126a8a12Smrg    }
628126a8a12Smrg
629126a8a12Smrg    if (mask & SmcSaveCompleteProcMask)
630126a8a12Smrg    {
631126a8a12Smrg	smcConn->callbacks.save_complete.callback =
632126a8a12Smrg	    callbacks->save_complete.callback;
633126a8a12Smrg	smcConn->callbacks.save_complete.client_data =
634126a8a12Smrg	    callbacks->save_complete.client_data;
635126a8a12Smrg    }
636126a8a12Smrg
637126a8a12Smrg    if (mask & SmcShutdownCancelledProcMask)
638126a8a12Smrg    {
639126a8a12Smrg	smcConn->callbacks.shutdown_cancelled.callback =
640126a8a12Smrg	    callbacks->shutdown_cancelled.callback;
641126a8a12Smrg	smcConn->callbacks.shutdown_cancelled.client_data =
642126a8a12Smrg	    callbacks->shutdown_cancelled.client_data;
643126a8a12Smrg    }
644126a8a12Smrg}
645