sm_manager.c revision d656433a
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
45
46
47static Status
48_SmsProtocolSetupProc (IceConn    iceConn,
49		       int majorVersion,
50		       int minorVersion,
51		       char *vendor,
52		       char *release,
53		       IcePointer *clientDataRet,
54		       char **failureReasonRet)
55{
56    SmsConn  		smsConn;
57    unsigned long 	mask;
58    Status		status;
59
60    /*
61     * vendor/release are undefined for ProtocolSetup in XSMP.
62     */
63
64    if (vendor)
65	free (vendor);
66    if (release)
67	free (release);
68
69
70    /*
71     * Allocate new SmsConn.
72     */
73
74    if ((smsConn = (SmsConn) malloc (sizeof (struct _SmsConn))) == NULL)
75    {
76	const char *str = "Memory allocation failed";
77
78	if ((*failureReasonRet = (char *) malloc (strlen (str) + 1)) != NULL)
79	    strcpy (*failureReasonRet, str);
80
81	return (0);
82    }
83
84    smsConn->iceConn = iceConn;
85    smsConn->proto_major_version = majorVersion;
86    smsConn->proto_minor_version = minorVersion;
87    smsConn->client_id = NULL;
88
89    smsConn->save_yourself_in_progress = False;
90    smsConn->interaction_allowed = SmInteractStyleNone;
91    smsConn->can_cancel_shutdown = False;
92    smsConn->interact_in_progress = False;
93
94    *clientDataRet = (IcePointer) smsConn;
95
96
97    /*
98     * Now give the session manager the new smsConn and get back the
99     * callbacks to invoke when messages arrive from the client.
100     *
101     * In the future, we can use the mask return value to check
102     * if the SM is expecting an older rev of SMlib.
103     */
104
105    bzero ((char *) &smsConn->callbacks, sizeof (SmsCallbacks));
106
107    status = (*_SmsNewClientProc) (smsConn, _SmsNewClientData,
108	&mask, &smsConn->callbacks, failureReasonRet);
109
110    return (status);
111}
112
113
114
115
116Status
117SmsInitialize(char *vendor, char *release, SmsNewClientProc newClientProc,
118	      SmPointer managerData, IceHostBasedAuthProc hostBasedAuthProc,
119	      int errorLength, char *errorStringRet)
120{
121    const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"};
122    IcePaAuthProc auth_procs[] = {_IcePaMagicCookie1Proc};
123    int auth_count = 1;
124
125    IcePaVersionRec versions[] = {
126        {SmProtoMajor, SmProtoMinor, _SmsProcessMessage}
127    };
128    int version_count = 1;
129
130    if (errorStringRet && errorLength > 0)
131	*errorStringRet = '\0';
132
133    if (!newClientProc)
134    {
135	if (errorStringRet && errorLength > 0) {
136	    strncpy (errorStringRet,
137		     "The SmsNewClientProc callback can't be NULL",
138		     errorLength);
139	    errorStringRet[errorLength - 1] = '\0';
140	}
141
142	return (0);
143    }
144
145    if (!_SmsOpcode)
146    {
147
148	if ((_SmsOpcode = IceRegisterForProtocolReply ("XSMP",
149	    vendor, release, version_count, versions,
150	    auth_count, auth_names, auth_procs, hostBasedAuthProc,
151	    _SmsProtocolSetupProc,
152	    NULL,	/* IceProtocolActivateProc - we don't care about
153			   when the Protocol Reply is sent, because the
154			   session manager can not immediately send a
155			   message - it must wait for RegisterClient. */
156	    NULL	/* IceIOErrorProc */
157            )) < 0)
158	{
159	    if (errorStringRet && errorLength > 0) {
160		strncpy (errorStringRet,
161			 "Could not register XSMP protocol with ICE",
162			 errorLength);
163		errorStringRet[errorLength - 1] = '\0';
164	    }
165	    return (0);
166	}
167    }
168
169    _SmsNewClientProc = newClientProc;
170    _SmsNewClientData = managerData;
171
172    return (1);
173}
174
175
176
177char *
178SmsClientHostName(SmsConn smsConn)
179{
180    return (IceGetPeerName (smsConn->iceConn));
181}
182
183
184
185Status
186SmsRegisterClientReply(SmsConn smsConn, char *clientId)
187{
188    IceConn			iceConn = smsConn->iceConn;
189    int				extra;
190    smRegisterClientReplyMsg 	*pMsg;
191    char 			*pData;
192
193    if ((smsConn->client_id = (char *) malloc (strlen (clientId) + 1)) == NULL)
194    {
195	return (0);
196    }
197
198    strcpy (smsConn->client_id, clientId);
199
200    extra = ARRAY8_BYTES (strlen (clientId));
201
202    IceGetHeaderExtra (iceConn, _SmsOpcode, SM_RegisterClientReply,
203	SIZEOF (smRegisterClientReplyMsg), WORD64COUNT (extra),
204	smRegisterClientReplyMsg, pMsg, pData);
205
206    STORE_ARRAY8 (pData, strlen (clientId), clientId);
207
208    IceFlush (iceConn);
209
210    return (1);
211}
212
213
214
215void
216SmsSaveYourself(SmsConn smsConn, int saveType, Bool shutdown,
217		int interactStyle, Bool fast)
218{
219    IceConn		iceConn = smsConn->iceConn;
220    smSaveYourselfMsg	*pMsg;
221
222    IceGetHeader (iceConn, _SmsOpcode, SM_SaveYourself,
223	SIZEOF (smSaveYourselfMsg), smSaveYourselfMsg, pMsg);
224
225    pMsg->saveType = saveType;
226    pMsg->shutdown = shutdown;
227    pMsg->interactStyle = interactStyle;
228    pMsg->fast = fast;
229
230    IceFlush (iceConn);
231
232    smsConn->save_yourself_in_progress = True;
233
234    if (interactStyle == SmInteractStyleNone ||
235	interactStyle == SmInteractStyleErrors ||
236	interactStyle == SmInteractStyleAny)
237    {
238	smsConn->interaction_allowed = interactStyle;
239    }
240    else
241    {
242	smsConn->interaction_allowed = SmInteractStyleNone;
243    }
244
245    smsConn->can_cancel_shutdown = shutdown &&
246	(interactStyle == SmInteractStyleAny ||
247	interactStyle == SmInteractStyleErrors);
248}
249
250
251
252void
253SmsSaveYourselfPhase2(SmsConn smsConn)
254{
255    IceConn	iceConn = smsConn->iceConn;
256
257    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
258    IceFlush (iceConn);
259}
260
261
262
263void
264SmsInteract(SmsConn smsConn)
265{
266    IceConn	iceConn = smsConn->iceConn;
267
268    IceSimpleMessage (iceConn, _SmsOpcode, SM_Interact);
269    IceFlush (iceConn);
270
271    smsConn->interact_in_progress = True;
272}
273
274
275
276void
277SmsDie(SmsConn smsConn)
278{
279    IceConn	iceConn = smsConn->iceConn;
280
281    IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
282    IceFlush (iceConn);
283}
284
285
286
287void
288SmsSaveComplete(SmsConn smsConn)
289{
290    IceConn	iceConn = smsConn->iceConn;
291
292    IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
293    IceFlush (iceConn);
294}
295
296
297
298void
299SmsShutdownCancelled(SmsConn smsConn)
300{
301    IceConn	iceConn = smsConn->iceConn;
302
303    IceSimpleMessage (iceConn, _SmsOpcode, SM_ShutdownCancelled);
304    IceFlush (iceConn);
305
306    smsConn->can_cancel_shutdown = False;
307}
308
309
310
311void
312SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props)
313{
314    IceConn			iceConn = smsConn->iceConn;
315    int 			bytes;
316    smPropertiesReplyMsg	*pMsg;
317    char 			*pBuf;
318    char			*pStart;
319
320    IceGetHeader (iceConn, _SmsOpcode, SM_PropertiesReply,
321	SIZEOF (smPropertiesReplyMsg), smPropertiesReplyMsg, pMsg);
322
323    LISTOF_PROP_BYTES (numProps, props, bytes);
324    pMsg->length += WORD64COUNT (bytes);
325
326    pBuf = pStart = IceAllocScratch (iceConn, bytes);
327
328    STORE_LISTOF_PROPERTY (pBuf, numProps, props);
329
330    IceWriteData (iceConn, bytes, pStart);
331    IceFlush (iceConn);
332}
333
334
335
336void
337SmsCleanUp(SmsConn smsConn)
338{
339    IceProtocolShutdown (smsConn->iceConn, _SmsOpcode);
340
341    if (smsConn->client_id)
342	free (smsConn->client_id);
343
344    free ((char *) smsConn);
345}
346