[comp.dcom.lans] STREAMS pipe driver

mark@applix.UUCP (Mark Fox) (11/16/87)

I just heard about this beast from someone with SVR3 sources. Apparently,
AT&T implemented this as a replacement for FIFOs but in their wisdom decided
not to document it.

Since we have processes that communicate with other processes on the
same machine as well as with others on remote machines, we need the
equivalent of Unix-domain or loop-back sockets. As you might expect,
we need to be able to multiplex input from local and remote processes. Now
an idle process could pend reading its FIFO and field SIGPOLLs. But a "more
elegant" approach, it would seem, is for a process to pend on a blocking
select (er, poll :-) system call awaiting messages from any process, local or
remote, that wants to talk to it. This is where a STREAMS pipe driver fits in.

Is the latter approach reasonable? Are people porting the pipe driver?
Is anybody willing to provide me with or post documentation on how to use it?
I have the Streams Programmer's Guide but I don't have a Unix source
license :-(

Thanx!
-- 
                                    Mark Fox
       Applix Inc., 112 Turnpike Road, Westboro, MA 01581, (617) 870-0300
                    uucp:  {ames,rutgers}!harvard!m2c!applix!mark

dougm@ico.UUCP (Doug McCallum) (11/22/87)

In article <620@applix.UUCP> mark@applix.UUCP (Mark Fox) writes:
>I just heard about this beast from someone with SVR3 sources. Apparently,
>AT&T implemented this as a replacement for FIFOs but in their wisdom decided
>not to document it.

Probably because it is something of a kludge.  It is only used by the
RFS name server, at least in a V.3.0 system.  FIFOs are a lot simpler 
and definitely more obvious how to use.

>elegant" approach, it would seem, is for a process to pend on a blocking
>select (er, poll :-) system call awaiting messages from any process, local or
>remote, that wants to talk to it. This is where a STREAMS pipe driver fits in.
>
>Is the latter approach reasonable? Are people porting the pipe driver?

The STREAMS pipe isn't quite what you expect, but would do the job.  If a V.3 
port supports RFS, it probably has the sp driver.

>Is anybody willing to provide me with or post documentation on how to use it?

Sure.  A quick summary of what is involved and then a quick hack program that
demonstrates how to use it.

You need to open two sp devices (open("/dev/spx", O_RDWR) will get a
new sp descriptor).  You then link the two descriptors together with
an I_FDINSERT ioctl call in order to get the other end connected.
Finally, you create a new device file with the mknod system call using
the major/minor numbers obtained with an fstat of the second file
descriptor.  This is what other processes use to communicate to the
first with.  When you read a message, you have no idea who sent it.
If you want a dedicated stream, you need to have the new process send
a new STREAM file descriptor to the server with an I_FDSEND ioctl.

			Doug McCallum
			Interactive Systems
			dougm@ico.isc.com


Here's the simple minded demonstration program:
--------------------------------------------------------------------------
/*
 * spdemo
 *	This program gets a pair of "streams pipe" file descriptors from
 * 	the clone open of "/dev/spx".  It then finds the major/minor
 *	number of the second descriptor, creates the special device file
 *	"/tmp/sp_server", links the two "pipes" together and then waits in
 *	a "getmsg" on the first file descriptor which will block until
 *	something gets written on the sp_server file.  A simple test is to
 *	run the following command:
 *		date >/tmp/sp_server
 *	from another terminal.  spdemo will print the date out.  Any streams
 *	operation may be performed, however.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stream.h>
#include <stropts.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

main()
{
  queue_t *dummy;
  int fd, fd2;

  struct stat statbuf;

  struct strbuf b1, b2;
  struct strfdinsert ins;

  char buff1[1024], buff2[1024];
  int opts = 0;

  fd = open("/dev/spx", O_RDWR);
  if (fd<0){
	perror("open");
	exit(1);
  }
  fd2 = open("/dev/spx", O_RDWR);
  if (fd2<0){
	perror("open");
	exit(1);
  }
  ins.databuf.maxlen = ins.databuf.len = -1;
  ins.databuf.buf = NULL;
  ins.ctlbuf.maxlen = ins.ctlbuf.len = sizeof(queue_t *);
  ins.ctlbuf.buf = &dummy;
  ins.offset = 0;
  ins.fildes = fd;
  ins.flags = 0;
  if (ioctl(fd2, I_FDINSERT, &ins)<0){
	perror("I_FDINSERT");
	exit(2);
  }

  if(fstat(fd2, &statbuf)<0){
	perror("fstat");
	exit(3);
  }
  if (mknod("/tmp/sp_server", S_IFCHR|0666, statbuf.st_rdev)<0){
	perror("mknod");
	exit(4);
  }

  b1.maxlen = sizeof buff1;
  b1.len = 0;
  b1.buf = buff1;

  b2.maxlen = sizeof buff2;
  b2.len = 0;
  b2.buf = buff2;

  if (getmsg(fd, &b1, &b2, &opts)<0){
	perror("getmsg");
  } else {
	if (b1.len > 0){
	    printf("control\n");
	}
	if (b2.len > 0){
	    printf("data: [%s]\n", buff2);
	}
  }
  unlink("/tmp/sp_server");
}

ekrell@ulysses.homer.nj.att.com (Eduardo Krell[arm]) (11/23/87)

In article <2003@ico.UUCP>, dougm@ico.UUCP writes:

> Finally, you create a new device file with the mknod system call using
> the major/minor numbers obtained with an fstat of the second file
> descriptor.

This will work only if you're root. mknod(2) on any device other than
a FIFO is restricted to root only (for obvious reasons).
-- 
    
    Eduardo Krell                   AT&T Bell Laboratories, Murray Hill

    {ihnp4,seismo,ucbvax}!ulysses!ekrell