sm_manager.c revision 3c15da26
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    int				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    STORE_ARRAY8 (pData, strlen (clientId), clientId);
202
203    IceFlush (iceConn);
204
205    return (1);
206}
207
208
209
210void
211SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown,
212		int interactStyle, Bool fast)
213{
214    IceConn		iceConn = smsConn->iceConn;
215    smSaveYourselfMsg	*pMsg;
216
217    IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself,
218	SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg);
219
220    pMsg->saveType = saveType;
221    pMsg->shutdown = shutdown;
222    pMsg->interactStyle = interactStyle;
223    pMsg->fast = fast;
224
225    IceFlush (iceConn);
226
227    smsConn->save_yourself_in_progress = True;
228
229    if (interactStyle == SmInteractStyleNone ||
230	interactStyle == SmInteractStyleErrors ||
231	interactStyle == SmInteractStyleAny)
232    {
233	smsConn->interaction_allowed = interactStyle;
234    }
235    else
236    {
237	smsConn->interaction_allowed = SmInteractStyleNone;
238    }
239
240    smsConn->can_cancel_shutdown = shutdown &&
241	(interactStyle == SmInteractStyleAny ||
242	interactStyle == SmInteractStyleErrors);
243}
244
245
246
247void
248SmsSaveYourselfPhase2(SmsConn smsConn)
249{
250    IceConn	iceConn = smsConn->iceConn;
251
252    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
253    IceFlush (iceConn);
254}
255
256
257
258void
259SmsInteract(SmsConn smsConn)
260{
261    IceConn	iceConn = smsConn->iceConn;
262
263    IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact);
264    IceFlush (iceConn);
265
266    smsConn->interact_in_progress = True;
267}
268
269
270
271void
272SmsDie(SmsConn smsConn)
273{
274    IceConn	iceConn = smsConn->iceConn;
275
276    IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
277    IceFlush (iceConn);
278}
279
280
281
282void
283SmsSaveComplete(SmsConn smsConn)
284{
285    IceConn	iceConn = smsConn->iceConn;
286
287    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
288    IceFlush (iceConn);
289}
290
291
292
293void
294SmsShutdownCancelled(SmsConn smsConn)
295{
296    IceConn	iceConn = smsConn->iceConn;
297
298    IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled);
299    IceFlush (iceConn);
300
301    smsConn->can_cancel_shutdown = False;
302}
303
304
305
306void
307SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props)
308{
309    IceConn			iceConn = smsConn->iceConn;
310    int 			bytes;
311    smPropertiesReplyMsg	*pMsg;
312    char 			*pBuf;
313    char			*pStart;
314
315    IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply,
316	SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg);
317
318    LISTOF_PROP_BYTES (numProps, props, bytes);
319    pMsg->length += WORD64COUNT (bytes);
320
321    pBuf = pStart = IceAllocScratch (iceConn, bytes);
322
323    STORE_LISTOF_PROPERTY (pBuf, numProps, props);
324
325    IceWriteData (iceConn, bytes, pStart);
326    IceFlush (iceConn);
327}
328
329
330
331void
332SmsCleanUp(SmsConn smsConn)
333{
334    IceProtocolShutdown (smsConn->iceConn, _SmsOpcode);
335
336    if (smsConn->client_id)
337	free (smsConn->client_id);
338
339    free (smsConn);
340}
341