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.