sm_manager.c revision 3fb97780
1/*
2
3Copyright 1993, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27/*
28 * Author: Ralph Mor, X Consortium
29 */
30
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34#include <X11/SM/SMlib.h>
35#include "SMlibint.h"
36#include <X11/Xtrans/Xtrans.h>
37
38#ifdef __UNIXWARE__
39#undef shutdown
40#endif
41
42
43
44static Status
45_SmsProtocolSetupProc (IceConn    iceConn,
46		       int majorVersion,
47		       int minorVersion,
48		       char *vendor,
49		       char *release,
50		       IcePointer *clientDataRet,
51		       char **failureReasonRet)
52{
53    SmsConn  		smsConn;
54    unsigned long 	mask;
55    Status		status;
56
57    /*
58     * vendor/release are undefined for ProtocolSetup in XSMP.
59     */
60
61    if (vendor)
62	free (vendor);
63    if (release)
64	free (release);
65
66
67    /*
68     * Allocate new SmsConn.
69     */
70
71    if ((smsConn = malloc (sizeof (struct _SmsConn))) == NULL)
72    {
73	const char *str = "Memory allocation failed";
74
75	*failureReasonRet = strdup (str);
76
77	return (0);
78    }
79
80    smsConn->iceConn = iceConn;
81    smsConn->proto_major_version = majorVersion;
82    smsConn->proto_minor_version = minorVersion;
83    smsConn->client_id = NULL;
84
85    smsConn->save_yourself_in_progress = False;
86    smsConn->interaction_allowed = SmInteractStyleNone;
87    smsConn->can_cancel_shutdown = False;
88    smsConn->interact_in_progress = False;
89
90    *clientDataRet = (IcePointer) smsConn;
91
92
93    /*
94     * Now give the session manager the new smsConn and get back the
95     * callbacks to invoke when messages arrive from the client.
96     *
97     * In the future, we can use the mask return value to check
98     * if the SM is expecting an older rev of SMlib.
99     */
100
101    bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks));
102
103    status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData,
104	&mask, &smsConn->callbacks, failureReasonRet);
105
106    return (status);
107}
108
109
110
111
112Status
113SmsInitialize(const char *vendor, const char *release,
114	      SmsNewClientProc newClientProc,
115	      SmPointer managerData, IceHostBasedAuthProc hostBasedAuthProc,
116	      int errorLength, char *errorStringRet)
117{
118    const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"};
119    IcePaAuthProc auth_procs[] = {_IcePaMagicCookie1Proc};
120    int auth_count = 1;
121
122    IcePaVersionRec versions[] = {
123        {SmProtoMajor, SmProtoMinor, _SmsProcessMessage}
124    };
125    int version_count = 1;
126
127    if (errorStringRet && errorLength > 0)
128	*errorStringRet = '\0';
129
130    if (!newClientProc)
131    {
132	if (errorStringRet && errorLength > 0) {
133	    strncpy (errorStringRet,
134		     "The SmsNewClientProc callback can't be NULL",
135		     errorLength);
136	    errorStringRet[errorLength - 1] = '\0';
137	}
138
139	return (0);
140    }
141
142    if (!_SmsOpcode)
143    {
144
145	if ((_SmsOpcode = IceRegisterForProtocolReply ("XSMP",
146	    vendor, release, version_count, versions,
147	    auth_count, auth_names, auth_procs, hostBasedAuthProc,
148	    _SmsProtocolSetupProc,
149	    NULL,	/* IceProtocolActivateProc - we don't care about
150			   when the Protocol Reply is sent, because the
151			   session manager can not immediately send a
152			   message - it must wait for RegisterClient. */
153	    NULL	/* IceIOErrorProc */
154            )) < 0)
155	{
156	    if (errorStringRet && errorLength > 0) {
157		strncpy (errorStringRet,
158			 "Could not register XSMP protocol with ICE",
159			 errorLength);
160		errorStringRet[errorLength - 1] = '\0';
161	    }
162	    return (0);
163	}
164    }
165
166    _SmsNewClientProc = newClientProc;
167    _SmsNewClientData = managerData;
168
169    return (1);
170}
171
172
173
174char *
175SmsClientHostName(SmsConn smsConn)
176{
177    return (IceGetPeerName (smsConn->iceConn));
178}
179
180
181
182Status
183SmsRegisterClientReply(SmsConn smsConn, char *clientId)
184{
185    IceConn			iceConn = smsConn->iceConn;
186    size_t			extra;
187    smRegisterClientReplyMsg 	*pMsg;
188    char 			*pData;
189
190    if ((smsConn->client_id = strdup (clientId)) == NULL)
191    {
192	return (0);
193    }
194
195    extra = ARRAY8_BYTES (strlen (clientId));
196
197    IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply,
198	SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra),
199	smRegisterClientReplyMsg, pMsg, pData);
200
201    if (pData != NULL) {
202        STORE_ARRAY8 (pData, strlen (clientId), clientId);
203        IceFlush (iceConn);
204    }
205    else {
206        SEND_ARRAY8 (iceConn, strlen (clientId), clientId);
207    }
208
209    return (1);
210}
211
212
213
214void
215SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown,
216		int interactStyle, Bool fast)
217{
218    IceConn		iceConn = smsConn->iceConn;
219    smSaveYourselfMsg	*pMsg;
220
221    IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself,
222	SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg);
223
224    pMsg->saveType = saveType;
225    pMsg->shutdown = shutdown;
226    pMsg->interactStyle = interactStyle;
227    pMsg->fast = fast;
228
229    IceFlush (iceConn);
230
231    smsConn->save_yourself_in_progress = True;
232
233    if (interactStyle == SmInteractStyleNone ||
234	interactStyle == SmInteractStyleErrors ||
235	interactStyle == SmInteractStyleAny)
236    {
237	smsConn->interaction_allowed = interactStyle;
238    }
239    else
240    {
241	smsConn->interaction_allowed = SmInteractStyleNone;
242    }
243
244    smsConn->can_cancel_shutdown = shutdown &&
245	(interactStyle == SmInteractStyleAny ||
246	interactStyle == SmInteractStyleErrors);
247}
248
249
250
251void
252SmsSaveYourselfPhase2(SmsConn smsConn)
253{
254    IceConn	iceConn = smsConn->iceConn;
255
256    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
257    IceFlush (iceConn);
258}
259
260
261
262void
263SmsInteract(SmsConn smsConn)
264{
265    IceConn	iceConn = smsConn->iceConn;
266
267    IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact);
268    IceFlush (iceConn);
269
270    smsConn->interact_in_progress = True;
271}
272
273
274
275void
276SmsDie(SmsConn smsConn)
277{
278    IceConn	iceConn = smsConn->iceConn;
279
280    IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
281    IceFlush (iceConn);
282}
283
284
285
286void
287SmsSaveComplete(SmsConn smsConn)
288{
289    IceConn	iceConn = smsConn->iceConn;
290
291    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
292    IceFlush (iceConn);
293}
294
295
296
297void
298SmsShutdownCancelled(SmsConn smsConn)
299{
300    IceConn	iceConn = smsConn->iceConn;
301
302    IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled);
303    IceFlush (iceConn);
304
305    smsConn->can_cancel_shutdown = False;
306}
307
308
309
310void
311SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props)
312{
313    IceConn			iceConn = smsConn->iceConn;
314    unsigned int		bytes;
315    smPropertiesReplyMsg	*pMsg;
316    char 			*pBuf;
317    char			*pStart;
318
319    IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply,
320	SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg);
321
322    LISTOF_PROP_BYTES (numProps, props, bytes);
323    pMsg->length += WORD64COUNT (bytes);
324
325    pBuf = pStart = IceAllocScratch (iceConn, bytes);
326
327    STORE_LISTOF_PROPERTY (pBuf, numProps, props);
328
329    IceWriteData (iceConn, bytes, pStart);
330    IceFlush (iceConn);
331}
332
333
334
335void
336SmsCleanUp(SmsConn smsConn)
337{
338    IceProtocolShutdown (smsConn->iceConn, _SmsOpcode);
339
340    if (smsConn->client_id)
341	free (smsConn->client_id);
342
343    free (smsConn);
344}
345