home *** CD-ROM | disk | FTP | other *** search
- # ifndef lint
- static char SccsId[] = "@(#)stream.c 1.2\t7/4/90" ;
- # endif
-
- # ifdef SUNOS40
- # include "sps.h"
- # include <h/stream.h>
- # include <h/vnode.h>
- # ifdef SUNOS41
- # include <h/strstat.h>
- # endif
-
- static struct stdata *pstreams ;
- static struct stdata *pstreamsNSTREAMS ;
-
- init_streams_tab()
- {
- int len ;
- extern struct info Info ;
- register struct stdata *s ;
- struct vnode *v ;
- char *getcore() ;
-
- if ( pstreams )
- /* reinitializing */
- for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
- if ( s->sd_vnode != 0 )
- free( (char*)s->sd_vnode ) ;
- free( (char*)pstreams ) ;
- # ifdef SUNOS41
- /*
- * In SunOS 4.1, the stream heads are in a linked list. A
- * `struct strstat' contains the number of active streams; the
- * variable `allstream' points to an apparently random
- * position in a doubly linked `struct stdata' chain.
- *
- * To find all streams we'll have to scan the chain forwards
- * AND backwards from `allstream'. `int going_forwards' below
- * tells which direction we are currently going. Weird.
- *
- */
-
- {
- struct strstat strst ;
- int n ;
- long addr ;
- struct stdata *this_stream ;
- int going_forwards = 1 ;
-
- if ( getkmem ((long) Info.i_strst, (char *) &strst,
- sizeof ( struct strstat )) != sizeof ( struct strstat ))
- return 0 ;
- len = strst.stream.use * sizeof( struct stdata ) ;
- pstreams = (struct stdata *)getcore (len ) ;
- addr = (long)Info.i_allstream ;
- this_stream = pstreams ;
- pstreamsNSTREAMS = pstreams - 1 ;
- for (n = 0 ; n < strst.stream.use ; n++)
- {
- if ( getkmem ( addr, (char *) this_stream,
- sizeof ( struct stdata ))
- != sizeof ( struct stdata ))
- {
- /*
- * If we are following the `sd_next' chain we'll
- * have to start over from the stream pointed to
- * by Info.i_allstream and scan `sd_prev'
- * backwards.
- */
- if ( going_forwards && n > 0 )
- {
- going_forwards = 0 ;
- addr = (long) pstreams[0].sd_prev ;
- n--;
- continue ;
- }
- if ( pstreamsNSTREAMS < pstreams )
- return 0 ;
- break ;
- }
- addr = going_forwards ? (long) this_stream->sd_next :
- (long) this_stream->sd_prev ;
- this_stream++ ;
- pstreamsNSTREAMS++ ;
- }
- }
- # else SUNOS41
- len = ((Info.i_streamsNSTREAMS - Info.i_streams) + 1)
- * sizeof( struct stdata ) ;
- pstreams = (struct stdata *)getcore( len ) ;
- pstreamsNSTREAMS = pstreams + (len / sizeof( struct stdata ) ) ;
- if ( getkmem( (long)Info.i_streams, (char *)pstreams, len ) != len )
- return( 0 ) ;
- # endif SUNOS41
-
- for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
- if ( s->sd_vnode != 0 )
- {
- if ( ( v = (struct vnode*)getcore( sizeof( *v ) ) )
- && getkmem( (long)s->sd_vnode, (char*)v, sizeof( *v ) )
- == sizeof( *v ) )
- {
- s->sd_vnode = v ;
- continue ;
- }
-
- s->sd_vnode = 0 ;
- }
- return( 1 ) ;
- }
-
-
- # ifdef SUNOS41
- struct sess *find_session ( addr )
-
- struct sess *addr ;
-
- {
- /*
- * SunOS 4.1 seems to store controlling tty's in a "struct
- * sess" which is accessible as p->p_sessp. Another layer
- * of indirection to wade through...
- *
- * To make this a tiny bit faster, I'll store sessions in a
- * linked list as I read them in with getkmem; subsequent
- * calls to find_session() check the cache.
- */
-
- struct sps_sess {
- struct sess sess ;
- struct sess *addr ;
- struct sps_sess *next ;
- };
-
- static struct sps_sess *sessions ; /* Cache of known sessions*/
- register struct sps_sess *s ;
-
- /* Try to find the session in the cache */
- for ( s = sessions ; s ; s = s->next )
- if ( s->addr == addr )
- return &s->sess ;
- /* Not found; get it from kmem and put it in the cache */
- s = (struct sps_sess *)getcore( sizeof ( struct sps_sess ) ) ;
- if ( getkmem ((long) addr, (char *) &s->sess,
- sizeof ( struct sess )) != sizeof ( struct sess ) )
- return 0 ;
- s->addr = addr ;
- s->next = sessions ;
- sessions = s ;
- return &s->sess ;
- }
- # endif SUNOS41
-
- struct stdata *getstdata ( st, dev )
-
- struct streamtab *st ;
- dev_t dev ;
-
- {
- register struct stdata *s ;
-
- for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
- if ( s->sd_strtab == st && s->sd_vnode
- && s->sd_vnode->v_rdev == dev )
- return( s ) ;
- return( 0 ) ;
- }
-
- /* 1 if `w' is in the address range defined by `a1' and `a2' ... */
- # define INRANGE( w, a1, a2 ) \
- ( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) )
-
- char *gettty ( lp, w )
-
- register struct ttyline *lp ;
- caddr_t w ;
-
- {
- struct stdata *s ;
- struct queue *q ;
- struct queue qq[2] ;
- char *cp = 0 ;
-
- if ( ( s = lp->l_stdata ) == 0 )
- return( 0 ) ;
-
- q = s->sd_wrq ; /* get write queue (only queue_t in stdata) */
- do
- {
- if ( INRANGE( w, RD( q ), q ) )
- { /* check read queue */
- cp = "rtty??" ;
- break ;
- }
- if ( INRANGE( w, q, WR ( q ) ) )
- { /* check write queue */
- cp = "wtty??" ;
- break ;
- }
- /* check queue private data structures - useful??? */
- if ( getkmem( (long)RD( q ), (char*)qq, sizeof( qq ) )
- != sizeof( qq ) )
- break ;
- if ( INRANGE( w, qq[0].q_ptr, qq[0].q_ptr + 1 ) )
- {
- cp = "r?ty??" ;
- }
- if ( INRANGE( w, qq[1].q_ptr, qq[1].q_ptr + 1 ) )
- {
- cp = "w?ty??" ;
- }
- q = qq[1].q_next ;
- }
- while ( q ) ;
- if ( cp )
- {
- cp[4] = lp->l_name[0] ;
- cp[5] = lp->l_name[1] ;
- return( cp ) ;
- }
- return( 0 ) ; /* chain down list? */
- }
- # endif SUNOS40
-
-