sm_process.c revision 126a8a12
1/* $Xorg: sm_process.c,v 1.4 2001/02/09 02:03:30 xorgcvs Exp $ */
2
3/*
4
5Copyright 1993, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26
27*/
28/* $XFree86$ */
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
40
41/*
42 * Check for bad length
43 */
44
45#define CHECK_SIZE_MATCH(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
46    if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
47    { \
48       _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
49       return; \
50    }
51
52#define CHECK_AT_LEAST_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
53    if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
54    { \
55       _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
56       return; \
57    }
58
59#define CHECK_COMPLETE_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _pStart, _severity) \
60    if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
61        != _expected_len) \
62    { \
63       _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
64       IceDisposeCompleteMessage (iceConn, _pStart); \
65       return; \
66    }
67
68
69
70void
71_SmcProcessMessage (iceConn, clientData, opcode,
72    length, swap, replyWait, replyReadyRet)
73
74IceConn		 iceConn;
75IcePointer	 clientData;
76int		 opcode;
77unsigned long	 length;
78Bool		 swap;
79IceReplyWaitInfo *replyWait;
80Bool		 *replyReadyRet;
81
82{
83    SmcConn	smcConn = (SmcConn) clientData;
84
85    if (replyWait)
86	*replyReadyRet = False;
87
88    if (!smcConn->client_id &&
89        opcode != SM_RegisterClientReply && opcode != SM_Error)
90    {
91	_IceReadSkip (iceConn, length << 3);
92
93	_IceErrorBadState (iceConn, _SmcOpcode, opcode, IceFatalToProtocol);
94	return;
95    }
96
97    switch (opcode)
98    {
99    case SM_Error:
100    {
101	iceErrorMsg 	*pMsg;
102	char	    	*pData;
103
104	CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
105	    length, SIZEOF (iceErrorMsg), IceFatalToProtocol);
106
107	IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
108	    iceErrorMsg, pMsg, pData);
109
110	if (!IceValidIO (iceConn))
111	{
112	    IceDisposeCompleteMessage (iceConn, pData);
113	    return;
114	}
115
116	if (swap)
117	{
118	    pMsg->errorClass = lswaps (pMsg->errorClass);
119	    pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
120	}
121
122	if (replyWait &&
123	    replyWait->minor_opcode_of_request == SM_RegisterClient &&
124            pMsg->errorClass == IceBadValue &&
125	    pMsg->offendingMinorOpcode == SM_RegisterClient &&
126	    pMsg->offendingSequenceNum == replyWait->sequence_of_request)
127	{
128	    /*
129	     * For Register Client, the previous ID was bad.
130	     */
131
132	    _SmcRegisterClientReply *reply =
133		(_SmcRegisterClientReply *) (replyWait->reply);
134
135	    reply->status = 0;
136
137	    *replyReadyRet = True;
138	}
139	else
140	{
141	    (*_SmcErrorHandler) (smcConn, swap,
142		pMsg->offendingMinorOpcode,
143	        pMsg->offendingSequenceNum,
144		pMsg->errorClass, pMsg->severity,
145		(SmPointer) pData);
146	}
147
148	IceDisposeCompleteMessage (iceConn, pData);
149	break;
150    }
151
152    case SM_RegisterClientReply:
153
154	if (!replyWait ||
155	    replyWait->minor_opcode_of_request != SM_RegisterClient)
156	{
157	    _IceReadSkip (iceConn, length << 3);
158
159	    _IceErrorBadState (iceConn, _SmcOpcode,
160		SM_RegisterClientReply, IceFatalToProtocol);
161	}
162        else
163	{
164	    smRegisterClientReplyMsg 	*pMsg;
165	    char			*pData, *pStart;
166	    _SmcRegisterClientReply 	*reply =
167	        (_SmcRegisterClientReply *) (replyWait->reply);
168
169#if 0 /* No-op */
170	    CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
171		length, SIZEOF (smRegisterClientReplyMsg), IceFatalToProtocol);
172#endif
173
174	    IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientReplyMsg),
175		smRegisterClientReplyMsg, pMsg, pStart);
176
177	    if (!IceValidIO (iceConn))
178	    {
179		IceDisposeCompleteMessage (iceConn, pStart);
180		return;
181	    }
182
183	    pData = pStart;
184
185	    SKIP_ARRAY8 (pData, swap);		/* client id */
186
187	    CHECK_COMPLETE_SIZE (iceConn, _SmcOpcode, opcode,
188		length, pData - pStart + SIZEOF (smRegisterClientReplyMsg),
189		pStart, IceFatalToProtocol);
190
191	    pData = pStart;
192
193	    EXTRACT_ARRAY8_AS_STRING (pData, swap, reply->client_id);
194
195	    reply->status = 1;
196	    *replyReadyRet = True;
197
198	    IceDisposeCompleteMessage (iceConn, pStart);
199	}
200	break;
201
202    case SM_SaveYourself:
203    {
204	smSaveYourselfMsg 	*pMsg;
205	unsigned char		errVal;
206	int			errOffset = -1;
207
208	CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
209	    length, SIZEOF (smSaveYourselfMsg),
210	    IceFatalToProtocol);
211
212	IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfMsg),
213	    smSaveYourselfMsg, pMsg);
214
215	if (!IceValidIO (iceConn))
216	{
217	    return;
218	}
219
220	if (pMsg->saveType != SmSaveGlobal &&
221	    pMsg->saveType != SmSaveLocal &&
222	    pMsg->saveType != SmSaveBoth)
223	{
224	    errVal = pMsg->saveType;
225	    errOffset = 8;
226	}
227	else if (pMsg->shutdown != 1 && pMsg->shutdown != 0)
228	{
229	    errVal = pMsg->shutdown;
230	    errOffset = 9;
231	}
232	else if (pMsg->interactStyle != SmInteractStyleNone &&
233	    pMsg->interactStyle != SmInteractStyleErrors &&
234	    pMsg->interactStyle != SmInteractStyleAny)
235	{
236	    errVal = pMsg->interactStyle;
237	    errOffset = 10;
238	}
239	else if (pMsg->fast != 1 && pMsg->fast != 0)
240	{
241	    errVal = pMsg->fast;
242	    errOffset = 11;
243	}
244
245	if (errOffset >= 0)
246	{
247	    _IceErrorBadValue (iceConn, _SmcOpcode,
248	        SM_SaveYourself, errOffset, 1, (IcePointer) &errVal);
249	}
250	else
251	{
252	    (*smcConn->callbacks.save_yourself.callback) (smcConn,
253	        smcConn->callbacks.save_yourself.client_data,
254                pMsg->saveType, pMsg->shutdown,
255		pMsg->interactStyle, pMsg->fast);
256
257	    smcConn->save_yourself_in_progress = True;
258
259	    if (pMsg->shutdown)
260		smcConn->shutdown_in_progress = True;
261	}
262	break;
263    }
264
265    case SM_SaveYourselfPhase2:
266
267	if (!smcConn->phase2_wait)
268	{
269	    _IceErrorBadState (iceConn, _SmcOpcode,
270		SM_SaveYourselfPhase2, IceCanContinue);
271	}
272        else
273	{
274	    CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
275	        length, SIZEOF (smSaveYourselfPhase2Msg),
276	        IceFatalToProtocol);
277
278	    (*smcConn->phase2_wait->phase2_proc) (smcConn,
279		smcConn->phase2_wait->client_data);
280
281	    free ((char *) smcConn->phase2_wait);
282	    smcConn->phase2_wait  = NULL;
283	}
284	break;
285
286    case SM_Interact:
287
288        if (!smcConn->interact_waits)
289	{
290	    _IceErrorBadState (iceConn, _SmcOpcode,
291		SM_Interact, IceCanContinue);
292	}
293        else
294	{
295	    _SmcInteractWait *next = smcConn->interact_waits->next;
296
297	    CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
298	        length, SIZEOF (smInteractMsg),
299	        IceFatalToProtocol);
300
301	    (*smcConn->interact_waits->interact_proc) (smcConn,
302		smcConn->interact_waits->client_data);
303
304	    free ((char *) smcConn->interact_waits);
305	    smcConn->interact_waits = next;
306	}
307	break;
308
309    case SM_SaveComplete:
310
311	if (!smcConn->save_yourself_in_progress)
312	{
313	    _IceErrorBadState (iceConn, _SmcOpcode,
314		SM_SaveComplete, IceCanContinue);
315	}
316	else
317	{
318	    CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
319	        length, SIZEOF (smSaveCompleteMsg),
320	        IceFatalToProtocol);
321
322	    smcConn->save_yourself_in_progress = False;
323
324	    (*smcConn->callbacks.save_complete.callback) (smcConn,
325	        smcConn->callbacks.save_complete.client_data);
326	}
327	break;
328
329    case SM_Die:
330
331	CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
332	    length, SIZEOF (smDieMsg),
333	    IceFatalToProtocol);
334
335	(*smcConn->callbacks.die.callback) (smcConn,
336	    smcConn->callbacks.die.client_data);
337	break;
338
339    case SM_ShutdownCancelled:
340
341	if (!smcConn->shutdown_in_progress)
342	{
343	    _IceErrorBadState (iceConn, _SmcOpcode,
344		SM_ShutdownCancelled, IceCanContinue);
345	}
346	else
347	{
348	    CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode,
349	        length, SIZEOF (smShutdownCancelledMsg),
350	        IceFatalToProtocol);
351
352	    smcConn->shutdown_in_progress = False;
353
354	    (*smcConn->callbacks.shutdown_cancelled.callback) (smcConn,
355	        smcConn->callbacks.shutdown_cancelled.client_data);
356	}
357	break;
358
359    case SM_PropertiesReply:
360
361        if (!smcConn->prop_reply_waits)
362	{
363	    _IceReadSkip (iceConn, length << 3);
364
365	    _IceErrorBadState (iceConn, _SmcOpcode,
366		SM_PropertiesReply, IceCanContinue);
367	}
368        else
369	{
370	    smPropertiesReplyMsg 	*pMsg;
371	    char 			*pData, *pStart;
372	    int				numProps;
373	    SmProp			**props = NULL;
374	    _SmcPropReplyWait 		*next;
375
376#if 0 /* No-op */
377	    CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode,
378		length, SIZEOF (smPropertiesReplyMsg), IceFatalToProtocol);
379#endif
380
381	    IceReadCompleteMessage (iceConn, SIZEOF (smPropertiesReplyMsg),
382		smPropertiesReplyMsg, pMsg, pStart);
383
384	    if (!IceValidIO (iceConn))
385	    {
386		IceDisposeCompleteMessage (iceConn, pStart);
387		return;
388	    }
389
390	    pData = pStart;
391
392	    SKIP_LISTOF_PROPERTY (pData, swap);
393
394	    CHECK_COMPLETE_SIZE (iceConn, _SmcOpcode, opcode,
395	        length, pData - pStart + SIZEOF (smPropertiesReplyMsg),
396	        pStart, IceFatalToProtocol);
397
398	    pData = pStart;
399
400	    EXTRACT_LISTOF_PROPERTY (pData, swap, numProps, props);
401
402	    next = smcConn->prop_reply_waits->next;
403
404	    (*smcConn->prop_reply_waits->prop_reply_proc) (smcConn,
405		smcConn->prop_reply_waits->client_data, numProps, props);
406
407	    free ((char *) smcConn->prop_reply_waits);
408	    smcConn->prop_reply_waits = next;
409
410	    IceDisposeCompleteMessage (iceConn, pStart);
411	}
412	break;
413
414    default:
415    {
416	_IceErrorBadMinor (iceConn, _SmcOpcode, opcode, IceCanContinue);
417	_IceReadSkip (iceConn, length << 3);
418	break;
419    }
420    }
421}
422
423
424
425void
426_SmsProcessMessage (iceConn, clientData, opcode, length, swap)
427
428IceConn		 iceConn;
429IcePointer       clientData;
430int		 opcode;
431unsigned long	 length;
432Bool		 swap;
433
434{
435    SmsConn	smsConn = (SmsConn) clientData;
436
437    if (!smsConn->client_id &&
438        opcode != SM_RegisterClient && opcode != SM_Error)
439    {
440	_IceReadSkip (iceConn, length << 3);
441
442	_IceErrorBadState (iceConn, _SmsOpcode, opcode, IceFatalToProtocol);
443
444	return;
445    }
446
447    switch (opcode)
448    {
449    case SM_Error:
450    {
451	iceErrorMsg 	*pMsg;
452	char	    	*pData;
453
454	CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
455	    length, SIZEOF (iceErrorMsg), IceFatalToProtocol);
456
457	IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
458	    iceErrorMsg, pMsg, pData);
459
460	if (!IceValidIO (iceConn))
461	{
462	    IceDisposeCompleteMessage (iceConn, pData);
463	    return;
464	}
465
466	if (swap)
467	{
468	    pMsg->errorClass = lswaps (pMsg->errorClass);
469	    pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
470	}
471
472	(*_SmsErrorHandler) (smsConn, swap,
473	    pMsg->offendingMinorOpcode,
474	    pMsg->offendingSequenceNum,
475	    pMsg->errorClass, pMsg->severity,
476            (SmPointer) pData);
477
478	IceDisposeCompleteMessage (iceConn, pData);
479	break;
480    }
481
482    case SM_RegisterClient:
483    {
484	smRegisterClientMsg 	*pMsg;
485	char 			*pData, *pStart;
486	char 			*previousId;
487	int                      idLen;
488
489#if 0 /* No-op */
490	CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
491	    length, SIZEOF (smRegisterClientMsg), IceFatalToProtocol);
492#endif
493
494	IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientMsg),
495	    smRegisterClientMsg, pMsg, pStart);
496
497	if (!IceValidIO (iceConn))
498	{
499	    IceDisposeCompleteMessage (iceConn, pStart);
500	    return;
501	}
502
503	pData = pStart;
504
505	SKIP_ARRAY8 (pData, swap);	/* previous id */
506
507	CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
508	   length, pData - pStart + SIZEOF (smRegisterClientMsg),
509	   pStart, IceFatalToProtocol);
510
511	pData = pStart;
512
513	EXTRACT_ARRAY8 (pData, swap, idLen, previousId);
514
515	if (*previousId == '\0')
516	{
517	    free (previousId);
518	    previousId = NULL;
519	}
520
521	if (!(*smsConn->callbacks.register_client.callback) (smsConn,
522            smsConn->callbacks.register_client.manager_data, previousId))
523	{
524	    /*
525	     * The previoudId was bad.  Generate BadValue error.
526	     */
527
528	    _IceErrorBadValue (smsConn->iceConn, _SmsOpcode, SM_RegisterClient,
529		8, ARRAY8_BYTES (idLen), (IcePointer) pStart);
530	}
531
532	IceDisposeCompleteMessage (iceConn, pStart);
533	break;
534    }
535
536    case SM_InteractRequest:
537
538        if (!smsConn->save_yourself_in_progress ||
539	    smsConn->interaction_allowed == SmInteractStyleNone)
540	{
541	    _IceErrorBadState (iceConn, _SmsOpcode,
542		SM_InteractRequest, IceCanContinue);
543	}
544        else
545	{
546	    smInteractRequestMsg 	*pMsg;
547
548	    CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
549	        length, SIZEOF (smInteractRequestMsg),
550	        IceFatalToProtocol);
551
552	    IceReadSimpleMessage (iceConn, smInteractRequestMsg, pMsg);
553
554	    if (pMsg->dialogType != SmDialogNormal &&
555		pMsg->dialogType != SmDialogError)
556	    {
557		unsigned char errVal = pMsg->dialogType;
558
559		_IceErrorBadValue (iceConn, _SmsOpcode,
560	            SM_InteractRequest, 2, 1, (IcePointer) &errVal);
561	    }
562	    else if (pMsg->dialogType == SmDialogNormal &&
563		smsConn->interaction_allowed != SmInteractStyleAny)
564	    {
565		_IceErrorBadState (iceConn, _SmsOpcode,
566		    SM_InteractRequest, IceCanContinue);
567	    }
568	    else
569	    {
570		(*smsConn->callbacks.interact_request.callback) (smsConn,
571	            smsConn->callbacks.interact_request.manager_data,
572		    pMsg->dialogType);
573	    }
574	}
575	break;
576
577    case SM_InteractDone:
578
579        if (!smsConn->interact_in_progress)
580	{
581	    _IceErrorBadState (iceConn, _SmsOpcode,
582		SM_InteractDone, IceCanContinue);
583	}
584        else
585	{
586	    smInteractDoneMsg 	*pMsg;
587
588	    CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
589	        length, SIZEOF (smInteractDoneMsg),
590	        IceFatalToProtocol);
591
592	    IceReadSimpleMessage (iceConn, smInteractDoneMsg, pMsg);
593
594	    if (pMsg->cancelShutdown != 1 &&
595		pMsg->cancelShutdown != 0)
596	    {
597		unsigned char errVal = pMsg->cancelShutdown;
598
599		_IceErrorBadValue (iceConn, _SmsOpcode,
600	            SM_InteractDone, 2, 1, (IcePointer) &errVal);
601	    }
602	    else if (pMsg->cancelShutdown && !smsConn->can_cancel_shutdown)
603	    {
604		_IceErrorBadState (iceConn, _SmsOpcode,
605		    SM_InteractDone, IceCanContinue);
606	    }
607	    else
608	    {
609		smsConn->interact_in_progress = False;
610
611		(*smsConn->callbacks.interact_done.callback) (smsConn,
612	            smsConn->callbacks.interact_done.manager_data,
613	            pMsg->cancelShutdown);
614	    }
615	}
616	break;
617
618    case SM_SaveYourselfRequest:
619    {
620	smSaveYourselfRequestMsg 	*pMsg;
621	unsigned char			errVal;
622	int				errOffset = -1;
623
624	CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
625	    length, SIZEOF (smSaveYourselfRequestMsg),
626	    IceFatalToProtocol);
627
628	IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfRequestMsg),
629	    smSaveYourselfRequestMsg, pMsg);
630
631	if (!IceValidIO (iceConn))
632	{
633	    IceDisposeCompleteMessage (iceConn, pMsg);
634	    return;
635	}
636
637	if (pMsg->saveType != SmSaveGlobal &&
638	    pMsg->saveType != SmSaveLocal &&
639	    pMsg->saveType != SmSaveBoth)
640	{
641	    errVal = pMsg->saveType;
642	    errOffset = 8;
643	}
644	else if (pMsg->shutdown != 1 && pMsg->shutdown != 0)
645	{
646	    errVal = pMsg->shutdown;
647	    errOffset = 9;
648	}
649	else if (pMsg->interactStyle != SmInteractStyleNone &&
650	    pMsg->interactStyle != SmInteractStyleErrors &&
651	    pMsg->interactStyle != SmInteractStyleAny)
652	{
653	    errVal = pMsg->interactStyle;
654	    errOffset = 10;
655	}
656	else if (pMsg->fast != 1 && pMsg->fast != 0)
657	{
658	    errVal = pMsg->fast;
659	    errOffset = 11;
660	}
661	else if (pMsg->global != 1 && pMsg->global != 0)
662	{
663	    errVal = pMsg->fast;
664	    errOffset = 11;
665	}
666
667	if (errOffset >= 0)
668	{
669	    _IceErrorBadValue (iceConn, _SmsOpcode,
670	        SM_SaveYourselfRequest, errOffset, 1, (IcePointer) &errVal);
671	}
672	else
673	{
674	    (*smsConn->callbacks.save_yourself_request.callback) (smsConn,
675	        smsConn->callbacks.save_yourself_request.manager_data,
676                pMsg->saveType, pMsg->shutdown, pMsg->interactStyle,
677	        pMsg->fast, pMsg->global);
678	}
679	break;
680    }
681
682    case SM_SaveYourselfPhase2Request:
683
684        if (!smsConn->save_yourself_in_progress)
685	{
686	    _IceErrorBadState (iceConn, _SmsOpcode,
687		SM_SaveYourselfPhase2Request, IceCanContinue);
688	}
689        else
690	{
691	    CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
692	        length, SIZEOF (smSaveYourselfPhase2RequestMsg),
693	        IceFatalToProtocol);
694
695	    (*smsConn->callbacks.save_yourself_phase2_request.callback) (
696		smsConn, smsConn->callbacks.
697		save_yourself_phase2_request.manager_data);
698	}
699	break;
700
701    case SM_SaveYourselfDone:
702
703        if (!smsConn->save_yourself_in_progress)
704	{
705	    _IceErrorBadState (iceConn, _SmsOpcode,
706		SM_SaveYourselfDone, IceCanContinue);
707	}
708        else
709	{
710	    smSaveYourselfDoneMsg 	*pMsg;
711
712	    CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
713	        length, SIZEOF (smSaveYourselfDoneMsg),
714	        IceFatalToProtocol);
715
716	    IceReadSimpleMessage (iceConn, smSaveYourselfDoneMsg, pMsg);
717
718	    if (pMsg->success != 1 && pMsg->success != 0)
719	    {
720		unsigned char errVal = pMsg->success;
721
722		_IceErrorBadValue (iceConn, _SmsOpcode,
723	            SM_SaveYourselfDone, 2, 1, (IcePointer) &errVal);
724	    }
725	    else
726	    {
727		smsConn->save_yourself_in_progress = False;
728		smsConn->interaction_allowed = SmInteractStyleNone;
729
730		(*smsConn->callbacks.save_yourself_done.callback) (smsConn,
731	            smsConn->callbacks.save_yourself_done.manager_data,
732		    pMsg->success);
733	    }
734	}
735	break;
736
737    case SM_CloseConnection:
738    {
739	smCloseConnectionMsg 	*pMsg;
740	char 			*pData, *pStart;
741	int 			count, i;
742	char 			**reasonMsgs = NULL;
743
744#if 0 /* No-op */
745	CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
746	    length, SIZEOF (smCloseConnectionMsg), IceFatalToProtocol);
747#endif
748
749	IceReadCompleteMessage (iceConn, SIZEOF (smCloseConnectionMsg),
750	    smCloseConnectionMsg, pMsg, pStart);
751
752	if (!IceValidIO (iceConn))
753	{
754	    IceDisposeCompleteMessage (iceConn, pStart);
755	    return;
756	}
757
758	pData = pStart;
759
760	EXTRACT_CARD32 (pData, swap, count);
761	pData += 4;
762
763	for (i = 0; i < count; i++)
764	    SKIP_ARRAY8 (pData, swap);
765
766	CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
767	   length, pData - pStart + SIZEOF (smCloseConnectionMsg),
768	   pStart, IceFatalToProtocol);
769
770	pData = pStart + 8;
771
772	reasonMsgs = (char **) malloc (count * sizeof (char *));
773	for (i = 0; i < count; i++)
774	    EXTRACT_ARRAY8_AS_STRING (pData, swap, reasonMsgs[i]);
775
776	IceDisposeCompleteMessage (iceConn, pStart);
777
778	(*smsConn->callbacks.close_connection.callback) (smsConn,
779	    smsConn->callbacks.close_connection.manager_data,
780	    count, reasonMsgs);
781	break;
782    }
783
784    case SM_SetProperties:
785    {
786	smSetPropertiesMsg 	*pMsg;
787	char 			*pData, *pStart;
788	SmProp			**props = NULL;
789	int 			numProps;
790
791#if 0 /* No-op */
792	CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
793	    length, SIZEOF (smSetPropertiesMsg), IceFatalToProtocol);
794#endif
795
796	IceReadCompleteMessage (iceConn, SIZEOF (smSetPropertiesMsg),
797	    smSetPropertiesMsg, pMsg, pStart);
798
799	if (!IceValidIO (iceConn))
800	{
801	    IceDisposeCompleteMessage (iceConn, pStart);
802	    return;
803	}
804
805	pData = pStart;
806
807	SKIP_LISTOF_PROPERTY (pData, swap);
808
809	CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
810	   length, pData - pStart + SIZEOF (smSetPropertiesMsg),
811	   pStart, IceFatalToProtocol);
812
813	pData = pStart;
814
815	EXTRACT_LISTOF_PROPERTY (pData, swap, numProps, props);
816
817	(*smsConn->callbacks.set_properties.callback) (smsConn,
818	    smsConn->callbacks.set_properties.manager_data, numProps, props);
819
820	IceDisposeCompleteMessage (iceConn, pStart);
821	break;
822    }
823
824    case SM_DeleteProperties:
825    {
826	smDeletePropertiesMsg 	*pMsg;
827	char 			*pData, *pStart;
828	int 			count, i;
829	char 			**propNames = NULL;
830
831#if 0 /* No-op */
832	CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode,
833	    length, SIZEOF (smDeletePropertiesMsg), IceFatalToProtocol);
834#endif
835
836	IceReadCompleteMessage (iceConn, SIZEOF (smDeletePropertiesMsg),
837	    smDeletePropertiesMsg, pMsg, pStart);
838
839	if (!IceValidIO (iceConn))
840	{
841	    IceDisposeCompleteMessage (iceConn, pStart);
842	    return;
843	}
844
845	pData = pStart;
846
847	EXTRACT_CARD32 (pData, swap, count);
848	pData += 4;
849
850	for (i = 0; i < count; i++)
851	    SKIP_ARRAY8 (pData, swap);	/* prop names */
852
853	CHECK_COMPLETE_SIZE (iceConn, _SmsOpcode, opcode,
854	   length, pData - pStart + SIZEOF (smDeletePropertiesMsg),
855	   pStart, IceFatalToProtocol);
856
857	pData = pStart + 8;
858
859	propNames = (char **) malloc (count * sizeof (char *));
860	for (i = 0; i < count; i++)
861	    EXTRACT_ARRAY8_AS_STRING (pData, swap, propNames[i]);
862
863	IceDisposeCompleteMessage (iceConn, pStart);
864
865	(*smsConn->callbacks.delete_properties.callback) (smsConn,
866	    smsConn->callbacks.delete_properties.manager_data,
867	    count, propNames);
868
869	break;
870    }
871
872    case SM_GetProperties:
873
874	CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode,
875	    length, SIZEOF (smGetPropertiesMsg),
876	    IceFatalToProtocol);
877
878	(*smsConn->callbacks.get_properties.callback) (smsConn,
879	    smsConn->callbacks.get_properties.manager_data);
880	break;
881
882    default:
883    {
884	_IceErrorBadMinor (iceConn, _SmsOpcode, opcode, IceCanContinue);
885	_IceReadSkip (iceConn, length << 3);
886	break;
887    }
888    }
889}
890