SRI-NOSC/ncpk/nopcls.c

Compare this file to the similar file:
Show the results in this format:

#
#include "param.h"
#include "inode.h"
#include "file.h"
#include "net_ncp.h"
#include "net_net.h"
#include "net_open.h"	/* for open parameters */
#include "user.h"
#include "conf.h"
#include "reg.h"
#include "net_contab.h"
#include "systm.h"

#ifdef SCCSID
/* SCCS PROGRAM IDENTIFICATION STRING */
char id_nopcls[] "~|^`nopcls.c\tV3.9E2\t09Mar78\n";
#endif

int ncpopnstate;       /*current state of ncp's io channel. 0=closed,>0=open*/

/*name:
	netopen

function:
	serves as an interface between the user in his open calls
	and the ncpdaemon, which actually does the opening of the
	connections.

algorithm:
	make sure ncp is up
	allocate a file for the user
	initialize flags bits for the file
	format an open command for the ncpdaemon
	if this is a server request plug in server and lskt num
	else
	if this is a standard open, second param a number between 0 and 4
	then set type to zero.
	else load user parameters from his space(fubyte)
	find a free entry in the network file table
	make that entry known to the network portions of the 
	system.
	send the open command off to the daemon(to_ncp)
	wait for a return
	check for an error ( hibyte zero, lobyte contains error type )
	point fid part of write socket at file
	mark file as user using
	set nominal allocation
	exit
	ERROR
	return file to system resources

parameters:
	aip	-	inode of the file specified as the first param
			to the open
			if zero means that this a request to issue a server
			open to the ncpdaemon
	mode	-	0 - 2 menas standard telnet open read, write, r/w
			any other number denotes a pointer to a structure
			of type nopen, with parameters filled in by the
			user.
			if aip is zero, mode is the local socket number
			to do the listen on.



returns:
	a file to be used in further communication with the network over
	this port
	or zero if there was an error

globals:
	none

calls:
	infiletab
	to_ncp
	bcopyin
	spl_imp

called by:
	open1 (sys2.c)
	tsrvopen	(newsrvtel.c)

history:
	initial coding 1/7/75 by S. F. Holmgren
	modified for parameterized open 6/11/75 Holmgren
	modified to net_frlse 7/8/76 by S. F. Holmgren (deleted below 20Apr78)
	modified to check for server open 8/27/76 by S. F. Holmgren
	modified by greep to see whether ncp is running
	modified by greep to free inode if no files available
	comment added at sleep 12Jun77 J.S.Kravitz
	inclusion of netopen.h for open parameters 12Jun77 J.S.Kravitz
	12Jun77 deleted setting rfnm rcvd bit in open J.S.Kravitz
	12Jun77 moved f_count++ to inside (infiletab()) if statement...
		if infiletab returned a null entry, the file descriptor
		would stay tied up forever
	14Jun77	J.S.Kravitz  put sleep in a loop to see if a wf_ready
		had really been done (FOPEN set)
		the ifdef SFHBYTE surrounds the following mods
	added multiple of 8 bytesize 01/27/78 S. F. Holmgren
	20Apr78	Rearranged code so that trapped signals don't hurt
		us if we never come back from the sleep J.S.Kravitz
	20Apr78	Removed the aip == 0 code, since it's not used JSK

*/

netopen (aip, mode)
struct inode *aip;
{

	struct openparams nopen;

	register *fp;		/* file ptr get aip for speed */
	register *ip;		/* inode ptr also for speed */
	register i;
	int hst;				/* for inode host num */

	/*
	 * get host number and release host spec file
	 */
	hst = (aip->i_addr[0]).d_minor;
	iput( aip );

	/* see whether ncp is up */
	if( ncpopnstate == 0 )
	{
		u.u_error = ENCPNO;	/* no ncp to use! (was ENXIO) */
		return;
	}

	/* does user have available files */
	if( fp=falloc() )
	{
		/* set default params in structure */
		for( ip= &nopen; ip <= &nopen.o_relid; *ip++ = 0 );
		fp->f_inode = 0;	/* make sure file struct inited */

		/* this an open with params or stnd telnet? */
		if( mode < 1 || mode > 3)
		{
			/*
			 * user has specified parameters, so copy them in
			 */
#ifndef UCBUFMOD
			bcopyin (mode, &nopen, sizeof nopen);
#endif UCBUFMOD
#ifdef UCBUFMOD
			for(ip = &nopen, i = 0; i < sizeof nopen; i=+2)
				*ip++ = fuword(mode + i);
#endif UCBUFMOD
			if( (i=nopen.o_relid) >= 0 && i < NOFILE )/* he give relid */
				nopen.o_relid = getf( i );	/* yes then trans */
			mode = (FREAD|FWRITE);			/* set mode */
		}
		if( nopen.o_frnhost == 0 )	/* if no frh host */
			nopen.o_frnhost = hst;	/* use hst from inode */

		nopen.o_op = ncp_open;			/* set open opcode */
		nopen.o_id = fp;			/* give daemon id */

		spl_imp();
		/*
		 * because we may never come back from the sleep
		 * later, we fudge the ofile descripter JSK
		 */
		u.u_ofile[u.u_ar0[R0]] = 0;

		if( ( ip = infiletab( 0 ) ) )		/* get file tab entry */
		{
			fp->f_flag = (FNET|mode);	/* init access and type */
			*ip = fp;			/* use file entry */
			spl0();
			to_ncp( &nopen, sizeof nopen, 0 );	/* send open off */
			do {
				sleep (fp, NETPRI);	/* wait for open */
				if( fp->f_flag & FERR )	/* get an error */
				{
					/*
					 * Return a useful error code to the
					 * user from the ncpdaemon
					 */
					u.u_error = fp->f_netnode[f_rdnode];
					return;
				}
			} while ( ! (fp->f_flag & FOPEN) );

			/*
			 * this was moved here to compensate for the fact
			 * that the user may not ever return from the
			 * sleep, if the user gets a trapped signal
			 */
			fp->f_count++;		/* inc count for ncp use */

			/* if there is a read socket */
			if( (ip=fp->f_netnode[f_rdnode]))
			{
				ip->r_flags =| n_usriu;	/* mark user using */
				/* set nominal allocation */
#ifndef SFHBYTE
				ip->r_hiwat = nopen.o_nomall?nopen.o_nomall:256;
#endif
#ifdef SFHBYTE
				ip->r_hiwat = nopen.o_nomall?nopen.o_nomall:
					((256*8)/ip->r_bsize);
#endif
			}
			/* if there is a write socket */
			if( (ip=fp->f_netnode[f_wrtnode]))
			{
				ip->w_flags =| n_usriu;	/* mark user using */
				ip->w_fid = fp;	/* load local file id */
			}
			/*
			 * this reloads the open file descriptor in
			 * the U, now that the file is really open
			 * JSK
			 */
			u.u_ofile[u.u_ar0[R0]] = fp;
			return;
		}
		else
		{
			/*
			 * decrement file descriptor use count (to zero)
			 * since we didn't need it after all
			 */
			--fp->f_count;
			u.u_error = EMNETF;	/* to many open net files */
						/* was EMFILE */
		}
	}
}

/*name:
	netclose

function:
	serves to initiate a close to the ncpdaemon in response to a user
	close on a network file

algorithm:
	if i am second to last guy closing the file 
		tell the last guy to close ( he may be hung on a read )
	if i am the last guy closing the file
		check each possible socket
			if its there
				if ncp still using
					send close
				destroy the socket

		call net_frlse and try to give back the file

parameters:
	afp	-	a pointer to the file which indirectly contains
			pointers to any inodes associated with the connection

returns:
	nothing

globals:
	none

calls:
	wakeup
	daecls
	daedes
	net_frlse
	incontab
	rmcontab

called by:
	closef	(fio.c)
	tsrvcls	(newsrvtel.c)

history:
	initial coding 1/7/75 by S. F. Holmgren
	modified to call net_frlse 7/8/76 by S. F. Holmgren
	modified by greep to remove connection table entry

*/

netclose( afp )
struct netfile *afp;
{

	register i;
	register struct netfile *fp;	/* afp for speed */
	register *sktp;			/* pointer to inode for speed */
	
	
	fp = afp;

	/* is this the second to last guy out ?? */
	if( fp->f_count == 3 )
	{

		/* yes then possibly tell someone waiting on rdskt */
		if( sktp = fp->f_netnode[ f_rdnode ] ) /* read skt? */
		{
			/* reset open */
			sktp->r_flags =& ~n_open;
			/* set eof */
			sktp->r_flags =| n_eof;
			/* let user know that close is taking place */
			wakeup( sktp );
		}
	}

	/* is this the last guy out ?? */
	if( fp->f_count <= 2 )
	{

		for( i=0; i < 3; i++ )
			if( (sktp = fp->f_netnode[i]) >= &inode[0] ) /* each inode*/
			{
				if( sktp->r_flags & n_ncpiu )
					daecls( fp,i );         /* say im closing */
				if( sktp->r_hostlink )
				    rmcontab( incontab( sktp->r_hostlink,sktp ) );
				daedes( fp,i );
			}

	}
	net_frlse( fp );		/* decrement count and release if done  */
}

/*name:
	net_frlse

function:
	decrement the number of users who have a file
	if the count is zero, release the file.

algorithm:
	decrement the count
	if the count is zero 
		if the file is in the file table
			take it out
		clean up the flag field of the file

parameters:
	address of the file to be cleaned up

returns:
	nothing

globals:
	none

calls:
	infiletab

called by:
	wf_frlse	(ncpio.c)
	netopen
	netclose

history:
	initial coding 7/8/76 by S. F. Holmgren

*/
net_frlse( afp )
struct netfile *afp;
{
	register struct netfile *fp;
	register int *p;

	fp = afp;
	if( --fp->f_count == 0 )
	{
		/* file is release by zero count clean up */
		if( p = infiletab( fp ) )
			*p = 0;		/* take it out of filetab */
		fp->f_flag = 0;		/* clean up flags field */
	}
}

/*name:
	daecls

function:
	sends a close command to the ncpdaemon

algorithm:
	build the close command according to structure nclose
	send it to the ncpdaemon

parameters:
	a pointer to a file
	and offset into that structure specifing which inode the close
	references

returns:
	nothing.

globals:
	none

calls:
	to_ncp

called by:
	netclose
	iclean	(ncpio.c)

history:
	initial coding 1/7/75 by S. F. Holmgren

*/

daecls( afp,offset )
struct netfile *afp;
char offset;
{

	struct
	{
		char c_op;	/* contains close opcode */
		char c_indx;	/* indx into f_netnode of skt to close */
		struct netfile *c_fp;	/* file ptr for daemon */
	} nclose;

	nclose.c_op = ncp_close;	/* load close opcode */
	nclose.c_indx = offset;		/* load offset */
	nclose.c_fp = afp;		/* load file pointer */

	to_ncp( &nclose,4,0 );		/* send off to ncp */

}

/*name:
	daedes

function:
	to release an inode to the system

algorithm:
	remove the entry from the appropriate connection table
	release in associated queued data
	clean up the inode
	release the inode

parameters:
	a pointer to a file containing a pointer to the inode to be
	released
	and offset into that file structure, denoting which inode
	to be released.

returns:
	nothing

globals:
	none

calls:
	freemsg

called by:
	netclose
	iclean	(ncpio.c)

history:
	initial coding 1/7/75 by S. F. Holmgren
	modified to call freemsg 7/7/76 by S. F. Holmgren
	modified by greep - no longer removes connection
	   table entry (this has already been done)
	modified by JSK - spl_imp around some of release code, so that
		consistancy check code works ok

*/

daedes( afp,offset )
struct netfile *afp;
char offset;
{

	register struct netfile *fp;
	register int *ip;
	register int *sktp;
	int	saveps;

	fp = afp;
	ip = fp->f_netnode[offset];
	if( ip == 0 )	return;

	/* free any queued data if this is read socket */
	if( offset == f_rdnode )
		freemsg( ip->r_msgq );

	saveps = PS->integ;
	spl_imp();
	/* point ip at top of inode instead of i_addr array */
	ip =- 7;
	
	/* clean up inode */
	for( sktp = &ip->i_dev; sktp <= &ip->i_addr[8]; sktp++ )
		*sktp = 0;

	/* reset file socket pointer */
	fp->f_netnode[offset] = 0;

	/* release inode */
	ip->i_flag = ip->i_count = ip->i_lastr = 0;

	PS->integ = saveps;


}
/*name:
	netstat

function:
	return host, localsocket, and foreignsocket from read connection

algorithm:
	if read socket exists
		if there is a connection table entry 
			copy in relavent info
			copy info into user

parameters:
	address of a network file
	user address

returns:
	nothing

globals:
	contab

calls:
	incontab

called by:
	stat (sys3)

history:
	initial coding 4/16/75 by S. F. Holmgren
	12Jun77 J.S.Kravitz Inclusion of openparams used in
		declaration. Note that the connection table should
		eventually use long integers

*/
netstat( filep,usraddr )
{

	register *fp;
	register *conp;
	register ip;

	struct	openparams nopen;	/* place to build returned info */

	fp = filep;
	if( (ip = fp->f_netnode[ f_rdnode ]) != 0 )
		if( (conp=incontab( ip->r_hostlink,ip )) != 0 )
		{
			nopen.o_frnhost = conp->c_hostlink>>8;
			nopen.o_lskt    = conp->c_localskt;
			nopen.o_fskt[0] = conp->c_fskt[0];
			nopen.o_fskt[1] = conp->c_fskt[1];
			ip = sizeof nopen>>1;
			fp = usraddr;
			conp = &nopen;
			do
				suword( fp++,*conp++ );
			while( --ip );
			return;
		}
	u.u_error = EBADF;
}