home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume26
/
sps3
/
part02
/
stream.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-08
|
5KB
|
227 lines
# ifndef lint
static char SccsId[] = "@(#)stream.c 1.3\t8/22/91" ;
# 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