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 
43 
44 static Status
_SmsProtocolSetupProc(IceConn iceConn,int majorVersion,int minorVersion,char * vendor,char * release,IcePointer * clientDataRet,char ** failureReasonRet)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 
112 Status
SmsInitialize(const char * vendor,const char * release,SmsNewClientProc newClientProc,SmPointer managerData,IceHostBasedAuthProc hostBasedAuthProc,int errorLength,char * errorStringRet)113 SmsInitialize(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 
174 char *
SmsClientHostName(SmsConn smsConn)175 SmsClientHostName(SmsConn smsConn)
176 {
177     return (IceGetPeerName (smsConn->iceConn));
178 }
179 
180 
181 
182 Status
SmsRegisterClientReply(SmsConn smsConn,char * clientId)183 SmsRegisterClientReply(SmsConn smsConn, char *clientId)
184 {
185     IceConn			iceConn = smsConn->iceConn;
186     size_t			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 
210 void
SmsSaveYourself(SmsConn smsConn,int saveType,Bool shutdown,int interactStyle,Bool fast)211 SmsSaveYourself(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 
247 void
SmsSaveYourselfPhase2(SmsConn smsConn)248 SmsSaveYourselfPhase2(SmsConn smsConn)
249 {
250     IceConn	iceConn = smsConn->iceConn;
251 
252     IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveYourselfPhase2);
253     IceFlush (iceConn);
254 }
255 
256 
257 
258 void
SmsInteract(SmsConn smsConn)259 SmsInteract(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 
271 void
SmsDie(SmsConn smsConn)272 SmsDie(SmsConn smsConn)
273 {
274     IceConn	iceConn = smsConn->iceConn;
275 
276     IceSimpleMessage (iceConn, _SmsOpcode, SM_Die);
277     IceFlush (iceConn);
278 }
279 
280 
281 
282 void
SmsSaveComplete(SmsConn smsConn)283 SmsSaveComplete(SmsConn smsConn)
284 {
285     IceConn	iceConn = smsConn->iceConn;
286 
287     IceSimpleMessage (iceConn, _SmsOpcode, SM_SaveComplete);
288     IceFlush (iceConn);
289 }
290 
291 
292 
293 void
SmsShutdownCancelled(SmsConn smsConn)294 SmsShutdownCancelled(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 
306 void
SmsReturnProperties(SmsConn smsConn,int numProps,SmProp ** props)307 SmsReturnProperties(SmsConn smsConn, int numProps, SmProp **props)
308 {
309     IceConn			iceConn = smsConn->iceConn;
310     unsigned 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 
331 void
SmsCleanUp(SmsConn smsConn)332 SmsCleanUp(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