[comp.unix.wizards] how to create stream pipe

stevens@hsi.UUCP (Richard Stevens) (01/11/89)

I'm trying to figure out how to create a "stream pipe" with System 5,
Release 3.2 (386 version).  The streamio(7) man page says the only
way to pass a file descriptor is using these, but I can't find
any reference as to how a stream pipe is created.  In Steve
Bellovin's "Session TTY Manager" paper from the San Francisco
Usenix, he describes the "strange" way they're created under
Research Unix, but I can't find any mention of /dev/spx in my
System 5 manuals.

	Richard Stevens
	Health Systems International, New Haven, CT
	   stevens@hsi.com
           ... { uunet | yale } ! hsi ! stevens

dougm@ico.ISC.COM (Doug McCallum) (01/12/89)

In article <244@hsi86.hsi.UUCP> stevens@hsi.UUCP (Richard Stevens) writes:
>I'm trying to figure out how to create a "stream pipe" with System 5,
>Release 3.2 (386 version).  The streamio(7) man page says the only
>way to pass a file descriptor is using these, but I can't find
>any reference as to how a stream pipe is created.  In Steve

I don't believe there is any "clear" documentation on using them since
the streams pipe is sort of a kludge to get RFS started.  I say kludge
because spx violates most STREAMS conventions and has problems if you
attempt to push a module on it.  You also need to be running as root
to do things unless you get prearranged dev entries.  (this is based
on V.3.0 not 3.2)

Quick summary is that you open /dev/spx twice, connect the two
streams, create a device file for one of them (using the major/minor
found via fstat) and close the one that you want others to connect on.

Hope this is of some help,
Doug McCallum
Interactive Systems Corp.
dougm@ico.isc.com


The following is a quick-and-dirty program to show the mechanism of
setting one up.
---------------------------------------------------------------------
/*
 * 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.  Almost
 *	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");
}

dougm@ico.ISC.COM (Doug McCallum) (01/12/89)

One thing I didn't mention is that if all you want are two STREAMS
endpoints connected like normal pipes except bi-directional, you
can omit the mknod step and give one end to a child process.  This
doesn't require being root, only the mknod does.

larry@hcr.UUCP (Larry Philps) (01/16/89)

In article <244@hsi86.hsi.UUCP> stevens@hsi.UUCP writes:
>I'm trying to figure out how to create a "stream pipe" with System 5,
>Release 3.2 (386 version).  The streamio(7) man page says the only
>way to pass a file descriptor is using these, but I can't find
>any reference as to how a stream pipe is created.  In Steve
>Bellovin's "Session TTY Manager" paper from the San Francisco
>Usenix, he describes the "strange" way they're created under
>Research Unix, but I can't find any mention of /dev/spx in my
>System 5 manuals.
>
>	Richard Stevens
>	Health Systems International, New Haven, CT
>	   stevens@hsi.com
>           ... { uunet | yale } ! hsi ! stevens

Call the function "spipe" exactly as you would call "pipe" and then link
your program against the -lns library.
---
Larry Philps                             HCR Corporation
130 Bloor St. West, 10th floor           Toronto, Ontario.  M5S 1N5
(416) 922-1937                           {utzoo,utcsri,decvax,ihnp4}!hcr!larry