[comp.windows.x] bugs in server/ddx/sun/sunInit.c

peterson@SW.MCC.COM (James Peterson) (11/03/88)

VERSION:
	X11 release 2 and release 3

CLIENT MACHINE:
	Sun 3/280

CLIENT OPERATING SYSTEM:
	SunOS 3.5

DISPLAY:
	CG2, BW2

SYNOPSIS:
	 Cannot get Sun X server to use colon-delimited list of devices for
	 -dev switch or environment variable

DESCRIPTION:
	 The man page for Xsun indicates that XDEVICE can be a colon-separated
	 list of devices, and implies that the -dev option is the same.
	 Code in sunInit.c uses 'nthdev' to step through the colon-separated
	 list and check each device.  However, the code only works for the
	 first device in the list.

REPEAT-BY:
	xinit -- Xsun -dev /dev/cgtwo0:/dev/bwtwo0
	xinit -- Xsun -dev /dev/bwtwo0:/dev/cgtwo0

FIX:

	The problem is that nthdev in server/ddx/sun/sunInit.c scans to 
	the first ':' but does not advance over it, so that when it goes for 
	the 2nd or subsequent devices, it immediately finds the ':' and thinks
	there was an empty device specified.  This can be corrected by 
	modifying nthdev as follows:

438a439
>     /* skip to the nth colon or end of the string; n is 0-origin */
440,442c441,445
< 	while (*dList && *dList != ':') {
< 	    dList++;
< 	}
---
>         /* find the next colon */
>         while (*dList != '\0' && *dList != ':') {
>             dList++;
>         }
>         if (*dList != '\0') dList++ /* skip colon */;
444,445d446
<     if (*dList) {
< 	register char *cp = dList;
447,452c448,450
< 	while (*cp && *cp != ':') {
< 	    cp++;
< 	}
< 	result = returnstring;
< 	strncpy (result, dList, cp - dList);
< 	result[cp - dList] = '\0';
---
>     /* if there was no nth colon -- return NULL */
>     if (*dList == '\0') {
>         result = (char *)NULL;
454c452,465
< 	result = (char *)0;
---
>         register char *cp = dList;
> 	short length;
> 
> 	/* we found the nth colon -- now find the next colon (or end of string)
> 	   and copy the delimited string to our buffer for return */
>         while (*cp != '\0' && *cp != ':') {
> 	    cp++;
>         }
>         result = returnstring;
> 	length = cp - dList;
> 	/* check that we do not exceed the length of our static returnstring */
> 	if (length > sizeof(returnstring)-1) length = sizeof(returnstring)-1;
> 	strncpy (result, dList, length);
> 	result[length] = '\0';


If you do this, however, another bug surfaces.  The two example lines
given above result in different displays: in the first case both cgtwo0
and bwtwo0 are used; in the second, only bwtwo0 is used.  This problem is
caused by code, also in server/ddx/sun/sunInit.c in sunOpenFrameBuffer that 
checks the list as follows:


<     if (devsw == (char *)NULL ||
< 	(name = nthdev (devsw, index)) == (char *)NULL ||
< 	(access (name, R_OK | W_OK) != 0) ||
< 	(strcmp(name, sunFbData[fbNum].devName) != 0)) {
< 	    name = (char *)NULL;

index is a count of the number of displays we have found.  fbNum
indicates the name/type of the display we are currently considering.
index will not be advanced until we accept the first device in the list.
So we check (in order) first cgtwo0.  Since we have bwtwo0 first in the
list and the names do not match, we do not find a cgtwo0.  Then we check
bwtwo0 and find it.  Now we advance index and are prepared to check the
cgtwo0, but we have already advanced fbNum (about 2 procedures higher in
the calling tree) past the cgtwo0 entry in sunFbData.  Hence the cgtwo0 is
not found.

Correcting this bug requires either a complete restructuring of the way
that the displays are considered, or simply that when we want to consider
a particular type of device (defined by fbNum) then we must search the
entire device (or XDEVICE) list for any devices of that name in the list.

With this latter approach, it is easiest to introduce an additional
procedure (CheckDeviceList) which calls nthdev repeatedly to check each
device in the device list for suitability.  Replace the current calls
to nthdev to a call to CheckDeviceList.  The diffs for the resulting
sunInit.c file are:

458a471,491
> 
> static char *
> CheckDeviceList(dList, fbNum)
> char *dList;
> int  fbNum;
> {
>   short index;
>   char *name;
> 
>   for (index = 0; (name = nthdev(dList,index)) != NULL; index++)
>     {
>       if ((strcmp(name, sunFbData[fbNum].devName) == 0)
>           && (access (name, R_OK | W_OK) == 0))
>         {
>           return(name);
>         }
>     }
>   return(NULL);
> }
> 
> 
522,527c555,558
<     if (devsw == (char *)NULL ||
< 	(name = nthdev (devsw, index)) == (char *)NULL ||
< 	(access (name, R_OK | W_OK) != 0) ||
< 	(strcmp(name, sunFbData[fbNum].devName) != 0)) {
< 	    name = (char *)NULL;
<     }
---
>     if (devsw != (char *)NULL)
>       {
> 	name = CheckDeviceList (devsw, fbNum);
>       }
536,541c567,572
<     if (devsw == (char *)NULL && name == (char *)NULL &&
< 	xdevice != (char *)NULL &&
< 	(name = nthdev(xdevice, index)) != (char *)NULL &&
< 	(access (name, R_OK | W_OK) != 0)) {
< 	    name = (char *)NULL;
<     }
---
>     if (devsw == (char *)NULL 
> 	&& name == (char *)NULL 
> 	&& xdevice != (char *)NULL)
>       {
> 	name = CheckDeviceList (xdevice, fbNum);
>       }

This still leaves a potential problem in that the order of the displays
found is defined by the order of the displays in the sunFbData array, not
by the order given by XDEVICE or -dev.  (that is, -dev a:b is the same as
-dev b:a) It would be reasonable to assume that the order would be defined
by the order in which the devices are given.

This bug was reported, with these fixes, in August.