sm_manager.c revision 555991fd
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 = (SmsConn) malloc (sizeof (struct _SmsConn))) == NULL)
72    {
73	const char *str = "Memory allocation failed";
74
75	if ((*failureReasonRet = (char *) malloc (strlen (str) + 1)) != NULL)
76	    strcpy (*failureReasonRet, str);
77
78	return (0);
79    }
80
81    smsConn->iceConn = iceConn;
82    smsConn->proto_major_version = majorVersion;
83    smsConn->proto_minor_version = minorVersion;
84    smsConn->client_id = NULL;
85
86    smsConn->save_yourself_in_progress = False;
87    smsConn->interaction_allowed = SmInteractStyleNone;
88    smsConn->can_cancel_shutdown = False;
89    smsConn->interact_in_progress = False;
90
91    *clientDataRet = (IcePointer) smsConn;
92
93
94    /*
95     * Now give the session manager the new smsConn and get back the
96     * callbacks to invoke when messages arrive from the client.
97     *
98     * In the future, we can use the mask return value to check
99     * if the SM is expecting an older rev of SMlib.
100     */
101
102    bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks));
103
104    status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData,
105	&mask, &smsConn->callbacks, failureReasonRet);
106
107    return (status);
108}
109
110
111
112
113Status
114SmsInitialize(char *vendor, char *release, 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 = (char *) malloc (strlen (clientId) + 1)) == NULL)
191    {
192	return (0);
193    }
194
195    strcpy (smsConn->client_id, clientId);
196
197    extra = ARRAY8_BYTES (strlen (clientId));
198
199    IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply,
200	SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra),
201	smRegisterClientReplyMsg, pMsg, pData);
202
203    STORE_ARRAY8 (pData, strlen (clientId), clientId);
204
205    IceFlush (iceConn);
206
207    return (1);
208}
209
210
211
212void
213SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown,
214		int interactStyle, Bool fast)
215{
216    IceConn		iceConn = smsConn->iceConn;
217    smSaveYourselfMsg	*pMsg;
218
219    IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself,
220	SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg);
221
222    pMsg->saveType = saveType;
223    pMsg->shutdown = shutdown;
224    pMsg->interactStyle = interactStyle;
225    pMsg->fast = fast;
226
227    IceFlush (iceConn);
228
229    smsConn->save_yourself_in_progress = True;
230
231    if (interactStyle == SmInteractStyleNone ||
232	interactStyle == SmInteractStyleErrors ||
233	interactStyle == SmInteractStyleAny)
234    {
235	smsConn->interaction_allowed = interactStyle;
236    }
237    else
238    {
239	smsConn->interaction_allowed = SmInteractStyleNone;
240    }
241
242    smsConn->can_cancel_shutdown = shutdown &&
243	(interactStyle == SmInteractStyleAny ||
244	interactStyle == SmInteractStyleErrors);
245}
246
247
248
249void
250SmsSaveYourselfPhase2(SmsConn smsConn)
251{
252    IceConn	iceConn = smsConn->iceConn;
253
254    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
255    IceFlush (iceConn);
256}
257
258
259
260void
261SmsInteract(SmsConn smsConn)
262{
263    IceConn	iceConn = smsConn->iceConn;
264
265    IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact);
266    IceFlush (iceConn);
267
268    smsConn->interact_in_progress = True;
269}
270
271
272
273void
274SmsDie(SmsConn smsConn)
275{
276    IceConn	iceConn = smsConn->iceConn;
277
278    IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
279    IceFlush (iceConn);
280}
281
282
283
284void
285SmsSaveComplete(SmsConn smsConn)
286{
287    IceConn	iceConn = smsConn->iceConn;
288
289    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
290    IceFlush (iceConn);
291}
292
293
294
295void
296SmsShutdownCancelled(SmsConn smsConn)
297{
298    IceConn	iceConn = smsConn->iceConn;
299
300    IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled);
301    IceFlush (iceConn);
302
303    smsConn->can_cancel_shutdown = False;
304}
305
306
307
308void
309SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props)
310{
311    IceConn			iceConn = smsConn->iceConn;
312    int 			bytes;
313    smPropertiesReplyMsg	*pMsg;
314    char 			*pBuf;
315    char			*pStart;
316
317    IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply,
318	SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg);
319
320    LISTOF_PROP_BYTES (numProps, props, bytes);
321    pMsg->length += WORD64COUNT (bytes);
322
323    pBuf = pStart = IceAllocScratch (iceConn, bytes);
324
325    STORE_LISTOF_PROPERTY (pBuf, numProps, props);
326
327    IceWriteData (iceConn, bytes, pStart);
328    IceFlush (iceConn);
329}
330
331
332
333void
334SmsCleanUp(SmsConn smsConn)
335{
336    IceProtocolShutdown (smsConn->iceConn, _SmsOpcode);
337
338    if (smsConn->client_id)
339	free (smsConn->client_id);
340
341    free ((char *) smsConn);
342}
343