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