144dda7b2Smrg/*
244dda7b2SmrgCopyright 1989, 1998  The Open Group
344dda7b2Smrg
444dda7b2SmrgPermission to use, copy, modify, distribute, and sell this software and its
544dda7b2Smrgdocumentation for any purpose is hereby granted without fee, provided that
644dda7b2Smrgthe above copyright notice appear in all copies and that both that
744dda7b2Smrgcopyright notice and this permission notice appear in supporting
844dda7b2Smrgdocumentation.
944dda7b2Smrg
1044dda7b2SmrgThe above copyright notice and this permission notice shall be included in
1144dda7b2Smrgall copies or substantial portions of the Software.
1244dda7b2Smrg
1344dda7b2SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1444dda7b2SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1544dda7b2SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1644dda7b2SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1744dda7b2SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1844dda7b2SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1944dda7b2Smrg
2044dda7b2SmrgExcept as contained in this notice, the name of The Open Group shall not be
2144dda7b2Smrgused in advertising or otherwise to promote the sale, use or other dealings
2244dda7b2Smrgin this Software without prior written authorization from The Open Group.
2344dda7b2Smrg *
2444dda7b2Smrg * Author:  Keith Packard, MIT X Consortium
2544dda7b2Smrg */
2644dda7b2Smrg
2744dda7b2Smrg#ifdef HAVE_CONFIG_H
2844dda7b2Smrg#include <config.h>
2944dda7b2Smrg#endif
3044dda7b2Smrg#include <X11/Xos.h>
3144dda7b2Smrg#include <X11/X.h>
3244dda7b2Smrg#include <X11/Xmd.h>
3344dda7b2Smrg#include <X11/Xdmcp.h>
3444dda7b2Smrg#include <stdlib.h>
3544dda7b2Smrg
3644dda7b2Smrgint
3744dda7b2SmrgXdmcpReadHeader (XdmcpBufferPtr buffer, XdmcpHeaderPtr header)
3844dda7b2Smrg{
3944dda7b2Smrg    if (XdmcpReadCARD16 (buffer, &header->version) &&
4044dda7b2Smrg        XdmcpReadCARD16 (buffer, &header->opcode) &&
4144dda7b2Smrg	XdmcpReadCARD16 (buffer, &header->length))
4244dda7b2Smrg	return TRUE;
4344dda7b2Smrg    return FALSE;
4444dda7b2Smrg}
4544dda7b2Smrg
4644dda7b2Smrgint
4744dda7b2SmrgXdmcpReadRemaining (const XdmcpBufferPtr  buffer)
4844dda7b2Smrg{
4944dda7b2Smrg    return buffer->count - buffer->pointer;
5044dda7b2Smrg}
5144dda7b2Smrg
5244dda7b2Smrgint
5344dda7b2SmrgXdmcpReadARRAY8 (XdmcpBufferPtr buffer, ARRAY8Ptr array)
5444dda7b2Smrg{
5544dda7b2Smrg    int	    i;
5644dda7b2Smrg
5744dda7b2Smrg    /*
5844dda7b2Smrg     * When returning FALSE, guarantee that array->data = 0.
5944dda7b2Smrg     * This allows the user to safely call XdmcpDisposeARRAY8(array)
6044dda7b2Smrg     * regardless of the return value below.
6144dda7b2Smrg     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
6244dda7b2Smrg     * so we must guarantee that array->data is NULL or a malloced pointer.
6344dda7b2Smrg     */
6444dda7b2Smrg    if (!XdmcpReadCARD16 (buffer, &array->length)) {
6544dda7b2Smrg 	array->data = NULL;
6644dda7b2Smrg	return FALSE;
6744dda7b2Smrg    }
6844dda7b2Smrg    if (!array->length)
6944dda7b2Smrg    {
7044dda7b2Smrg	array->data = NULL;
7144dda7b2Smrg	return TRUE;
7244dda7b2Smrg    }
7344dda7b2Smrg    array->data = (CARD8 *) malloc(array->length * sizeof (CARD8));
7444dda7b2Smrg    if (!array->data)
7544dda7b2Smrg	return FALSE;
7644dda7b2Smrg    for (i = 0; i < (int)array->length; i++)
7744dda7b2Smrg    {
7844dda7b2Smrg	if (!XdmcpReadCARD8 (buffer, &array->data[i]))
7944dda7b2Smrg	{
8044dda7b2Smrg	    free(array->data);
8144dda7b2Smrg	    array->data = NULL;
8244dda7b2Smrg	    array->length = 0;
8344dda7b2Smrg	    return FALSE;
8444dda7b2Smrg	}
8544dda7b2Smrg    }
8644dda7b2Smrg    return TRUE;
8744dda7b2Smrg}
8844dda7b2Smrg
8944dda7b2Smrgint
9044dda7b2SmrgXdmcpReadARRAY16 (XdmcpBufferPtr buffer, ARRAY16Ptr array)
9144dda7b2Smrg{
9244dda7b2Smrg    int	    i;
9344dda7b2Smrg
9444dda7b2Smrg    /*
9544dda7b2Smrg     * When returning FALSE, guarantee that array->data = 0.
9644dda7b2Smrg     * This allows the user to safely call XdmcpDisposeARRAY16(array)
9744dda7b2Smrg     * regardless of the return value below.
9844dda7b2Smrg     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
9944dda7b2Smrg     * so we must guarantee that array->data is NULL or a malloced pointer.
10044dda7b2Smrg     */
10144dda7b2Smrg    if (!XdmcpReadCARD8 (buffer, &array->length)) {
10244dda7b2Smrg	array->data = NULL;
10344dda7b2Smrg	return FALSE;
10444dda7b2Smrg    }
10544dda7b2Smrg    if (!array->length)
10644dda7b2Smrg    {
10744dda7b2Smrg	array->data = NULL;
10844dda7b2Smrg	return TRUE;
10944dda7b2Smrg    }
11044dda7b2Smrg    array->data = (CARD16 *) malloc(array->length * sizeof (CARD16));
11144dda7b2Smrg    if (!array->data)
11244dda7b2Smrg	return FALSE;
11344dda7b2Smrg    for (i = 0; i < (int)array->length; i++)
11444dda7b2Smrg    {
11544dda7b2Smrg	if (!XdmcpReadCARD16 (buffer, &array->data[i]))
11644dda7b2Smrg	{
11744dda7b2Smrg	    free(array->data);
11844dda7b2Smrg	    array->data = NULL;
11944dda7b2Smrg	    array->length = 0;
12044dda7b2Smrg	    return FALSE;
12144dda7b2Smrg	}
12244dda7b2Smrg    }
12344dda7b2Smrg    return TRUE;
12444dda7b2Smrg}
12544dda7b2Smrg
12644dda7b2Smrgint
12744dda7b2SmrgXdmcpReadARRAY32 (XdmcpBufferPtr buffer, ARRAY32Ptr array)
12844dda7b2Smrg{
12944dda7b2Smrg    int	    i;
13044dda7b2Smrg
13144dda7b2Smrg    /*
13244dda7b2Smrg     * When returning FALSE, guarantee that array->data = 0.
13344dda7b2Smrg     * This allows the user to safely call XdmcpDisposeARRAY32(array)
13444dda7b2Smrg     * regardless of the return value below.
13544dda7b2Smrg     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
13644dda7b2Smrg     * so we must guarantee that array->data is NULL or a malloced pointer.
13744dda7b2Smrg     */
13844dda7b2Smrg    if (!XdmcpReadCARD8 (buffer, &array->length)) {
13944dda7b2Smrg	array->data = NULL;
14044dda7b2Smrg	return FALSE;
14144dda7b2Smrg    }
14244dda7b2Smrg    if (!array->length)
14344dda7b2Smrg    {
14444dda7b2Smrg	array->data = NULL;
14544dda7b2Smrg	return TRUE;
14644dda7b2Smrg    }
14744dda7b2Smrg    array->data = (CARD32 *) malloc(array->length * sizeof (CARD32));
14844dda7b2Smrg    if (!array->data)
14944dda7b2Smrg	return FALSE;
15044dda7b2Smrg    for (i = 0; i < (int)array->length; i++)
15144dda7b2Smrg    {
15244dda7b2Smrg	if (!XdmcpReadCARD32 (buffer, &array->data[i]))
15344dda7b2Smrg	{
15444dda7b2Smrg	    free(array->data);
15544dda7b2Smrg	    array->data = NULL;
15644dda7b2Smrg	    array->length = 0;
15744dda7b2Smrg	    return FALSE;
15844dda7b2Smrg	}
15944dda7b2Smrg    }
16044dda7b2Smrg    return TRUE;
16144dda7b2Smrg}
16244dda7b2Smrg
16344dda7b2Smrgint
16444dda7b2SmrgXdmcpReadARRAYofARRAY8 (XdmcpBufferPtr buffer, ARRAYofARRAY8Ptr array)
16544dda7b2Smrg{
16644dda7b2Smrg    CARD8    i;
16744dda7b2Smrg
16844dda7b2Smrg    /*
16944dda7b2Smrg     * When returning FALSE, guarantee that array->data = 0.
17044dda7b2Smrg     * This allows the user to safely call XdmcpDisposeARRAYofARRAY8(array)
17144dda7b2Smrg     * regardless of the return value below.
17244dda7b2Smrg     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
17344dda7b2Smrg     * so we must guarantee that array->data is NULL or a malloced pointer.
17444dda7b2Smrg     */
17544dda7b2Smrg    if (!XdmcpReadCARD8 (buffer, &array->length)) {
17644dda7b2Smrg	array->data = NULL;
17744dda7b2Smrg	return FALSE;
17844dda7b2Smrg    }
17944dda7b2Smrg    if (!array->length)
18044dda7b2Smrg    {
18144dda7b2Smrg	array->data = NULL;
18244dda7b2Smrg	return TRUE;
18344dda7b2Smrg    }
18444dda7b2Smrg    array->data = (ARRAY8 *) malloc(array->length * sizeof (ARRAY8));
18544dda7b2Smrg    if (!array->data)
18644dda7b2Smrg	return FALSE;
18744dda7b2Smrg    for (i = 0; i < array->length; i++)
18844dda7b2Smrg    {
18944dda7b2Smrg	if (!XdmcpReadARRAY8 (buffer, &array->data[i]))
19044dda7b2Smrg	{
19144dda7b2Smrg	    /*
19244dda7b2Smrg	     * We must free all of the arrays allocated thus far in the loop
19344dda7b2Smrg	     * and free array->data and finally set array->data = 0;
19444dda7b2Smrg	     * The easiest way to do this is to reset the length and call
19544dda7b2Smrg	     * XdmcpDisposeARRAYofARRAY8(array).
19644dda7b2Smrg	     */
19744dda7b2Smrg	    array->length = i;
19844dda7b2Smrg	    XdmcpDisposeARRAYofARRAY8(array);
19944dda7b2Smrg	    return FALSE;
20044dda7b2Smrg	}
20144dda7b2Smrg    }
20244dda7b2Smrg    return TRUE;
20344dda7b2Smrg}
20444dda7b2Smrg
20544dda7b2Smrgint
20644dda7b2SmrgXdmcpReadCARD8 (XdmcpBufferPtr buffer, CARD8Ptr valuep)
20744dda7b2Smrg{
20844dda7b2Smrg    if (buffer->pointer >= buffer->count)
20944dda7b2Smrg	return FALSE;
21044dda7b2Smrg    *valuep = (CARD8) buffer->data[buffer->pointer++];
21144dda7b2Smrg    return TRUE;
21244dda7b2Smrg}
21344dda7b2Smrg
21444dda7b2Smrgint
21544dda7b2SmrgXdmcpReadCARD16 (XdmcpBufferPtr buffer, CARD16Ptr valuep)
21644dda7b2Smrg{
21744dda7b2Smrg    CARD8   high, low;
21844dda7b2Smrg
21944dda7b2Smrg    if (XdmcpReadCARD8 (buffer, &high) &&
22044dda7b2Smrg        XdmcpReadCARD8 (buffer, &low))
22144dda7b2Smrg    {
22244dda7b2Smrg	*valuep = (((CARD16) high) << 8) | ((CARD16) low);
22344dda7b2Smrg	return TRUE;
22444dda7b2Smrg    }
22544dda7b2Smrg    return FALSE;
22644dda7b2Smrg}
22744dda7b2Smrg
22844dda7b2Smrgint
22944dda7b2SmrgXdmcpReadCARD32 (XdmcpBufferPtr buffer, CARD32Ptr valuep)
23044dda7b2Smrg{
23144dda7b2Smrg    CARD8   byte0, byte1, byte2, byte3;
23244dda7b2Smrg    if (XdmcpReadCARD8 (buffer, &byte0) &&
23344dda7b2Smrg        XdmcpReadCARD8 (buffer, &byte1) &&
23444dda7b2Smrg	XdmcpReadCARD8 (buffer, &byte2) &&
23544dda7b2Smrg	XdmcpReadCARD8 (buffer, &byte3))
23644dda7b2Smrg    {
23744dda7b2Smrg	*valuep = (((CARD32) byte0) << 24) |
23844dda7b2Smrg		  (((CARD32) byte1) << 16) |
23944dda7b2Smrg		  (((CARD32) byte2) << 8) |
24044dda7b2Smrg		  (((CARD32) byte3));
24144dda7b2Smrg	return TRUE;
24244dda7b2Smrg    }
24344dda7b2Smrg    return FALSE;
24444dda7b2Smrg}
245