[comp.sys.hp] X11R4 xmh problems on HP series 800

andreas@hpcvlx.cv.hp.com (Jim Andreas) (02/20/90)

>  
>  I am using X11R4 on our HP 9000/800 with HP-UX 3.1, I am very pleased
>  everything works perfect, except for the new xmh.  I keep getting core
>  dumps from xmh at the most ill suited moments. As far as I can tell
>  the problems comes from the following lines taken from the file
>  command.c.
>  
>  
>  static /*void*/
>  CheckReadFromPipe( fd, bufP, lenP )
>      int fd;
>      char **bufP;
>      int *lenP;
>  {
>      long nread;
>      if (ioctl( fd, FIONREAD, &nread ) /*failed*/) {
>  	SystemError( "couldn't inquire bytes in pipe" );
>      }
>  
>  
>  The value returned by the FIONREAD ioctl is sometimes negative and
>  this causes bad problems later in the routine and finally a coredump
>  from bcopy().

Sorry but the word from the folks who know is that FIONREAD is 
broken when applied to pipes in HP-UX.  This will be fixed in 
a release to follow HP-UX 7.0.

>  I have not been able to find any documentation on the FIONREAD ioctl
>  at all, so I can not verify the use of it at all.

The documentation is cleverly hidden in termio(5), to wit (for those 
individuals with a desire to know):

FIONNREAD      Returns in the long integer referenced
               by arg the number of characters
               immediately readable from the terminal
               device file.  This command is allowed
               from a background process; however, the
               data itself cannot be read from a
               background process.

>  
>  Does anyone have any suggestions or ideas. 
>  Thanks in advance.
>  
>  --
>  
>  Arne Lundberg
>  
>  European Space Technology Centre, Noordwijk, the Netherlands
>  arne@yc.estec.nl or ALUNDBER@ESTEC.BITNET
>  Phone: +31 1719 84865, Fax: +31 1719 12142, Telex: 39098
>  ----------

I have attached a work-around code fragment.
Replace the CheckReadFromPipe() function in your MIT X11R4
xmh command.c file with the following.  The ugly loop
at the front inside the #ifdef hpux section puts the 
pipe into a "O_NDELAY" mode and reads bytes out one-by-one.

-----------------------------------------------------------------------
Jim Andreas             | andreas@cv.hp.com                | INTERNET
Hewlett-Packard Company | {backbone}!hplabs!hp-pcd!andreas | UUCP
1000 N.E. Circle        | (USA) (503) 750-2860             | VOICE
Corvallis, OR 97330     | (USA) (503) 750-3788             | FAX  
-----------------------------------------------------------------------
This response does not represent the official position of, or statement by,
the Hewlett-Packard Company.  The above data is provided for informational
purposes only.  It is supplied without warranty of any kind.
-----------------------------------------------------------------------

static /*void*/
CheckReadFromPipe( fd, bufP, lenP )
    int fd;
    char **bufP;
    int *lenP;
{
#ifdef   hpux
    int oldflags;
    int newflags;
    char c;
    /*
     * The FIONREAD ioctl is broken on HP-UX, so substitute
     * the following workaround.   This code sets the O_NDELAY
     * mode on the pipe, so that we can read from it without
     * blocking.  The code then reads bytes from the pipe
     * until the read returns with zero bytes.
     */
    if (( oldflags = fcntl( fd, F_GETFL, 0 )) < 0 )
	SystemError( "CheckReadFromPipe: error on fcntl F_GETFL" );
    newflags = oldflags | O_NDELAY;
    if ( fcntl( fd, F_SETFL, newflags ) < 0 )
	SystemError( "CheckReadFromPipe: error on fcntl F_SETFL" );

    if (read( fd, &c, 1 ) == 1 )
    {
	char * pChar;
	int    ByteCount = 1;
	int    old_len = *lenP;

	*bufP = XtRealloc( *bufP, (Cardinal) ((*lenP += BUFSIZ) + 1) );
	pChar = *bufP + old_len;
	*pChar++ = c;
	for ( ;; )
	{
	    int RetCode;

	    if (( RetCode = read( fd, &c, 1 )) == 0 )
	    {
		*pChar = '\0';
		break;
	    }
	    if ( RetCode < 0 )
	    {
		SystemError( "CheckReadFromPipe: error on read from pipe" );
		*pChar = '\0';
		break;
	    }
	    if ( ByteCount == BUFSIZ )
	    {
		old_len = *lenP;
		*bufP = XtRealloc( *bufP, (Cardinal) ((*lenP += BUFSIZ) + 1) );
		ByteCount = 0;
		pChar = *bufP + old_len;
	    }
	    *pChar++ = c;
	    ByteCount++;
	}
    }
    if ( fcntl( fd, F_SETFL, oldflags ) < 0 )
	SystemError( "CheckReadFromPipe: error on fcntl F_SETFL" );

#else /* hpux */

    long nread;
    if (ioctl( fd, FIONREAD, &nread ) /*failed*/) {
	SystemError( "couldn't inquire bytes in pipe" );
    }
    else if (nread) {
	char buf[BUFSIZ];
	int old_end = *lenP;
	*bufP = XtRealloc( *bufP, (Cardinal) ((*lenP += nread) + 1) );
	while (nread > BUFSIZ) {
	    read( fd, buf, BUFSIZ );
	    bcopy( buf, *bufP+old_end, BUFSIZ );
	    nread -= BUFSIZ;
	    old_end += BUFSIZ;
	}
	read( fd, buf, (int) nread );
	bcopy( buf, *bufP+old_end, (int) nread );
	(*bufP)[old_end+nread] = '\0';
    }
#endif /* hpux */
}