/* acf3:comp.os.vms / baxter@xmws.uucp /  2:33 am  Dec 22, 1990 */
In article <1990Nov20.184509.3252@objy.com>, ricks@prefect.objy.com (Rick L. Spickelmier) writes:
> I'm trying to get XtAddInput to work on VMS with the input 
> coming from a pipe connected to a subprocess (created with
	stuff deleted
> I just hang...  Does anybody use XtAddInput under VMS?  

Yes

> Is it with a subprocess via pipes?  

No 

I did a presentation on this at DECUS six months ago... get ahold of
the VAX Sig session notes from someone for the New Orleans Decus last spring.

You CANN'T DO IT with PIPES...  Which are ONLY SIMULATED on VMS. 

You need control of read completion from the mailbox that the pipe really is...

You _MUST_ do this in a VMS specific way, i.e. You MUST use the VMS QIO 
Mechansim and you must do it asynchonously... so that XtMainEventLoop will 
still have control...

The source argument to XtAddInput is really a VMS event flag number...
THIS is the key!!!!!

In your QIO read completion ast routine you must Set the event flag when
you have read something... This causes Xt to calback your XtInputCallback
routine... which can then process the data is "real" time as apposed to at
AST level.  NB: Xt on VMS is NOT AST reentrant 

In the simplest case: (where you let the OS buffer the IO, and you do not
do internal io buffering)

	your Application Q's a read, and returns to the main eventloop.

	The AST read completion routine reads the data and sets the efn 
	passed to XtAddInput.  

	Xt then calls the XtInputCallback routine.
	The XtInputCallback routine should clear the efn.   When the
	data is processed, it should Q the next read.

The code can be ISOLATED to a small IO module that is VMS specific.

Read the IO users guide on using mailboxes... this will tell you how to
setup the interprocess communication using mailboxes... (which is what
a pipe really is on VMS)

Code fragments for reading follow... its not complete but you
should get the idea...

#define cleared_bit_was_clear( bp, flgs ) ( _BBCCI( (bp), (flgs) ))
#define set_bit_was_set( bp, flgs )       ( _BBSSI( (bp), (flgs) ))

static long int read_ast ( IOBuffer * bufferP )
{
    long int ret_stat;
    sys$synch( read_QIO_efn, &bufferP->iosb );
    sys$setef ( Xt_read_efn  );
    put_on_Q_tail( bufferP, full_Q, ret_stat );
    cleared_bit_was_clear( ReadIsPending, &IO_flags );
}

long int StartReadIO()
{
    long int ret_stat;
    long int io_function;
    IOBuffer * bufferP;

    if ( set_bit_was_set( ReadIsPending, &IO_flags ) ) return 0;
    else
    {
        GetIOBuffer( &bufferP );
        ret_stat = sys$qio (
                       read_QIO_efn
                       ,IO_channel
                       ,IO$_READVBLK
                       ,&bufferP->iosb
                       ,&read_ast     /* ast routine.r */
                       ,bufferP         /* astprm.v */
                       ,bufferP->dataP
                       ,MaximumBufferLength
                       ,0
                       ,0 
                       ,0
                       ,0
                   );

        _ExitIfOSError( ret_stat, "SYS$QIO in IO:read_IO_started" );
    }
    return 1;
}
#undef ROUTINE

XtInputCallbackProc XtInputHandler( 
	caddr_t userdata, int * Source, XtInputId * id )
    /* we ignore the arguements,
     * this routine does the work in real time not ast time
     */
{
    int ret_stat;
    char * cp;
    IOBuffer * bufferP;

    ret_stat = sys$clref ( Xt_read_efn );
    ret_stat = remove_from_Q_head( full_Q, bufferP );
    switch ( ret_stat )
    {
          case Q_INTERLOCK_FAILED     :
                ExitWithMessage ( "Q_INTERLOCK_FAILED in XtInputHandler" );
          case Q_WAS_EMPTY            : return False;
          case REMQ_WERE_MORE_ENTRIES :
                        sys$setef ( Xt_read_efn ); /* call me again */
    }

    _ExitIfOSError( bufferP->iosb.condition ,"Bad iosb.condition in XtInputCallbackProc" );
    /* NOW extract data from buffer and process it */
    (*theProtocolDecodeProc)(
        bufferP->dataP, bufferP->iosb.transfer_cnt );

    /* now setup the next IO */
    put_on_Q_tail( bufferP, free_Q, ret_stat );
    StartReadIO();
    return False;
}
/* ---------- */