Git init
[framework/uifw/xorg/lib/libsm.git] / src / sm_manager.c
1 /*
2
3 Copyright 1993, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in 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 \f
43
44 static 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 \f
112
113 Status
114 SmsInitialize(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 \f
174 char *
175 SmsClientHostName(SmsConn smsConn)
176 {
177     return (IceGetPeerName (smsConn->iceConn));
178 }
179
180
181 \f
182 Status
183 SmsRegisterClientReply(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 \f
212 void
213 SmsSaveYourself(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 \f
249 void
250 SmsSaveYourselfPhase2(SmsConn smsConn)
251 {
252     IceConn     iceConn = smsConn->iceConn;
253
254     IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
255     IceFlush (iceConn);
256 }
257
258
259 \f
260 void
261 SmsInteract(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 \f
273 void
274 SmsDie(SmsConn smsConn)
275 {
276     IceConn     iceConn = smsConn->iceConn;
277
278     IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
279     IceFlush (iceConn);
280 }
281
282
283 \f
284 void
285 SmsSaveComplete(SmsConn smsConn)
286 {
287     IceConn     iceConn = smsConn->iceConn;
288
289     IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
290     IceFlush (iceConn);
291 }
292
293
294 \f
295 void
296 SmsShutdownCancelled(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 \f
308 void
309 SmsReturnProperties(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 \f
333 void
334 SmsCleanUp(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 }