Article 2693 of comp.sources.unix:
Path: nntpd.lkg.dec.com!crl.dec.com!crl.dec.com!caen!hookup!solaris.cc.vt.edu!homer.alpha.net!uwm.edu!chi-news.cic.net!newsfeed.internetmci.com!in2.uu.net!vixie!vixie!not-for-mail
From: thoth@cis.ufl.edu (Robert H. Forsman, Jr)
Newsgroups: comp.sources.unix
Subject: v29i037: netpipes-3 -- BSD network pipe tools, V3, Part01/01
Date: 24 Oct 1995 15:27:07 -0700
Organization: Vixie Enterprises
Lines: 4312
Sender: vixie@vix.com
Approved: vixie@gw.home.vix.com
Message-ID: <1.814573567.17907@gw.home.vix.com>
NNTP-Posting-Host: gw.home.vix.com

Submitted-By: thoth@cis.ufl.edu (Robert H. Forsman, Jr)
Posting-Number: Volume 29, Issue 37
Archive-Name: netpipes-3/part01

This is an update of netpipes from Volume 26.

faucet and hose:
  These two utilities are useful for connecting arbitrary programs
over sockets.  The power of the '|' character in the shell can now be
used over the network.

#!/bin/sh
# This is a shell archive (produced by shar 3.50)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/24/1995 21:54 UTC by thoth@coast
# Source directory /tmp/netpipes3.0
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1835 -r--r--r-- README
#   2196 -r--r--r-- Makefile
#   5348 -rw-r--r-- common.c
#   1802 -rw-r--r-- common.h
#    679 -rw-r--r-- version.c
#   7264 -rw-r--r-- faucet.1
#  11590 -rw-r--r-- faucet.c
#   6980 -r--r--r-- hose.1
#  12117 -rw-r--r-- hose.c
#   4263 -rw-r--r-- sockdown.1
#   2095 -rw-r--r-- sockdown.c
#   6118 -r--r--r-- getpeername.1
#   4042 -rw-r--r-- getpeername.c
#   4616 -r--r--r-- netpipes.1
#   7904 -rw-r--r-- faucet.html
#   6557 -rw-r--r-- getpeername.html
#   7541 -rw-r--r-- hose.html
#   5041 -rw-r--r-- netpipes.html
#   4558 -rw-r--r-- sockdown.html
#  17981 -rw-r--r-- COPYING
#
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
	echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
X  Enjoy NETPIPES 3
X
X  by Robert Forsman
X
X  Check the Makefile.  You will want to change where it installs
stuff.  Some systems require extra libraries or compile flags.
X
X  There has been a change in the way that the subcommand is specified.
It is MUCH better than the old way.  Read the manual pages.
X
X  I think USE_IOCTL is now required.  This is because I don't know the
canonical portable way to disassociate myself from the controlling
terminal.  If anyone can tell me how to do this without using ioctl,
please do.
X
X  Also, I need portable ways to clean up child processes.  Maybe I'll
just read the perl source one day.
X
X  This program has, in the past, been compiled and tested on a DEC
5100, an RS6k, an HP9k, an SGI and sees almost daily usage under SunOS
4.1.3 and Linux.
X
X  If you compile this program on an architecture/OS not mentioned
above, drop me a line.  If you have problems compiling on any
architecture, I want to hear about it (and I'll try to help you fix
the problem and make sure that the next version compiles out of the
box).
X
X  Normally, I say all software sucks, but I can now proudly say that
NETPIPES RULES!  If you disagree, tell me why and I'll see if I can
fix it.
X
X  HEY CYPHERPUNKS!
X
X  I'm having difficulty thinking of new things to add to netpipes.
The only thing I would like to add is some sort of authorization/
encryption filter so that two processes which normally wouldn't care
about authentication/encryption could be secured.
X
X  I would write an RSA thingy myself, but I'm a U.S. citizen and
suffer from unwieldy export restrictions (yes, my appointed officials
are twits).  If somebody in the U.K. (or wherever encryption is legal
to export) ever does write an encryption filter compatible with
netpipes, could you talk to me and I'll have you make a combo package
for export to the U.S.
SHAR_EOF
chmod 0444 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 1835 -eq "$Wc_c" ||
	echo 'README: original size 1835, current size' "$Wc_c"
fi
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
#    faucet and hose: network pipe utilities
#    Copyright (C) 1992,1993 Robert Forsman
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
# You probably want to change this:
INSTROOT = ${HOME}
INSTBIN = ${INSTROOT}/bin
INSTMAN = ${INSTROOT}/man
X
# This might be necessary for HPUX
#LDLIBS=-lBSD
X
# I'm told this is required for Sequent SysV
#LDLIBS=-lsocket -linet -lnsl
X
# This will be necessary for Sun Solaris (the abomination)
#LDLIBS=-lsocket -lnsl
X
# For SunOS, add -DNO_MEMMOVE.  It doesn't have this very handy function.
X
# If you don't want to use (or don't have) fcntl(2) try the -DUSE_IOCTL.
X
# Add -DSYSV if your signal handlers need reinstalling after being called.
# hpux has been known to require this.  Solaris may or may not.  I haven't
# experimented enough.
CFLAGS = -DUSE_IOCTL -g -DNO_MEMMOVE
X
FOBJS = faucet.o common.o version.o
HOBJS = hose.o common.o version.o
SOBJS = sockdown.o version.o
GOBJS = getpeername.o version.o
X
MANPAGES = netpipes.1 faucet.1 hose.1 sockdown.1 getpeername.1
PROGRAMS = faucet hose sockdown getpeername
X
all	: ${PROGRAMS}
X
faucet	: ${FOBJS}
X	${CC} ${CFLAGS} -o $@ ${FOBJS} ${LDLIBS}
X
hose	: ${HOBJS}
X	${CC} ${CFLAGS} -o $@ ${HOBJS} ${LDLIBS}
X
sockdown: ${SOBJS}
X	${CC} ${CFLAGS} -o $@ ${SOBJS} ${LDLIBS}
X
getpeername: ${GOBJS}
X	${CC} ${CFLAGS} -o $@ ${GOBJS} ${LDLIBS}
X
install : all
X	cp ${PROGRAMS} ${INSTBIN}/
X	ln -s getpeername ${INSTBIN}/getsockname
X	cp ${MANPAGES} ${INSTMAN}/man1/
X
clean	:
X	rm -f ${FOBJS} ${HOBJS} ${SOBJS}
X
spotless: clean
X	rm -f *~ core ${PROGRAMS}
SHAR_EOF
chmod 0444 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 2196 -eq "$Wc_c" ||
	echo 'Makefile: original size 2196, current size' "$Wc_c"
fi
# ============= common.c ==============
if test -f 'common.c' -a X"$1" != X"-c"; then
	echo 'x - skipping common.c (File already exists)'
else
echo 'x - extracting common.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'common.c' &&
/*
X
X    $Id: common.c,v 1.8 1995/10/24 19:15:47 thoth Exp thoth $, part of
X    faucet and hose: network pipe utilities
X    Copyright (C) 1992-95 Robert Forsman
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X    */
X
#include	<stdio.h>
#include	<fcntl.h>
#include	<errno.h>
#include	<sys/socket.h>
#include	<sys/un.h>
#include	<netdb.h>
#include	<netinet/in.h>
#include "common.h"
X
char *programname;
X
/**********************************************************************/
X
int	*fds=0;
int	nfds;
int	fdsize=0;
X
int how_shutdown = -2;
X
void add_fd(fd)
X    int	fd;
{
X    if (fds==0) {
X	fds = (int*)malloc(sizeof(*fds)*(fdsize=4));
X    } else if (nfds >= fdsize) {
X	fds = (int*)realloc(sizeof(*fds)*(fdsize*=2));
X	if (fds==0) {
X	    fprintf(stderr, "%s: Out of memory\n", programname);
X	    exit(1);
X	}
X    }
X    fds[nfds++] = fd;
X    if (fd>2)
X	/* We should reserve this spot in the file descriptor table.
X	 If we don't it could get allocated by the socket(2) call and
X	 we would have an awful mess on our hands. */
X	dup2(0, fd);
}
X
void dup_n(socket)
X    int	socket;
{
X    int	i;
#if 0
X    printf("I will redirect fds");
X    for (i=0; i<nfds; i++) {
X	printf(" %d", fds[i]);
X    }
X    printf(" and shutdown with %d\n", how_shutdown);
#endif
X    if (how_shutdown>=0)
X	shutdown(socket, how_shutdown!=0);
X    for (i=0; i<nfds; i++) {
X	dup2(socket, fds[i]);
X    }
}
X
/**********************************************************************/
X
int name_to_inet_port(portname)
char *portname;
/* This procedure converts a character string to a port number.  It looks
X   up the service by name and if there is none, then it converts the string
X   to a number with sscanf */
{
X  struct servent	*p;
X
X  if (portname==NULL)
X    return 0;
X
X  p = getservbyname(portname,"tcp");
X  if (p!=NULL)
X    {
X      return p->s_port;
X    }
X  else
X    {
X      int	port;
X      if (sscanf(portname,"%i",&port)!=1)
X	{
X	  return 0;
X	}
X      else
X	return htons(port);
X    }
}
X
struct in_addr ** /* addr_array */
convert_hostname(name, count_ret)
X    char	*name;
X    int		*count_ret;
{
X  struct hostent	*hp;
X  int		len;
X  struct in_addr	**rval;
X
X  hp = gethostbyname(name);
X  if (hp != NULL) {
X    int	i;
X    if (hp->h_length != sizeof(struct in_addr)) {
X	fprintf(stderr, "%s: Funky: (hp->h_length = %d) != (sizeof(struct in_addr) = %d)\n", programname, hp->h_length, sizeof(struct in_addr));
X    }
X    for (i = 0; hp->h_addr_list[i]; i++)
X	{ }
X    *count_ret = i;
X    rval = (struct in_addr **)malloc(sizeof(*rval) * (i+1));
X    for (i=0; i<*count_ret; i++) {
X	rval[i] = (struct in_addr*)malloc(hp->h_length);
X	memcpy((char*)rval[i], hp->h_addr_list[i], hp->h_length);
X    }
X    rval[*count_ret] = 0;
X    return rval;
X  } else {
X      int	count;
X      unsigned int	a1,a2,a3,a4;
X      count = sscanf(name,"%i.%i.%i.%i%n", &a1, &a2, &a3, &a4, &len);
X      if (4!=count || 0!=name[len] )
X	return 0;
X
X      *count_ret = 1;
X      rval = (struct in_addr**)malloc(2*sizeof(*rval));
X      rval[0] = (struct in_addr*)malloc(sizeof(struct in_addr));
X      rval[0]->s_addr = (((((a1 << 8) | a2) << 8) | a3) << 8) | a4;
X      rval[1] = 0;
X      return rval;
X  }
}
X
X
int
bindlocal(fd, name, addrname, domain)
X     int	fd, domain;
X     char	*name, *addrname;
{
X  struct sockaddr	*laddr;
X  int	addrlen;
X  int	countdown;
X  int	rval;
X  
X  if (domain==AF_INET)
X    {
X      static struct sockaddr_in	srv;
X      static int	initted=0;
X
X      laddr = (struct sockaddr*)&srv;
X      addrlen = sizeof(srv);
X
X      if (!initted) {
X	srv.sin_family = AF_INET;
X
X	if (addrname) {
X	    int	count;
X	    struct in_addr **addresses;
X	    addresses = convert_hostname(addrname, &count);
X	    if (addresses == 0) {
X		fprintf(stderr, "%s: Unable to convert %s to an internet address\n", programname);
X		errno=0;
X		return 0;
X	    }
X	    srv.sin_addr = *(addresses[0]);
X	} else {
X	    srv.sin_addr.s_addr = INADDR_ANY;
X	}
X	
X	srv.sin_port = name_to_inet_port(name);
X      
X	if (srv.sin_port==0)
X	  {
X	    fprintf(stderr, "%s: port %s unknown\n", programname, name);
X	    errno = 0;
X	    return 0;
X	  }
X      }
X      initted = 1;		/* bindlocal is only called once in
X				   each netpipes program */
X    }
X  else
X    {
X      static struct sockaddr_un	srv;
X      laddr = (struct sockaddr*)&srv;
X      addrlen = sizeof(srv);
X      
X      srv.sun_family = AF_UNIX;
X      strcpy(srv.sun_path, name);
X    }
X  
X  countdown= (domain==AF_UNIX)?1:10;
X  do {
X    rval = bind(fd, laddr, addrlen);
X    if (rval)
X      if (errno==EADDRINUSE && --countdown>0)
X	{
X	  fprintf(stderr,"%s: Address %s in use, sleeping 10.\n",
X		  programname, name);
X	  sleep (10);
X	  fprintf(stderr,"%s: Trying again . . .\n", programname);
X	}
X      else
X	return 0;
X  } while (rval);
X
X  return 1;
}
SHAR_EOF
chmod 0644 common.c ||
echo 'restore of common.c failed'
Wc_c="`wc -c < 'common.c'`"
test 5348 -eq "$Wc_c" ||
	echo 'common.c: original size 5348, current size' "$Wc_c"
fi
# ============= common.h ==============
if test -f 'common.h' -a X"$1" != X"-c"; then
	echo 'x - skipping common.h (File already exists)'
else
echo 'x - extracting common.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'common.h' &&
/*
X
X    $id$, part of
X    faucet and hose: network pipe utilities
X    Copyright (C) 1992 Robert Forsman
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X    */
X
#ifndef common_h_
#define common_h_
X
/* set from argv[0] by the main() routine */
extern char *programname;
X
/* list of file descriptors to dup from the socket */
extern int	*fds;
extern int	nfds;
X
/* the mode to use when shutting down the socket
X	<0: don't do any shutdown
X	0 : shut down recieves (write-only)
X	>0: shut down sends (read-only)
X  */
X
extern int	how_shutdown;
X
/* add a file descriptor to the list */
void add_fd(/*int fd*/);
X
/* do the dup from the argument socket to the list of file descriptors,
X   perform the requested shutdown... */
void dup_n(/*int socket*/);
X
/**********************************************************************/
X
int name_to_inet_port(/* char* */);
X
/**********************************************************************/
X
struct in_addr ** /* addr_array */
convert_hostname(/* char *, int * */);
X
/**********************************************************************/
X
int
bindlocal(/* int, char *, char*, int */);
X
#endif // common_h_
SHAR_EOF
chmod 0644 common.h ||
echo 'restore of common.h failed'
Wc_c="`wc -c < 'common.h'`"
test 1802 -eq "$Wc_c" ||
	echo 'common.h: original size 1802, current size' "$Wc_c"
fi
# ============= version.c ==============
if test -f 'version.c' -a X"$1" != X"-c"; then
	echo 'x - skipping version.c (File already exists)'
else
echo 'x - extracting version.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'version.c' &&
#include <stdio.h>
X
void emit_version(progname, beginyear)
X    char *progname;
X    int beginyear;
{
X    int	thisyear=1995;
X    fprintf(stderr, "%s version 3, ", progname);
X    if (beginyear != thisyear) {
X	fprintf(stderr, "Copyright (C) %d-%d Robert Forsman\n", beginyear, thisyear%100);
X    } else {
X	fprintf(stderr, "Copyright (C) %d Robert Forsman\n", thisyear);
X    }
X    fprintf(stderr, "\
%s comes with ABSOLUTELY NO WARRANTY;\n\
This is free software, and you are welcome to redistribute it\n\
under the GNU General Public License as published by the Free\n\
Software Foundation; either version 2 of the License, or\n\
(at your option) any later version.\n", progname);
}
SHAR_EOF
chmod 0644 version.c ||
echo 'restore of version.c failed'
Wc_c="`wc -c < 'version.c'`"
test 679 -eq "$Wc_c" ||
	echo 'version.c: original size 679, current size' "$Wc_c"
fi
# ============= faucet.1 ==============
if test -f 'faucet.1' -a X"$1" != X"-c"; then
	echo 'x - skipping faucet.1 (File already exists)'
else
echo 'x - extracting faucet.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'faucet.1' &&
.\"" faucet.1 Copyright 1992-95 by Robert Forsman
.TH FAUCET 1 "October 24 1995"
.SH NAME
faucet \- a fixture for a BSD network pipe
.SH SYNOPSIS
\fBfaucet\fP \fIport\fP
(\fB\-in\fP|\fB\-out\fP|\fB\-err\fP|\fB\-fd\fP\fIn\fP)+
[\fB\-once\fP]
[\fB\-verbose\fP]
[\fB\-quiet\fP]
[\fB\-unix\fP]
[\fB\-foreignhost\fP \fIaddr\fP]
[\fB\-foreignport\fP \fIport\fP]
[\fB\-localhost\fP \fIaddr\fP]
[\fB\-daemon\fP]
[\fB\-shutdown\fP (r|w) ]
[\fB\-serial\fP]
\fIcommand\fP \fIargs\fP
X
.SH DESCRIPTION
.LP
.B faucet
attempts to provide the functionality of pipes over the network.
It behaves as the server end of a server\-client connection.
When used with
.B hose(1)
it can function as a replacement for
.RS
.nf
tar \-cf \- . | rsh other "cd destdir; tar \-xf \-"
.fi
.RE
.B faucet
and
.B hose
are especially useful when you don't have easy access to the
destination machine.
X
.B faucet
creates a BSD socket, binds it to the
.I port
specified on the command line, and listens for connections.
X
Every time
.B faucet
gets a connection it exec(2)s \fIcommand\fP and its \fIargs\fP with
stdin, stdout, stderr, and/or arbitrary file descriptors redirected
according to the
.B \-in \-out \-err \-fd\fIn\fB
flags.  \fBfaucet\fP also automagically shuts down the unused half of
the connection if only \fB-in\fP is specified or if only \fB-out\fP
and/or \fB-err\fP are specified.  See the \fB-shutdown\fP option for
more information.
X
If the
.B \-once
flag is specified,
.B faucet
will exec(2) the
.I command
instead of fork(2)ing and exec(2)ing.  
.B \-once
means that the network pipe
is only good for one shot.
X
The
.B \-verbose
flag specifies that
.B faucet
should print information about connecting hosts.  This information
includes the numeric host address, host names, and foreign port numbers.
The
.B \-quiet
flag specifies that
.B faucet
should NOT print such info.
.B \-quiet
is the default.
X
The
.B \-unix
flag specifies that the
.I port
is not an internet port number or service name, but instead it is a
filename for a UNIX domain socket.
X
The
.B \-foreignhost
option specifies that faucet should reject all connections that do not
come from the
.I host
machine.  Similarly
.B \-foreignport
specifies that faucet should reject all connections that are not bound
on their local machine to the
.I port
argument.  The above two options allow a crude form of authentication.
Note that on most systems only root can bind a socket to a port number
below 1024.
X
.B Please
do not be fooled into thinking this makes faucet secure.  There are
ways to spoof IP numbers that have been known for years (but only
publicized recently).  I do think that this method is safe from DNS
spoofs, but you probably should have
.B nospoof on
in /etc/host.conf anyway.
X
.B \-localhost
specifies that the listening socket should be bound to a specific
internet address on this host.  This is only useful on hosts with
several internet numbers.
X
.B \-daemon
specifies that the faucet should disassociate from the controlling
terminal once it has started listening on the socket.  This is done
using the standard ``close all file descriptors, ioctl TIOCNOTTY,
fork() and parent exit'' sequence.  
X
.B \-shutdown
is used to turn the (normally) bi-directional socket into a
uni-directional one
X  If the `r' is present, then \fBfaucet\fP will close half the
connection to make it a read-only socket.  If we try to write, it will
fail.  If the remote connection tries to read, it will percieve the
socket as closed.
X  If instead the `w' is present, then \fBfaucet\fP will close the
other half of the connection to make it a write-only socket.  If we
try to read, we will percieve the socket as closed.  If the remote
connection tries to write, it will fail.
X  The default behavior is to leave both halves open, however the
shutdown of half of the connection is automagically done by certain
combinations of the \fB\-in\fP, \fB\-out\fP, and \fB\-err\fP flags.
To suppress their automagic behavior you can use (respectively) \-fd0,
\-fd1, and \-fd2.
X
.B \-serial
causes faucet to wait for one child to finish before accepting any
more connections.  Serialization is a very crude form of
critical-section management.
X
.SH "EXAMPLES"
.LP
This creates a TCP\-IP socket on the local machine bound to port 3000.
.RS
.nf
example$ faucet 3000 \-out \-verbose tar \-cf \- .
.fi
.RE
Every time some process (from any machine) attempts to connect to
port 3000 on this machine the
.B faucet
program will fork(2) a process and the child will exec(2) a
.RS
.nf
tar \-cf \- .
.fi
.RE
The
.B \-out
option means that the output of the child process will have been
redirected into the new socket retrieved by the accept(2) call.
.B \-verbose
means that faucet will print information about each new connection.
X
.LP
This creates a UNIX domain socket in the current directory
.RS
.nf
example$ faucet u\-socket \-out \-err \-once \-unix csh \-c \\
X	"dd if=angio.pgm | funky.perl.script" 
.fi
.RE
The
.B \-out \-err
option means that stdout and stderr will be redirected in the child
process.  The
.B \-once
option means that the faucet will not fork(2), but exec(2) the process
so that only the first process can connect to the u\-socket before the
faucet becomes unavailable.
X
.SH "SEE ALSO"
.BR netpipes (1),
.BR hose (1),
.BR sockdown (1),
.BR getpeername (1),
.BR socket (2),
.BR bind (2),
.BR listen (2),
.BR accept (2),
.BR shutdown (2),
.BR services (5),
.BR gethostbyaddr (3)
X
.SH "NOTES"
.LP
Doubtless there are bugs in this program, especially in the unix domain
socket portions.  I welcome problem reports and would like to make
these programs as "clean" (no leftover files, sockets) as possible.
X
X  Release 2.3 added support for multi-homed hosts: hosts with multiple
internet numbers (such as gateways).  Before this faucet assumed that
the first internet number that gethostbyname returned was the only
one.
.B \-foreignport
authentication was weakened by this inadequacy so I beefed up the
algorithms.  
.B \-foreignport
will accept a connection from any of the
internet numbers associated with the host name.  
X
.SH "CREDITS"
.LP
Thanks to Steve Clift <clift@ml.csiro.au> for SGI (SysV) patches.
.LP
Many people complained about the old way of specifying the command.
Thanks to whoever gave me the alternative which is now implemented.
It is much better.
.LP
Randy Fischer <fischer@ucet.ufl.edu> finally prodded me into fixing
the old lame non-handling of multi-homed host.
X
.SH "COPYRIGHT"
Copyright (C) 1992,1993,1994,1995 Robert Forsman
X
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
X
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
X
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
.SH "AUTHOR"
X Robert Forsman
X thoth@purplefrog.com
X Purple Frog Software
X http://www.purplefrog.com/~thoth/
SHAR_EOF
chmod 0644 faucet.1 ||
echo 'restore of faucet.1 failed'
Wc_c="`wc -c < 'faucet.1'`"
test 7264 -eq "$Wc_c" ||
	echo 'faucet.1: original size 7264, current size' "$Wc_c"
fi
# ============= faucet.c ==============
if test -f 'faucet.c' -a X"$1" != X"-c"; then
	echo 'x - skipping faucet.c (File already exists)'
else
echo 'x - extracting faucet.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'faucet.c' &&
/*
X
X    faucet.c, part of
X    faucet and hose: network pipe utilities
X    Copyright (C) 1992-95 Robert Forsman
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X    */
X
static char info[] = "faucet: a network utility for sockets\nWritten 1992,1993 by Robert Forsman <thoth@cis.ufl.edu>\n";
#include	<stdio.h>
#include	<errno.h>
extern int errno;		/* I hate the errno header file */
#include	<signal.h>
#ifdef hpux
#include	<sgtty.h>
#endif
#include	<sys/wait.h>
#include	<sys/param.h>
#include	<sys/file.h>
#ifdef USE_IOCTL
#include	<sys/ioctl.h>
#ifdef linux
#include	<linux/termios.h>
#else
/* find the FIOCLEX ioctl */
#include	<sys/filio.h>
#endif
#else
#include	<sys/types.h>
#include	<unistd.h>
#include	<fcntl.h>
#endif
#include	<sys/socket.h>
#include	<sys/un.h>
#include	<netinet/in.h>
#include	<netdb.h>
/* for getrlimit with -daemon option */
#include <sys/time.h>
#include <sys/resource.h>
#include "common.h"
X
int	mastersocket;
#define	DOONCE		(1<<0)
#define	DOVERBOSE	(1<<1)
#define	DOUNIX		(1<<2)
#define DODAEMON	(1<<3)
X
int	doflags=0;
int	running=1;
X
struct in_addr ** /* addr_array */ convert_hostname();
X
char	*localhost=NULL;
char	*foreignhost=NULL,*foreignport=NULL;
int	foreignPORT;
int	foreignCOUNT=0;
struct in_addr	**foreignHOST;
int	serialize=0;
X
extern int errno;
extern char *sys_errlist[];
X
X
int name_to_inet_port();
X
void nice_shutdown()
/* This procedure gets called when we are killed with one of the reasonable
X   signals (TERM, HUP, that kind of thing).  The main while loop then
X   terminates and we get a chance to clean up. */
{
X  running = 0;
}
X
X
/* print an internet host address prettily */
printhost(addr)
X     struct in_addr	*addr;
{
X  struct hostent	*h;
X  char	*s,**p;
X  int	i;
X
X  h = gethostbyaddr((char*)addr, sizeof(*addr),AF_INET);
X  s = (h==NULL) ? NULL : h->h_name;
X
X  printf("%d", ((u_char*)addr)[0]);
X  for (i=1; i<sizeof(*addr); i++)
X    printf(".%d",((u_char*)addr)[i]);
X
X  printf("(%s",s?s:"name unknown");
X  if (s)
X    for (p=h->h_aliases; *p; p++)
X      printf(",%s",*p);
X  printf(")");
}
X
int setup_socket(name)
char *name;
/* This procedure creates a socket and handles retries on the inet domain.
X   Sockets seem to "stick" on my system (SunOS [43].x) */
{
X  int	sock;
X
X  sock = socket((doflags&DOUNIX)?AF_UNIX:AF_INET, SOCK_STREAM, 0);
X  /* I need a real value for the protocol eventually.  IPPROTO_TCP sounds
X     like a good value, but what about AF_UNIX sockets?  It seems to have
X     worked so far... */
X
X  if (sock <0) {
X      perror("opening stream socket");
X      exit(1);
X    }
X
X  if (!bindlocal(sock, name, localhost, (doflags&DOUNIX)?AF_UNIX:AF_INET)) {
X      fprintf(stderr,"%s: error binding stream socket %s (%s)",
X	      programname,name,sys_errlist[errno]);
X      exit(1);
X    }
X
X  /* We used to ask for NOFILE (max number of open files) for the size
X     of the connect queue.  Linux didn't like it (NOFILE=256) so we
X     hardcoded a smaller value. */
X  listen(sock,8);
X
X  return(sock);
}
X
X
void waitonchild()
X
{
X  int	status;
X
X  int	childpid;
X  
X  childpid = wait(&status);
X
#ifdef SYSV
X  signal(SIGCHLD,waitonchild);
#endif
}
X
X
int
authorize_address(sin)
X     struct sockaddr	*sin;
{
X  if (doflags&DOUNIX) {
X    struct sockaddr_un 	*srv = (struct sockaddr_un*)sin;
X    
X    if (foreignport != NULL && 0!=strcmp(foreignport, srv->sun_path)) {
X      if (doflags&DOVERBOSE) {
X	  printf("%s: refusing connection from port %s\n",
X		  programname, srv->sun_path);
X      }
X      return 0;
X    }
X  } else {
X    struct sockaddr_in	*srv = (struct sockaddr_in*)sin;
X    int	i;
X
X    if (foreignhost) {
X	for (i=0; i<foreignCOUNT; i++) {
X	    if (0==memcmp(&srv->sin_addr,
X			  foreignHOST[i], sizeof(struct in_addr)))
X		break;
X	}
X	if (i>=foreignCOUNT) {
X	    if (doflags&DOVERBOSE) {
X		printf("refusing connection from host ");
X		printhost(&srv->sin_addr);
X		printf(".\n");
X	    }
X	    return 0;
X	}
X    }
X    
X    if (foreignport!=NULL && foreignPORT != srv->sin_port) {
X      if (doflags&DOVERBOSE) {
X	printf("refusing connection from port %d.\n",
X	       ntohs(srv->sin_port));
X      }
X      return 0;
X    }
X  }
X  
X  return 1;
}
X
X
main (argc,argv)
int argc;
char ** argv;
X
{
X  int	rval, i;
X  union {
X    struct sockaddr_in	in;
X    struct sockaddr_un	un;
X  } saddr;
X  struct sockaddr_in	*sinp = &saddr.in;
X  struct sockaddr_un	*sunp = &saddr.un;
X  char	**cmd;
X  
X  programname = argv[0];
X  
X  if (argc<3) {
X    fprintf(stderr,"Usage : %s <port> (-in|-out|-err|-fdN)+ [-once] [-verb(|ose)] [-quiet] [-unix] [-foreignport <port>] [-foreignhost <inet-addr>] [-localhost <inet-addr>] [-daemon] [-shutdown (r|w)] [-serial] command args\n", programname);
X    exit(1);
X  }
X  
X  /* parse trailing args */
X  for (i=2; i<argc; i++) {
X    char	*arg;
X    if (argv[i][0]!='-')
X      break;
X    arg = argv[i]+1;
X    if (strcmp(arg,"in")==0) {
X	add_fd(0);
X	if (how_shutdown == 0)	/* make sure we can read from the socket */
X	    how_shutdown = -1;
X	else if (how_shutdown==-2)
X	    how_shutdown = 1;
X    } else if (strcmp(arg,"out")==0) {
X	add_fd(1);
X	if (how_shutdown == 1)	/* make sure we can write to the socket */
X	    how_shutdown = -1;
X	else if (how_shutdown==-2)
X	    how_shutdown = 0;
X    } else if (strcmp(arg,"err")==0) {
X	add_fd(2);
X	if (how_shutdown == 1)	/* make sure we can write to the socket */
X	    how_shutdown = -1;
X	else if (how_shutdown==-2)
X	    how_shutdown = 0;
X    } else if (strncmp(arg,"fd",2)==0) {
X	int	fd = atoi(arg+2);
X	add_fd(fd);
X	how_shutdown = -1;
X    } else if (strcmp(arg,"once")==0)
X      doflags |= DOONCE;
X    else if (strcmp(arg,"verbose")==0 ||
X	     strcmp(arg,"verb")==0)
X      doflags |= DOVERBOSE;
X    else if (strcmp(arg,"quiet")==0)
X      doflags &= ~DOVERBOSE;
X    else if (strcmp(arg,"unix")==0)
X      doflags |= DOUNIX;
X    else if (strcmp(arg,"foreignport")==0) {
X      if (i+1<argc)
X	foreignport=argv[++i];
X      else
X	fprintf(stderr,"%s: foreignport requires port name or number.\n",
X		programname);
X    } else if (strcmp(arg,"foreignhost")==0) {
X      if (i+1<argc)
X	foreignhost=argv[++i];
X      else
X	fprintf(stderr,"%s: foreignhost requires host name or number.\n",
X		programname);
X    } else if (strcmp(arg,"localhost")==0) {
X      if (i+1<argc)
X	localhost=argv[++i];
X      else {
X	  fprintf(stderr,"%s: localhost requires host name or number.\n",
X		  programname);
X	  exit(1);
X      }
X    } else if (strcmp(arg,"daemon")==0) {
X      doflags |= DODAEMON;
X    } else if (strcmp(arg,"shutdown")==0) {
X	int	err=1;
X	if (i+1<argc) {
X	    arg = argv[++i];
X	    err=0;
X	    if (0==strcmp(arg, "r")) {
X		how_shutdown = 1;
X	    } else if (0==strcmp(arg, "w")) {
X		how_shutdown = 0;
X	    } else {
X		err = 1;
X	    }
X	}
X	if (err) {
X	    fprintf(stderr,"%s: shutdown requires \"r\" or \"w\" string.\n",
X		    programname);
X	    exit(1);
X	}
X    } else if (strcmp(arg,"serial")==0) {
X	serialize=1;
X    } else {
X	fprintf(stderr,"%s: Bogus extra command line flag \"%s\".\n",
X		programname,argv[i]);
X	exit(1);
X    }
X  }
X  cmd = argv+i;
X
X  if (doflags&DOVERBOSE) {
X      emit_version("faucet", 1992);
X  }
X
X  if ( nfds==0 ) {
X    fprintf(stderr,"%s: Need at least one {-in|-out|-err|-fd#}.\n",programname);
X    exit(1);
X  }
X  
X  if ( (doflags&DOUNIX) && foreignhost!=NULL ) {
X    fprintf(stderr, "%s: foreignhost parameter makes no sense with UNIX domain sockets, ignoring.\n", programname);
X    foreignhost = NULL;
X  }
X  
X  if (!serialize)
X      signal(SIGCHLD,waitonchild);
X  
X  mastersocket = setup_socket(argv[1]);
X  
X  signal(SIGHUP, nice_shutdown);
X  signal(SIGINT, nice_shutdown);
X  signal(SIGPIPE, nice_shutdown);
X  signal(SIGALRM, nice_shutdown);
X  signal(SIGTERM, nice_shutdown);
X  
X  if (foreignhost != NULL &&
X      0==(foreignHOST = convert_hostname(foreignhost, &foreignCOUNT))) {
X    fprintf(stderr, "%s: could not translate %s to a host address\n",
X	    programname, foreignhost);
X    exit(1);
X  }
X  
X  if (foreignport!=NULL && !(doflags&DOUNIX) &&
X      0 == (foreignPORT = name_to_inet_port(foreignport)) ) {
X    fprintf(stderr,"%s: port %s unknown.\n",programname,foreignport);
X    exit(1);
X  }
X
X  if (doflags&DODAEMON) {
X      struct rlimit	rl;
X      int	count, rval;
X      if (doflags&DOVERBOSE) {
X	  printf("%s: detaching from terminal, bye\n");
X      }
X      /* figure out how many file descriptors are possible */
X      rval = getrlimit(RLIMIT_NOFILE, &rl);
X      if (rval!=0 || rl.rlim_cur == RLIM_INFINITY) {
X	  count=64;		/* reasonable guess */
X      } else {
X	  count = rl.rlim_cur;
X      }
X      /* close them all (except the listening socket) */
X      for (i = 0; i<count; i++) {
X	  if (i != mastersocket)
X	      close(i);
X      }
X      rval = open("/dev/tty", O_RDWR);
X      if (rval>=0) {
X	  ioctl(rval, TIOCNOTTY, &rval);
X	  close(rval);
X	  if (fork()>0)
X	      exit(0);
X      }
X  }
X
X
X  while (running) {
X
X    {
X      int	length;
X    
X      length = sizeof(saddr);
X    
X      rval = accept(mastersocket,(struct sockaddr*)&saddr,&length);
X    }
X    
X    if (rval<0) {
X      if (errno==EWOULDBLOCK) {
X	  fprintf(stderr, "%s: No more connections to talk to.\n",programname);
X      } else if (errno!=EINTR) {
X	fprintf(stderr,"%s: error in accept (%s).",
X		programname,sys_errlist[errno]);
X	exit(1);
X      }
X      continue;
X    }
X    
X    if (!authorize_address(&saddr)) {
X      close(rval);
X      continue;
X    }
X    
X    if ( doflags&DOVERBOSE ) {
X      printf("%s: Got connection from ",programname);
X      if ( doflags&DOUNIX ) {
X	printf("%s\n", sunp->sun_path);
X      } else {
X	printhost(&sinp->sin_addr);
X	printf(" port %d\n",ntohs(sinp->sin_port));
X      }
X    }
X    
X    fflush(stdout);
X    
X    if ( doflags&DOONCE || fork()==0 ) {
X      /* child process: frob descriptors and exec */
X      char	*s;
X      
X      if ( (doflags&(DOONCE|DOUNIX)) == (DOONCE|DOUNIX) )
X	unlink(argv[1]);
X      /* We don't want the unix domain socket anymore */
X
X      /* put stderr somewhere safe temporarily */
X      dup2(fileno(stderr),mastersocket);/*the old server socket is now closed*/
X
X      /* but we don't want it to hang around after we exec... */
#ifdef USE_IOCTL
X      ioctl(mastersocket,FIOCLEX,NULL);
#else
X      fcntl(mastersocket,F_SETFD,FD_CLOEXEC);
#endif
X
X      /* We don't need old stderr hanging around after an exec.
X	 The mastersocket has been closed by the dup2 */
X      
X      dup_n(rval); /* dup the socket onto all the chosen file descriptors */
X      
X      close(rval); /* rval has been properly duplicated */
X
X      execvp(cmd[0], cmd);
X      s ="exec failed\n";
X      write(mastersocket,s,strlen(s));
X      exit(0);
X    } else {
X      /* parent: close socket.
X	 Signal will arrive upon death of child. */
X      close(rval);
X      if (serialize) {
X	  int	status;
X	  pid_t	pid;
X	  pid = wait(&status);
X	  /* child has exited */
X	  if (pid == -1) {
X	      fprintf(stderr, "%s: error serializing (waiting on child) ",
X		      programname);
X	      perror("");
X	  }
X      }
X    }
X  }
X  
X  /* clean up the socket when we're done */
X  if (doflags&DOUNIX)
X    unlink(argv[1]);
X  close(mastersocket);
X  
}
SHAR_EOF
chmod 0644 faucet.c ||
echo 'restore of faucet.c failed'
Wc_c="`wc -c < 'faucet.c'`"
test 11590 -eq "$Wc_c" ||
	echo 'faucet.c: original size 11590, current size' "$Wc_c"
fi
# ============= hose.1 ==============
if test -f 'hose.1' -a X"$1" != X"-c"; then
	echo 'x - skipping hose.1 (File already exists)'
else
echo 'x - extracting hose.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'hose.1' &&
.\" $Id: hose.1,v 1.7 1995/10/24 18:28:08 thoth Exp $
.\" Copyright 1992-1995 by Robert Forsman
.\""
.TH HOSE 1 "October 24, 1995"
.SH NAME
hose \- the client end of a BSD network pipe
.SH SYNOPSIS
\fBhose\fP \fIhostname\fP \fIport\fP
(\fB\-in\fP|\fB\-out\fP|\fB\-err\fP|\fB\-fd\fP\fIn\fP|\fB\-slave\fP)
[\fB\-unix\fP]
[\fB\-localport\fP \fIport\fP]
[\fB\-localhost\fP \fIaddr\fP]
[\fB\-retry\fP \fIn\fP]
[\fB\-delay\fP \fIn\fP]
[\fB\-shutdown\fP [r|w][a] ]
\fIcommand\fP \fIargs\fP
X
.SH DESCRIPTION
.LP
.B hose
attempts to provide the functionality of pipes over the network.
It behaves as the client end of a server\-client connection.
When used with
.B faucet(1)
it can function as a replacement for
.RS
.nf
tar \-cf \- . | rsh other "cd destdir; tar \-xf \-"
.fi
.RE
.B faucet
and
.B hose
are especially useful when you don't have easy access to the
destination machine.
X
.LP
.B hose
creates a BSD socket and, if the
.B \-localport
option is used, binds it to the port number (or service name)
specified immediately afterwards.  If
.B \-localhost
is also specified then its argument is a local address to bind to. (
.B -localhost
is only useful on machines with multiple IP addresses.)
X
.B hose
then tries to connect to the foreign machine
.I hostname
with foreign port
.I port.
X
If successful
.B hose
redirects the socket to stdin, stdout, stderr, and/or arbitrary file
descriptors according to the
.B \-in \-out \-err \-fd\fIn\fB
flags.  \fBhose\fP also automagically shuts down the unused half of
the connection if only \fB-in\fP is specified or if only \fB-out\fP
and/or \fB-err\fP are specified.  See the \fB-shutdown\fP option for
more information.
X
.B hose
then exec(2)s a \fIcommand\fP with \fIargs\fP.
X
However, the \fB\-slave\fP flag turns \fBhose\fP into a primitive sort
of telnet.  The \fIcommand\fP is ignored.  Instead, \fBhose\fP goes
into a loop where it copies bytes from stdin to the socket, and bytes
from the socket to stdout.  This is actually more useful than telnet
because telnet tries to perform interpretation on the byte stream and
generally gets in your way.  \fBhose\fP just passes bytes without
mucking with them.
X
The
.B \-unix
flag specifies that the
.I port
is not an internet port number or service name, but instead it is a
filename for a UNIX domain socket.  This option may be simulated by
using 
.B \-unix\-
as the host name to connect to, or by renaming the
.B hose
program to \fBuhose\fP.
X
.B \-retry
.I n
allows the user to specify that
.b hose
should retry the connect(2) call for
.I n
times (or forever if
.I n
is negative).
.B \-delay
.I n
specifies how many seconds to delay between tries.
X
.B \-shutdown
is used to control two behaviors.  The first set is controlled by the
`r' and `w' flags.
X  If the `r' is present, then \fBhose\fP will close half the
connection to make it a read-only socket.  If the child tries to
write, it will fail.  If the remote connection tries to read, it will
percieve the socket as closed.
X  If instead the `w' is present, then \fBhose\fP will close the other
half of the connection to make it a write-only socket.  If the child
tries to read, it will percieve the socket as closed.  If the remote
connection tries to write, it will fail.
X  The default behavior is to leave both halves open, however the
shutdown of half of the connection is automagically done by certain
combinations of the \fB\-in\fP, \fB\-out\fP, and \fB\-err\fP flags.
To suppress their automagic behavior you can use (respectively) \-fd0,
\-fd1, and \-fd2.
X
X The other behavior is controlled by the `a' flag.  If the `a' flag is
present then \fBhose\fP will fork(2) before execcing the
.I command
and when the child exits it will perform a shutdown(2) with how=2.
This closes both halves of the connection.  This option is not
necessary for most applications since the closing of the file
descriptors is detected by the remote process, but some less
sophisticated network devices (such as printers) require a shutdown(2)
for proper operation.
X  To make things perfectly clear, the list of acceptable arguments to
the \fB\-shutdown\fP option are `r', `w', `ra', `wa', `a'.
X
.SH "EXAMPLES"
.LP
This will connect to port 3000 on the machine reef and connect the socket
to the stdin of a tar command.
.RS
.nf
example$ hose reef 3000 \-in tar \-xf \- .
.fi
.RE
The command actually exec(2)ed by the
.B hose
program is
.RS
.nf
tar \-xf \- .
.fi
.RE
The
.B \-in
option means that the input of the child process will have been
redirected into the socket connected to reef.
X
.LP
This connects to a UNIX domain socket in the current directory
.RS
.nf
example$ hose \-unix\- u\-socket \-in csh \-c \\
X	"unfunky.perl.script | dd of=sample.pgm"
.fi
.RE
The socket provides input to the csh command.
X
.SH "SEE ALSO"
.BR netpipes (1),
.BR faucet (1),
.BR sockdown (1),
.BR getpeername (1),
.BR socket (2),
.BR bind (2),
.BR connect (2),
.BR shutdown (2),
.BR services (5),
.BR gethostbyaddr (3)
X
.SH "NOTES"
.LP
Doubtless there are bugs in this program, especially in the unix domain
socket portions.  I welcome problem reports and would like to make
these programs as "clean" (no leftover files, sockets) as possible.
X
X  Release 2.3 added support for multi-homed hosts: hosts with multiple
internet numbers (such as gateways).  Before this faucet assumed that
the first internet number that gethostbyname returned was the only
one.
.B -foreignport
authentication was weakened by this inadequacy so I beefed up the
algorithms.  
.B -foreignport
X will accept a connection from any of the
internet numbers associated with the host name.  
X
.SH "CREDITS"
.LP
Thanks to Steve Clift <clift@ml.csiro.au> for SGI (SysV) patches.
.LP
Many people complained about the old way of specifying the command.
Thanks to whoever gave me the alternative which is now implemented.
It is much better.
.LP
Thanks to Sten Drescher <smd@hrt213.brooks.af.mil> for the -retry and
-delay patches and giving me the idea for the -shutdown option.
Evidently some printer doesn't appreciate the socket being close(2)d.
.LP
Randy Fischer <fischer@ucet.ufl.edu> finally prodded me into fixing
the old lame non-handling of multi-homed host.
X
X
.SH "COPYRIGHT"
Copyright (C) 1992,1993,1994,1995 Robert Forsman
X
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
X
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
X
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
.SH "AUTHOR"
X Robert Forsman
X thoth@cis.ufl.edu
X Purple Frog Software
X http://www.purplefrog.com/~thoth/
SHAR_EOF
chmod 0444 hose.1 ||
echo 'restore of hose.1 failed'
Wc_c="`wc -c < 'hose.1'`"
test 6980 -eq "$Wc_c" ||
	echo 'hose.1: original size 6980, current size' "$Wc_c"
fi
# ============= hose.c ==============
if test -f 'hose.c' -a X"$1" != X"-c"; then
	echo 'x - skipping hose.c (File already exists)'
else
echo 'x - extracting hose.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'hose.c' &&
/*
X
X    $Id: hose.c,v 1.10 1995/10/24 19:16:07 thoth Exp thoth $, part of
X    faucet and hose: network pipe utilities
X    Copyright (C) 1992-95 Robert Forsman
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X    */
X
static char info[] = "hose: a network utility for sockets\nWritten 1992,1993 by Robert Forsman <thoth@cis.ufl.edu>\n";
#include	<stdio.h>
#ifdef hpux
#include	<sgtty.h>
#endif
#include	<signal.h>
#include	<sys/errno.h>
#include	<sys/param.h>
#include	<sys/file.h>
#ifdef USE_IOCTL
#include	<sys/ioctl.h>
#ifdef linux
#include	<linux/termios.h>
#else
/* find the FIOCLEX ioctl */
#include	<sys/filio.h>
#endif
#else
#include	<fcntl.h>
#endif
#include	<unistd.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<sys/un.h>
#include	<netinet/in.h>
#include	<sys/time.h>
#include	<netdb.h>
#include "common.h"
X
#define	DOUNIX		(1<<0)
#define	DOVERBOSE	(1<<1)
#define	DOJAM		(1<<2)
#define	DOSLAVE		(1<<3)
X
struct in_addr ** /* addr_array */ convert_hostname();
long	doflags=0;
X
int	retry=0;	       /* how many times to retry after ECONNREFUSED */
unsigned delay=5;		/* how long to wait between each retry */
int	shutdn=0;		/* should we fork, wait and shutdown? */
char	*localport=NULL;	/* local port name */
char	*localaddr=NULL;	/* local internet address */
char	*programname;
extern int	errno;
extern char *sys_errlist[];
X
X
int name_to_inet_port();
X
X
int setup_socket(hostname,portname)
char	*hostname;
char	*portname;
X
{
X  int	sock;
X  struct in_addr ** addresses=0;
X  struct sockaddr_un	unix_addr;
X  struct sockaddr_in	inet_addr;
X  int	num_addresses;
X  int length;
X  int tries;
X  int cstat;
X
X  if (doflags&DOUNIX) {
X      unix_addr.sun_family = AF_UNIX;
X      strcpy( unix_addr.sun_path, portname);
X      length = sizeof(struct sockaddr_un);
X      num_addresses = 1;
X  } else {
X      inet_addr.sin_family = AF_INET;
X
X      if (0==(addresses = convert_hostname(hostname, &num_addresses))) {
X	  fprintf(stderr, "%s: could not translate %s to a host address\n",
X		  programname, hostname);
X	  exit(1);
X      }
X
X      inet_addr.sin_port = name_to_inet_port(portname);
X      if (inet_addr.sin_port==0) {
X	  fprintf(stderr,"%s: bogus port number %s\n",programname,portname);
X	  exit(1);
X      }
X
X      length = sizeof(struct sockaddr_in);
X  }
X  
X  for (tries = 0; retry<0 || tries <= retry; tries++) {
X    int	j;
X  
X    for ( j=0; j<num_addresses; j++) {
X
X	sock = socket((doflags&DOUNIX)?AF_UNIX:AF_INET, SOCK_STREAM, 0);
X	if (sock <0) {
X	    perror("opening stream socket");
X	    exit(1);
X	}
X
X	if ((localport) &&
X	    !bindlocal(sock, localport, localaddr,
X		       (doflags&DOUNIX)?AF_UNIX:AF_INET) ) {
X	    fprintf(stderr,"%s: error binding stream socket %s (%s)\n",
X		    programname,localport,sys_errlist[errno]);
X	    exit(1);
X	}
X  
X	if (!(doflags&DOUNIX)) {
X	    inet_addr.sin_addr = *(addresses[j]);
X	}
X
X	if (doflags&DOVERBOSE) {
X	    fputs("attempting to connect to", stdout);
X	    if (doflags&DOUNIX) {
X		printf(" %s\n",
X		       unix_addr.sun_path);
X	    } else {
X		struct in_addr	*tmp = & inet_addr.sin_addr;
X		printf(" %d.%d.%d.%d port %d\n", (tmp->s_addr>>24)&0xff,
X		       (tmp->s_addr>>16)&0xff,
X		       (tmp->s_addr>> 8)&0xff,
X		       (tmp->s_addr>> 0)&0xff, ntohs(inet_addr.sin_port));
X	    }
X	}
X	cstat=connect(sock,
X		      (doflags&DOUNIX) ?
X		      ((struct sockaddr*)&unix_addr) :
X		      ((struct sockaddr*)&inet_addr) ,
X		      length);
X	if (cstat==0)
X	    break;		/* success */
X
X	if (errno==ECONNREFUSED) {
X	    close(sock);
X	    sock = -1;
X	} else {
X	    perror("connecting");
X	    exit(1);
X	}
X    }
X    if (j<num_addresses)
X	break;			/* success */
X
X    if (tries<retry) {
X	/* failed, retry all addresses after a delay */
X	if (doflags&DOVERBOSE) {
X	    printf("sleeping before retry...");
X	    fflush(stdout);
X	}
X	sleep(delay);
X	if (doflags&DOVERBOSE)
X	    printf("\n");
X    }
X  }
X
X  if (sock < 0) {
X    fprintf(stderr, "Retries exhausted, failing connect\n");
X    exit(1);
X  }
X
X  return(sock);
}
X
X
#ifdef NO_MEMMOVE
/* bloody SunOS, it's not ANSI */
void *memmove(dst, src, n)
X    void *dst;
X    void *src;
X    size_t n;
{
X    int	i;
X    /* this memmove is not as functional as the ANSI one, it only works for
X       what we do in copyio */
X    for (i=0; i<n; i++) {
X	((char*)dst)[i] = ((char*)src)[i];
X    }
}
X
#endif
/*
X   copy bytes from stdin to the socket and
X   copy bytes from the socket to stdout.
X   */
void copyio(sock)
X    int	sock;
{
X    fd_set	readfds, writefds;
#define BSIZE	4096
X    char	tosockbuf[BSIZE], fromsockbuf[BSIZE];
X    int		tosocklen, fromsocklen;
X    int		rval;
X    int	exitval = 0;
X
X    tosocklen = fromsocklen = 0;
X    while (tosocklen>=0 || fromsocklen>=0) {
X	/********************/
X	FD_ZERO(&readfds);
X	FD_ZERO(&writefds);
X	if (tosocklen>=0) {
X	    if (tosocklen==0) {
X		FD_SET(0, &readfds);
X	    } else {
X		FD_SET(sock, &writefds);
X	    }
X	}
X	if (fromsocklen>=0) {
X	    if (fromsocklen==0) {
X		FD_SET(sock, &readfds);
X	    } else {
X		FD_SET(1, &writefds);
X	    }
X	}
X	/********************/
X
X	rval=select(sock+1, &readfds, &writefds,
X		    (fd_set*)0, (struct timeval*)0);
X	/********************/
X	if (rval<0) {
X	    if (errno != EINTR) {
X		perror("during copyio() select(2)");
X		exit(1);
X	    }
X	} else if (rval==0) {
X	    break;
X	}
X	/********************/
X	if (FD_ISSET(1, &writefds)) {
X	    rval = write(1, fromsockbuf, fromsocklen);
X	    if (rval<0) {
X		perror("during copyio() write(2)(1)");
X		exitval = 1;
X		fromsocklen = -1;
X		shutdown(sock, 0);
X	    } else {
X		memmove(fromsockbuf, fromsockbuf+rval, fromsocklen-rval);
X		fromsocklen -= rval;
X	    }
X	}
X	if (FD_ISSET(sock, &writefds)) {
X	    rval = write(sock, tosockbuf, tosocklen);
X	    if (rval<0) {
X		perror("during copyio() write(2)(sock)");
X		exitval = 1;
X		tosocklen = -1;
X		shutdown(sock, 1);
X	    } else {
X		memmove(tosockbuf, tosockbuf+rval, tosocklen-rval);
X		tosocklen -= rval;
X	    }
X	}
X	if (FD_ISSET(0, &readfds)) {
X	    tosocklen = read(0, tosockbuf, BSIZE);
X	    if (tosocklen<0) {
X		perror("during copyio() read(2)(0)");
X		exitval = 1;
X		tosocklen = -1;
X	    } else if (tosocklen==0) {
X		tosocklen = -1;
X		shutdown(sock, 1);
X	    }
X	}
X	if (FD_ISSET(sock, &readfds)) {
X	    fromsocklen = read(sock, fromsockbuf, BSIZE);
X	    if (fromsocklen<0) {
X		perror("during copyio() read(2)(0)");
X		exitval = 1;
X		fromsocklen = -1;
X	    } else if (fromsocklen==0) {
X		fromsocklen = -1;
X		shutdown(sock, 0);
X	    }
X	}
X    }
X    exit(exitval);
}
X
void endjam()
{
X  doflags &= ~DOJAM;
}
X
X
main (argc,argv)
X     int argc;
X     char ** argv;
X     
{
X  int	sock,i;
X  int	jampipe[2];
X  char	**cmd;
X  
X  programname=argv[0];
X  
X  if (argc<4) {
X    fprintf(stderr,"Usage : %s <hostname> <port> (-in|-out|-err|-fdN|-slave)+ [-verb(|ose)] [-unix] [-localport <port>] [-localhost <inet-addr>] [-retry n] [-delay n] [-shutdown [r|w][a]] <command>\n",programname);
X    exit(1); 
X  }
X  if (strcmp(argv[1],"-unix-")==0 || strcmp(programname,"uhose")==0 )
X    doflags |= DOUNIX;
X  for (i=3; i<argc; i++) {
X    char	*arg;
X    if (argv[i][0]!='-')
X      break;
X    arg = argv[i]+1;
X    if (strcmp(arg,"in")==0) {
X	add_fd(0);
X	if (how_shutdown == 0)	/* make sure we can read from the socket */
X	    how_shutdown = -1;
X	else if (how_shutdown==-2)
X	    how_shutdown = 1;
X    } else if (strcmp(arg,"out")==0) {
X	add_fd(1);
X	if (how_shutdown == 1)	/* make sure we can write to the socket */
X	    how_shutdown = -1;
X	else if (how_shutdown==-2)
X	    how_shutdown = 0;
X    } else if (strcmp(arg,"err")==0) {
X	add_fd(2);
X	if (how_shutdown == 1)	/* make sure we can write to the socket */
X	    how_shutdown = -1;
X	else if (how_shutdown==-2)
X	    how_shutdown = 0;
X    } else if (strncmp(arg,"fd",2)==0) {
X	int	fd = atoi(arg+2);
X	add_fd(fd);
X	how_shutdown = -1;
X    } else if (strcmp(arg,"slave")==0) {
X	doflags |= DOSLAVE;
X    } else if (strcmp(arg,"unix")==0)
X      doflags |= DOUNIX;
X    else if (strcmp(arg,"verbose")==0 ||
X	     strcmp(arg,"verb")==0)
X      doflags |= DOVERBOSE;
#if 0
X    else if (strcmp(arg,"bourne")==0)
X      doflags |= DOBOURNE;
X    else if (strcmp(arg,"csh")==0)
X      doflags &= ~DOBOURNE;
#endif
X    else if (strcmp(arg,"jam")==0)
X      doflags |= DOJAM;
X    else if (strcmp(arg,"localport")==0) {
X      if (i+1<argc)
X	localport=argv[++i];
X      else
X	fprintf(stderr,
X		"%s: -localport requires port name or number argument.\n",
X		programname);
X    } else if (strcmp(arg,"localhost")==0) {
X      if (i+1<argc)
X	localaddr=argv[++i];
X      else
X	fprintf(stderr,
X		"%s: -localhost requires internet name or number.\n",
X		programname);
X    } else if (strcmp(arg,"retry")==0) {
X      if (i+1<argc)
X        retry=atoi(argv[++i]);
X      else
X	fprintf(stderr,"%s: retry requires count argument.\n",
X		programname);
X    } else if (strcmp(arg,"delay")==0) {
X      if (i+1<argc)
X        delay=atoi(argv[++i]);
X      else
X	fprintf(stderr,"%s: delay requires time argument in seconds.\n",
X		programname);
X    } else if (strcmp(arg,"shutdown")==0) {
X	int	err=1;
X	if (i+1<argc) {
X	    arg = argv[++i];
X	    err=0;
X	    if (0==strcmp(arg, "r")) {
X		how_shutdown = 1;
X	    } else if (0==strcmp(arg, "w")) {
X		how_shutdown = 0;
X	    } else if (0==strcmp(arg, "ra")) {
X		how_shutdown = 1;
X		shutdn = 1;
X	    } else if (0==strcmp(arg, "wa")) {
X		how_shutdown = 0;
X		shutdn = 1;
X	    } else if (0==strcmp(arg, "a")) {
X		shutdn = 1;
X	    } else {
X		err = 1;
X	    }
X	}
X	if (err) {
X	    fprintf(stderr,"%s: shutdown requires \"r\", \"w\" \"ra\", \"wa\", or \"a\" string.\n",
X		    programname);
X	    exit(1);
X	}
X    } else {
X	fprintf(stderr,"%s: Bogus extra command line flag \"%s\".\n",
X		programname,argv[i]);
X	exit(1);
X    }
X  }
X  cmd = argv+i;
X
X  if (doflags&DOVERBOSE) {
X      emit_version("hose", 1992);
X  }
X
X  if ( nfds==0 && !(doflags&DOSLAVE) ) {
X    fprintf(stderr,"%s: Need at least one {in|out|err|fd#|slave}.\n",programname);
X    exit(1);
X  }
X
X  /* this wierd setup is to flood a socket with connections */
X  if (doflags&DOJAM) {
X    signal(SIGCHLD, endjam);
X    if (0>pipe(jampipe)) {
X      perror("opening jampipe");
X      exit(1);
X    }
X  }
X
X  while ( (doflags & DOJAM) && fork() ) {
X    char	ch;
X    close (jampipe[1]);
X    while (1==read(jampipe[0], &ch, 1))
X      ;
X    close (jampipe[0]);
X    jampipe[0] = -1;
X    if (0>pipe(jampipe)) {
X      perror("opening jampipe");
X      exit(1);
X    }
X  }
X
X  if (doflags&DOJAM)
X    close (jampipe[0]);
X
X  sock = setup_socket(argv[1],argv[2]);
X  
X  if (doflags&DOUNIX && localport!=NULL)
X    unlink(localport);
X
X  if (doflags &DOSLAVE) {
X      copyio(sock);
X  }
X
X  /* if we're to shutdown(2) the socket when the subprocess exits we
X     need to fork */
X  i = shutdn ? fork() : 0;
X
X  if (i) {
X    /* we are supposed to shutdown(2) the socket and we are the parent */
X    int	status;
X    int	pid;
X    pid = wait(&status);
X    if (pid != -1 && i!=pid)
X      fprintf(stderr, "Strange, wait returned a child I don't know about.  I'm an unwed father!\n");
X    shutdown(sock, 2);		/* shut the socket down nicely? */
X    close(sock);
X    exit( (status&0xff) ? 1 : ((status>>8)&0xff));
X  } else {
X    int sparefd;
X    char *s;
X    
X    sparefd = dup(fileno(stderr));
#ifdef USE_IOCTL
X    ioctl(sparefd,FIOCLEX,NULL);
#else
X    fcntl(sparefd,F_SETFD,FD_CLOEXEC);
#endif
X    
X    dup_n(sock); /* dup the socket onto all the chosen file descriptors */
X
X    close(sock);
X    
X    if (doflags&DOJAM)
X      close (jampipe[1]);
X
X    execvp(cmd[0], cmd);
X
X    s ="exec failed for ";
X    write(sparefd,s,strlen(s));
X    write(sparefd,cmd[0],strlen(cmd[0]));
X    write(sparefd,"\n",1);
X    exit(1);
X  }
}
SHAR_EOF
chmod 0644 hose.c ||
echo 'restore of hose.c failed'
Wc_c="`wc -c < 'hose.c'`"
test 12117 -eq "$Wc_c" ||
	echo 'hose.c: original size 12117, current size' "$Wc_c"
fi
# ============= sockdown.1 ==============
if test -f 'sockdown.1' -a X"$1" != X"-c"; then
	echo 'x - skipping sockdown.1 (File already exists)'
else
echo 'x - extracting sockdown.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sockdown.1' &&
.\" $Id: sockdown.1,v 1.3 1995/10/24 18:40:05 thoth Exp thoth $ Copyright 1995 by Robert Forsman
.\""
.TH SOCKDOWN 1 "October 24, 1995"
.SH NAME
sockdown - shutdown(2) a socket
.SH SYNOPSIS
\fBsockdown\fP
[\fIfd\fP
[\fIhow\fP] ]
X
.SH DESCRIPTION
.LP
.B sockdown
performs the shutdown(2) system call on one of its file descriptors
specified by \fIfd\fP.  The possible values for \fIhow\fP are
.RS
.nf
.ta +\w'(space)\0'u +\w'convert to write-only file descriptor\0'u
0		convert to write-only file descriptor
writeonly	symbolic for same as above
1		convert to read-only file descriptor
readonly	symbolic for same as above
2		complete shutdown.  no reads or writes allowed in the future
totally		symbolic for same as above
.fi
.RE
X  The default \fIfd\fP is 1 (stdout) and the
default \fIhow\fP is 1.
X
.SH EXAMPLES
X
Imagine you have a machine that can perform a service (in this case
conversion from ASCII to fancy postscript) :
.RS
.nf
server$ faucet 3000 \-in \-out enscript \-2rGhp \-
.fi
.RE
You may then connect to it with a hose.  However, the first example enters deadlock :
.RS
.nf
client$ hose server 3000 \-in \-out \\
X	sh -c " cat blah.txt & cat > blah.ps "
.fi
.RE
The enscript blocks waiting for input from the socket because not all
of the client processes have exited.  While the cat blah.txt is
finished, the cat > blah.ps is not, and will not be finished until the
remote enscript process finishes writing.  The enscript process will
not finish writing until it is finished reading, but that
client->server half of the socket is still open and will not be closed
until all the client processes are done.  The result is deadlock.
X
So, we use sockdown to close half of the pipe
.RS
.nf
client$ hose server 3000 \-in \-out \\
X	sh -c " ( cat blah.txt ; sockdown ) & cat > blah.ps "
.fi
.RE
This way when the cat blah.txt is done, half of the socket is shut
down and the remote enscript process runs out of input, causing it to
flush its output and exit, so eventually the whole mess finishes
cleanly.
X
Note: the & on the hose is necessary to prevent another deadlock.  If
we simply used the ; to serialize the two cat processes it is possible
that the enscript would fill up its write buffer before the first cat
was done causing both processes to block and preventing the second cat
from draining the pipe.
X
.SH ERRORS
.B Socket operation on non-socket
X  The \fIfd\fP you specified does not refer to a socket.  This happens
when you run sockdown by itself (it is unlikely that any of the file
descriptors attached to an interactive shell are actually sockets) or
if you goof up your faucet/hose command and forgot to dup(2) one of
your descriptors.
X
.B Bad file number
X  You gave it a bad file number for \fIfd\fP.  If you have enough
skill to actually generate this error, you probably know what is
wrong.
X
If you encounter any other errors, clue me in.
X
X
.SH "SEE ALSO"
.BR netpipes (1)
.BR faucet (1),
.BR hose (1),
.BR getpeername (1),
.BR socket (2),
.BR shutdown (2),
X
.SH NOTES
.LP
Any normal human would assume a program this simple has to be bug
free, but I am an experienced programmer.
X
X  Just avoid doing anything funky like passing \fBsockdown\fP strings
and it should serve you well.  You should not have to pass it any
arguments unless you are doing something fairly funky.
X
X  Perhaps I should ditch the \fBshutdown -a\fP semantics on hose since
a \fBsockdown 1 2\fP would do the job.
X
.SH "CREDITS"
``Hi Mom! Hi Dad!''
X
.SH "COPYRIGHT"
Copyright (C) 1995 Robert Forsman
X
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
X
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
X
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
.SH "AUTHOR"
X Robert Forsman
X thoth@cis.ufl.edu
X Purple Frog Software
X http://www.purplefrog.com/~thoth/
SHAR_EOF
chmod 0644 sockdown.1 ||
echo 'restore of sockdown.1 failed'
Wc_c="`wc -c < 'sockdown.1'`"
test 4263 -eq "$Wc_c" ||
	echo 'sockdown.1: original size 4263, current size' "$Wc_c"
fi
# ============= sockdown.c ==============
if test -f 'sockdown.c' -a X"$1" != X"-c"; then
	echo 'x - skipping sockdown.c (File already exists)'
else
echo 'x - extracting sockdown.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sockdown.c' &&
/*
X
X    $Id: sockdown.c,v 1.2 1995/10/24 18:40:36 thoth Exp thoth $, part of
X    faucet and hose: network pipe utilities
X    Copyright (C) 1995 Robert Forsman
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X    */
X
static char info[] = "sockdown: a network utility for sockets\nWritten 1995 by Robert Forsman <thoth@cis.ufl.edu>\n";
#include	<stdio.h>
X
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
X
char *programname;
X
int main(argc, argv)
X    int	argc;
X    char **argv;
{
X    int	fd;
X    int	how;
X    int	verbose=0;
X
X    programname=argv[0];
X
X    if (argc>1&&
X	0==strncmp(argv[1], "-verbose", strlen(argv[1]))) {
X	verbose=1;
X	argc--;
X	argv++;
X    }
X    if (argc<2) {
X	fd = 1;
X	how = 1;
X    } else {
X	fd = atoi(argv[1]);
X	if (argc<3) {
X	    how = 1;
X	} else {
X	    if (0==strncmp("readonly", argv[2], strlen(argv[2]))) {
X		how = 1;
X	    } else if (0==strncmp("writeonly", argv[2], strlen(argv[2]))) {
X		how = 0;
X	    } else if (0==strncmp("totally", argv[2], strlen(argv[2]))) {
X		how = 2;
X	    } else {
X		how = atoi(argv[2]);
X	    }
X	}
X    }
X
X    if (verbose) {
X      emit_version("sockdown", 1995);
X      fprintf(stderr,
X	      "%s: Performing shutdown on descriptor %d with mode %d\n",
X	      programname, fd, how);
X    }
X
X    if ( 0==shutdown(fd, how) ) {
X	exit(0);
X    } else {
X	fprintf(stderr, "%s: Error %d during shutdown(%d, %d) of socket.  ",
X		programname, errno, fd, how);
X	perror("");
X	exit(1);
X    }
}
SHAR_EOF
chmod 0644 sockdown.c ||
echo 'restore of sockdown.c failed'
Wc_c="`wc -c < 'sockdown.c'`"
test 2095 -eq "$Wc_c" ||
	echo 'sockdown.c: original size 2095, current size' "$Wc_c"
fi
# ============= getpeername.1 ==============
if test -f 'getpeername.1' -a X"$1" != X"-c"; then
	echo 'x - skipping getpeername.1 (File already exists)'
else
echo 'x - extracting getpeername.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'getpeername.1' &&
.\" $Id: getpeername.1,v 1.1 1995/10/24 18:20:15 thoth Exp $ Copyright 1995 by Robert Forsman
.\""
.TH GETPEERNAME 1 "October 24, 1995"
.SH NAME
getpeername \- get information about this or that end of the socket's connection
.SH SYNOPSIS
\fBgetpeername\fP
[ \fB\-verbose\fP ]
[ \fB\-sock\fP ]
[ \fIfd\fP ]
X
\fBgetsockname\fP
[ \fB\-verbose\fP ]
[ \fB\-peer\fP ]
[ \fIfd\fP ]
.SH DESCRIPTION
X
.B getpeername
performs a getpeername(2) system call on one of its file descriptors
specified by \fIfd\fP and prints out the results.  The default \fIfd\fP
is 0 (stdin).  You may cause
.B getpeername
to behave like
.B getsockname
by providing the \-sock argument.
X
.B getsockname
performs a getsockname(2) system call on one of its file descriptors
specified by \fIfd\fP and prints out the results. The default \fIfd\fP
is 0 (stdin).  You may cause
.B getsockname
to behave like
.B getpeername
by providing the \-peer argument.
X
There is a severe limitation of \fBgetpeername\fP.  If the remote
process has closed the connection, getpeername will fail with a
`Socket is not connected' error.  This will happen with dismaying
frequency when the remote process is not dependent upon the local
process for input and it is only sending small amounts of output
before closing the connection.  Hopefully the practical uses of
getpeername (if there are any) will not exercise this problem.
X
X  You can use
.B getpeername
to find out the address of the opposite end of a socket.  You can use
.B getsockname
to find out the address of the local end of a socket.  They are in
fact the same program with different names.  We will refer to both of
them by the name
.B getpeername
in the following description.
X
.B getpeername
knows how to display peer information about UNIX and Internet sockets.
If you try to use it on another type of socket, it will fail with an
"unknown address family" error.  If you regularly deal with strange
sockets and wish getpeername to work with them, send me email.
X
If the socket is a UNIX domain socket, then getpeername prints the
name of the file (which is the port) on a single line.  If
.B \-verbose
was specified, getpeername prints a more detailed report consisting of
the word `Unix' on the first line, the word `Port' on the second line,
and the name of the file on the third line.
X
If the socket is an Internet socket, then getpeername prints the port
number on the first line and the numeric address on the second line.  If
.B \-verbose
was specified, getpeername prints a more detailed report consisting of
the word `Internet' on the first line, the word `Port' on the second
line, the port numer on the third line, the word `Host' on the fourth
line.  On the fifth and following lines it prints all of the numeric
internet addresses followed by all the host names returned by the
gethostbyaddr(3) library routine.
X
.SH EASTER EGG
X
X  If you specify \fB-verbose\fP twice, the program will print a
copyright notice.
X
.SH EXAMPLES
X
X  I have a feeling any practical uses of the getpeername program are
fairly complicated.  If you actually do use it in a non-trivial way,
drop me a line.
X
.RS
.nf
client$ hose mail.cis.ufl.edu smtp \-in ./getpeername
25
128.227.224.13
.fi
.RE
X
X  You connected to mail.cis.ufl.edu on the SMTP port (port 25).  For a
verbose report:
X
.RS
.nf
X aviator:80 $ ./hose mail.cis.ufl.edu smtp -in ./getpeername -v
Internet
Port
25
Host
128.227.224.13
128.227.100.196
inlet.cis.ufl.edu
.fi
.RE
X
X  Now let's give an example of a race condition which will cause
getpeername to fail:
X
.RS
.nf
client$ hose www.cis.ufl.edu 80 -in ./getpeername
./getpeername: getpeername failed on descriptor 0: Socket is not connected
.fi
.RE
X
X  The HTTP daemon tries to read a request, finds that half of the full
duplex connection closed (by the special behavior of the -in option on
hose(1)) and drops the connection before getpeername can query the
file descriptor.  We can cause the HTTP daemon to wait for us by
leaving both halves of the duplex connection open.
X
.RS
.nf
client$ hose www.cis.ufl.edu 80 -fd0 ./getpeername -v
Internet
Port
25
Host
128.227.224.13
128.227.100.196
inlet.cis.ufl.edu
.fi
.RE
X
X And, finally, let's extract some useful information from our socket.
X
.RS
.nf
client$ hose www.cis.ufl.edu 80 -fd0 sh -c " ./getpeername -v | \\
X	tail +5 | egrep -v '^[0-9.]*$' | head -1"
sand.cis.ufl.edu
.fi
.RE
X
.SH ERRORS
.B Socket operation on non-socket
X  The \fIfd\fP you specified does not refer to a socket, or refers to
a socket that has been closed.  This happens when you run getpeername
by itself (it is unlikely that any of the file descriptors attached to
an interactive shell are actually sockets), or if you goof up your
faucet/hose command and forgot to dup(2) one of your descriptors, or
if the remote machine manages to close the connection before
getpeername could run.
X
.B Bad file number
X  You gave it a bad file number for \fIfd\fP.  If you have enough
skill to actually generate this error, you probably know what is
wrong.
X
If you encounter any other errors, clue me in.
X
X
.SH "SEE ALSO"
.BR netpipes (1),
.BR faucet (1),
.BR hose (1),
.BR sockdown (1),
.BR socket (2),
.BR shutdown (2),
X
.SH NOTES
.LP
X  Just avoid doing anything funky like passing \fBgetpeername\fP
strings and it should serve you well.
X
.SH "CREDITS"
X
"Hi Mom! Hi Dad!"
X
.SH "COPYRIGHT"
Copyright (C) 1995 Robert Forsman
X
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
X
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
X
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
.SH "AUTHOR"
X Robert Forsman
X thoth@cis.ufl.edu
X Purple Frog Software
X http://www.purplefrog.com/~thoth/
SHAR_EOF
chmod 0444 getpeername.1 ||
echo 'restore of getpeername.1 failed'
Wc_c="`wc -c < 'getpeername.1'`"
test 6118 -eq "$Wc_c" ||
	echo 'getpeername.1: original size 6118, current size' "$Wc_c"
fi
# ============= getpeername.c ==============
if test -f 'getpeername.c' -a X"$1" != X"-c"; then
	echo 'x - skipping getpeername.c (File already exists)'
else
echo 'x - extracting getpeername.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'getpeername.c' &&
/*
X
X    getpeername.c, part of
X    faucet and hose: network pipe utilities
X    Copyright (C) 1995 Robert Forsman
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
X    */
X
static char info[] = "getpeername: a network utility for sockets\nWritten 1995 by Robert Forsman <thoth@cis.ufl.edu>\n";
#include	<stdio.h>
#include	<errno.h>
extern int errno;		/* I hate the errno header file */
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<sys/un.h>
#include	<netinet/in.h>
#include	<netdb.h>
X
char *progname;
X
void usage()
{
X    fprintf(stderr, "Usage: %s [ -verbose ] [ fd# ]\n", progname);
}
X
int getpeername();
int getsockname();
X
int main(argc, argv)
X    int argc;
X    char **argv;
{
X    int	i;
X    int	peer_not_sock = 1;
X    int	fd = 0;			/* assume socket is attached to stdin.
X				  (if it's attached to stdout, our
X				  output will go over the socket) */
X    int	verbose=0;
X
X    progname = argv[0];
X    if (0==strcmp(progname + strlen(progname) - 11, "getsockname") &&
X	(strlen(progname)<12 || progname[strlen(progname)-12] == '/'))
X	peer_not_sock = 0;
X
X    for (i=1; i<argc; i++) {
X	if (0==strncmp(argv[i], "-verbose", strlen(argv[i]))) {
X	    verbose++;
X	} else if (0==strncmp(argv[i], "-sock", strlen(argv[i]))) {
X	    peer_not_sock=0;
X	} else if (0==strncmp(argv[i], "-peer", strlen(argv[i]))) {
X	    peer_not_sock=1;
X	} else {
X	    break;
X	}
X    }
X    if (i<argc) {
X	fd = atoi(argv[i++]);
X    }
X    if (i<argc) {
X	fprintf(stderr, "Too many arguments\n");
X	usage();
X	exit(1);
X    }
X
X    if (verbose>1) {
X      emit_version("sockdown", 1995);
X    }
X
X    {
X	union {
X	    struct sockaddr	base;
X	    struct sockaddr_in	in;
X	    struct sockaddr_un	un;
X	} saddr;
X	struct sockaddr_in	*sinp = &saddr.in;
X	struct sockaddr_un	*sunp = &saddr.un;
X	int	saddrlen = sizeof(saddr);
X	int (*f)();
X	char	*name;
X	if (peer_not_sock) {
X	    f = getpeername;
X	    name = "peer";
X	} else {
X	    f = getsockname;
X	    name = "sock";
X	}
X
X	if (0!= f(fd, &saddr, &saddrlen)) {
X	    fprintf(stderr, "%s: get%sname failed on descriptor %d: ", progname, name, fd);
X	    perror("");
X	    exit(1);
X	}
X	if (saddr.base.sa_family == AF_UNIX) {
X	    if (verbose) puts("Unix\nPort");
X	    puts(sunp->sun_path); /* with newline */
X	} else if (saddr.base.sa_family == AF_INET) {
X	    if (verbose) puts("Internet\nPort");
X	    printf("%d\n", sinp->sin_port);
X	    if (verbose) puts("Host");
X	    {
X		struct in_addr* addr = &sinp->sin_addr;
X		int	i;
X		printf("%d", ((u_char*)addr)[0]);
X		for (i=1; i<sizeof(*addr); i++)
X		    printf(".%d",((u_char*)addr)[i]);
X		printf("\n");
X	    }
X	    if (verbose) {
X		struct hostent	*host;
X		host = gethostbyaddr((char*)&sinp->sin_addr, sizeof(sinp->sin_addr),
X				     AF_INET);
X		if (host) {
X		    int	j,k;
X		    for (j=0; host->h_addr_list[j]; j++) {
X			struct in_addr	*ia =
X			    (struct in_addr *)host->h_addr_list[j];
X			if (0==memcmp(host->h_addr_list[j],
X				      &sinp->sin_addr, host->h_length)) {
X			    continue; /* skip this one */
X			}
X			printf("%d", ((u_char*)ia)[0]);
X			for (k=1; k<sizeof(*ia); k++)
X			    printf(".%d",((u_char*)ia)[k]);
X			printf("\n");
X		    }
X		    puts(host->h_name);
X		    for (j=0; host->h_aliases[j]; j++) {
X			puts(host->h_aliases[j]);
X		    }
X		} else {
X		    puts(" (no name for host)");
X		}
X	    }
X	} else {
X	    fprintf(stderr, "%s: unknown address family (%d) returned by get%sname\n", saddr.base.sa_family, name);
X	}
X    }
}
SHAR_EOF
chmod 0644 getpeername.c ||
echo 'restore of getpeername.c failed'
Wc_c="`wc -c < 'getpeername.c'`"
test 4042 -eq "$Wc_c" ||
	echo 'getpeername.c: original size 4042, current size' "$Wc_c"
fi
# ============= netpipes.1 ==============
if test -f 'netpipes.1' -a X"$1" != X"-c"; then
	echo 'x - skipping netpipes.1 (File already exists)'
else
echo 'x - extracting netpipes.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'netpipes.1' &&
.\" $Id: netpipes.1,v 1.2 1995/10/24 18:30:04 thoth Exp $ Copyright 1995 by Robert Forsman
.\""
.TH NETPIPES 1 "June 12, 1995"
.SH NAME
netpipes \- a package to manipulate BSD TCP/IP stream sockets
.SH SYNOPSIS
\fBfaucet\fP \fIport\fP
(\fB\-in\fP|\fB\-out\fP|\fB\-err\fP|\fB\-fd\fP\fIn\fP)
[\fB\-once\fP]
[\fB\-verbose\fP]
[\fB\-quiet\fP]
[\fB\-unix\fP]
[\fB\-foreignhost\fP \fIaddr\fP]
[\fB\-foreignport\fP \fIport\fP]
[\fB\-localhost\fP \fIaddr\fP]
[\fB\-daemon\fP]
[\fB\-shutdown\fP (r|w) ]
[\fB\-serial\fP]
\fIcommand\fP \fIargs\fP
X
\fBhose\fP \fIhostname\fP \fIport\fP
(\fB\-in\fP|\fB\-out\fP|\fB\-err\fP|\fB\-fd\fP\fIn\fP|\fB\-slave\fP)
[\fB\-unix\fP]
[\fB\-localport\fP \fIport\fP]
[\fB\-localhost\fP \fIaddr\fP]
[\fB\-retry\fP \fIn\fP]
[\fB\-delay\fP \fIn\fP]
[\fB\-shutdown\fP [r|w][a] ]
\fIcommand\fP \fIargs\fP
X
\fBsockdown\fP
[\fIfd\fP
[\fIhow\fP] ]
X
\fBgetpeername\fP
[ \fB\-verbose\fP ]
[ \fB\-sock\fP ]
[ \fIfd\fP ]
X
\fBgetsockname\fP
[ \fB\-verbose\fP ]
[ \fB\-peer\fP ]
[ \fIfd\fP ]
X
.SH DESCRIPTION
X
X  The netpipes package makes TCP/IP streams usable in shell scripts.
It can also simplify client/server code by allowing the programmer to
skip all the tedious programming bits related to sockets and
concentrate on writing a filter/service.
X
X  \fBfaucet\fP is the server end of a TCP/IP stream.  It listens on a
port of the local machine waiting for connections.  Every time it gets
a connection it forks a process to perform a service for the
connecting client.
X
X  \fBhose\fP is the client end of a TCP/IP stream.  It actively
connects to a remote port and execs a process to request a service.
X
X  \fBsockdown\fP is a simple program designed to shut down part or all
of the socket connection.  It is primarily useful when the processes
connected to the socket perform both input and output.
X
X  \fBgetpeername\fP and \fBgetsockname\fP are two names for a program
designed to print out the addresses of the ends of a socket.
\fBgetpeername\fP prints the address of the remote end and
\fBgetsockname\fP prints the address of the local end.
X
X
.SH EXAMPLES
X
Here is a simple command I often perform to transfer directory trees
between machines.  (rsh does not work because one machine is connected
using SLIP and .rhosts are out of the question).
.RS
.nf
server$ faucet 3000 -out tar cf - .
client$ hose server 3000 -in tar xvf -
.fi
.RE
X
Here is a minimal HTTP client.  It is so minimal it speaks old HTTP.
.RS
.nf
cairo$ hose www.cis.ufl.edu 80 -in -out \\
X	sh -c "(echo 'GET /'; sockdown) & cat > result"
.fi
.RE
X
And of course, there is Nick Trown's metaserver for Netrek
.RS
.nf
cairo$ hose metaserver.ecst.csuchico.edu 3521 -in cat
.fi
.RE
X
Finally, allow me to apologize ahead of time for the convolutedness of
the following example.  It requires an understanding of Bourne shell
file descriptor redirection syntax (and illustrates why csh and tcsh
suck eggs).  Do not try to type this from your tcsh command line.  Get
a bash (GNU's Bourne Again SHell).
.RS
.nf
server$ faucet 3000 -in -out -verbose enscript -2rGhp -
client$ ps aux | hose server 3000 -in -out \\
X	sh -c " (cat <&3; sockdown ) & cat >&4 " 3<&0 4>&1 | \\
X	lpr -Pps422
.fi
.RE
This proves that hose \fIcan\fP be used as part of a pipeline to
perform a sort of remote procedure call (RPC).  After you have figured
out that example, you will know how to use Bourne shell to shuffle
file descriptors around.  It is a handy skill.
X
Now we go to the extreme, but simplify things by using the
\fI-slave\fP option of hose.  The following is a socket relay
.RS
.nf
gateway$ faucet 3000 -in -out \\
X	sh -c "hose server 4000 -slave "
.fi
.RE
It's a handy little bugger when you want to tunnel through a firewall
on an occasional basis.
X
.SH "SEE ALSO"
.BR faucet (1),
.BR hose (1),
.BR sockdown (1),
.BR getpeername (1),
X
.SH "COPYRIGHT"
Copyright (C) 1995 Robert Forsman
X
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
X
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
X
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
.SH "AUTHOR"
X Robert Forsman
X thoth@cis.ufl.edu
X Purple Frog Software
X http://www.purplefrog.com/~thoth/
SHAR_EOF
chmod 0444 netpipes.1 ||
echo 'restore of netpipes.1 failed'
Wc_c="`wc -c < 'netpipes.1'`"
test 4616 -eq "$Wc_c" ||
	echo 'netpipes.1: original size 4616, current size' "$Wc_c"
fi
# ============= faucet.html ==============
if test -f 'faucet.html' -a X"$1" != X"-c"; then
	echo 'x - skipping faucet.html (File already exists)'
else
echo 'x - extracting faucet.html (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'faucet.html' &&
<title>faucet</title>
<body>
<H1>FAUCET(1)</H1>
X
<P>
<H2>NAME
</H2>
faucet - a fixture for a BSD network pipe
X
<P>
<H2>SYNOPSIS
</H2>
<b>faucet</b>
<i>   port</i>
X   (<b>-in</b>
|<b>-out</b>
|<b>-err</b>
|<b>-fd</b>
<i>n</i>
)+  [<b>-once</b>
]  [<b>-verbose</b>
]
[<b>-quiet</b>
] [<b>-unix</b>
] [<b>-foreignhost</b>
<i> addr</i>
]  [<b>-foreignport</b>
<i>  port</i>
]
[<b>-localhost</b>
<i>  addr</i>
]  [<b>-daemon</b>
] [<b>-shutdown</b>
X (r|w) ] [<b>-serial</b>
]
<i>command args
</i>
X
<P>
<H2>DESCRIPTION
</H2>
<b>faucet</b>
X attempts to provide the functionality of pipes over
the   network.    It  behaves  as  the  server  end  of  a
server-client connection.  When used with<b> hose(1)</b>
X  it  can
function as a replacement for
tar -cf - . | rsh other "cd destdir; tar -xf -"
<b>faucet</b>
X  and<b> hose</b>
X are especially useful when you don't have
easy access to the destination machine.
X
<P><b>faucet</b>
X creates a BSD socket, binds it to the<i>  port</i>
X  specified on the command line, and listens for connections.
<P>Every  time<b>  faucet</b>
X  gets a connection it exec(2)s<i> command
</i>
and its<i> args</i>
X with stdin, stdout, stderr, and/or  arbitrary
file descriptors redirected according to the<b> -in -out -err
-fd</b><i>n</i>
X flags.<b>  faucet</b>
X  also  automagically  shuts  down  the
unused  half of the connection if only<b> -in</b>
X is specified or
if only<b> -out</b>
X and/or<b> -err</b>
X are specified.  See the<b> -shutdown
</b>
option for more information.
<P>If  the<b>  -once</b>
X  flag is specified,<b> faucet</b>
X will exec(2) the
<i>command</i>
X instead of fork(2)ing and exec(2)ing.<b>  -once</b>
X means
that the network pipe is only good for one shot.
<P>The<b>  -verbose</b>
X  flag  specifies  that<b>  faucet</b>
X  should print
information  about  connecting  hosts.   This  information
includes the numeric host address, host names, and foreign
port numbers.   The<b>  -quiet</b>
X  flag  specifies  that<b>  faucet
</b>
should NOT print such info.<b>  -quiet</b>
X is the default.
<P>The<b>  -unix</b>
X flag specifies that the<i> port</i>
X is not an internet
port number or service name, but instead it is a  filename
for a UNIX domain socket.
<P>The<b>  -foreignhost</b>
X  option  specifies  that  faucet  should
reject all connections that do  not  come  from  the<i>  host
</i>
machine.   Similarly<b>  -foreignport</b>
X  specifies  that faucet
should reject all connections that are not bound on  their
local machine to the<i> port</i>
X argument.  The above two options
allow a crude form of authentication.  Note that  on  most
systems only root can bind a socket to a port number below
1024.
X
<P><b>Please</b>
X do not be fooled into thinking  this  makes  faucet
secure.  There are ways to spoof IP numbers that have been
known for years (but  only  publicized  recently).   I  do
think  that  this  method is safe from DNS spoofs, but you
probably should have<b> nospoof on</b>
X in /etc/host.conf  anyway.
X
<P><b>-localhost</b>
X  specifies  that the listening socket should be
bound to a specific internet address on this  host.   This
is only useful on hosts with several internet numbers.
X
<P><b>-daemon</b>
X specifies that the faucet should disassociate from
the controlling terminal once it has started listening  on
the  socket.   This is done using the standard ``close all
file  descriptors,  ioctl  TIOCNOTTY,  fork()  and  parent
exit'' sequence.
X
<P><b>-shutdown</b>
X  is  used  to turn the (normally) bi-directional
socket into a uni-directional one
If the `r' is present, then<b> faucet</b>
X will close  half  the
connection  to  make  it a read-only socket.  If we try to
write, it will fail.  If the remote  connection  tries  to
read, it will percieve the socket as closed.
If  instead  the  `w' is present, then<b> faucet</b>
X will close
the other half of the connection to make it  a  write-only
socket.  If we try to read, we will percieve the socket as
closed.  If the remote connection tries to write, it  will
fail.
The  default behavior is to leave both halves open, however the shutdown of half of the connection  is  automagically  done  by certain combinations of the<b> -in</b>
,<b> -out</b>
, and
<b>-err</b>
X flags.  To suppress their automagic behavior you  can
use (respectively) -fd0, -fd1, and -fd2.
X
<P><b>-serial</b>
X  causes  faucet  to  wait  for one child to finish
before accepting any more connections.  Serialization is a
very crude form of critical-section management.
X
<P>
<H2>EXAMPLES
</H2>
This creates a TCP-IP socket on the local machine bound to
port 3000.
<pre>
example$ faucet 3000 -out -verbose tar -cf - .
</pre>
Every time some process (from  any  machine)  attempts  to
connect  to  port  3000 on this machine the<b> faucet</b>
X program
will fork(2) a process and the child will exec(2) a
tar -cf - .
The<b> -out</b>
X option means that the output of the child process
will have been redirected into the new socket retrieved by
the accept(2) call.<b>  -verbose</b>
X means that faucet will print
information about each new connection.
<P>This creates a UNIX domain socket in the current directory
<pre>
example$ faucet u-socket -out -err -once -unix csh -c \
X	"dd if=angio.pgm | funky.perl.script"
</pre>
The<b> -out -err</b>
X option means that stdout and stderr will  be
redirected  in  the child process.  The<b> -once</b>
X option means
that the faucet will not fork(2), but exec(2) the  process
so that only the first process can connect to the u-socket
before the faucet becomes unavailable.
X
<P>
<H2>SEE ALSO
</H2>
<A HREF="netpipes.html"><b>netpipes</b></a>(1),
<A HREF="hose.html"><b>hose</b></a>(1),
<A HREF="sockdown.html"><b>sockdown</b></a>(1),
<A HREF="getpeername.html"><b>getpeername</b></a>(1),
<b>socket</b>(2),
<b>bind</b>(2),
<b>listen</b>(2),
<b>accept</b>(2),
<b>shutdown</b>(2),
<b>services</b>(5),
<b>gethostbyaddr</b>(3)
X
<P>
<H2>NOTES
</H2>
Doubtless there are bugs in this  program,  especially  in
the  unix  domain  socket  portions.   I  welcome  problem
reports and would like to make these programs  as  "clean"
(no leftover files, sockets) as possible.
<P>Release  2.3  added support for multi-homed hosts: hosts
with multiple internet numbers (such as gateways).  Before
this  faucet  assumed  that the first internet number that
gethostbyname returned was  the  only  one.<b>   -foreignport
</b>
authentication was weakened by this inadequacy so I beefed
up the algorithms.<b>  -foreignport</b>
X will accept a  connection
from  any of the internet numbers associated with the host
name.
X
<P>
<H2>CREDITS
</H2>
Thanks to Steve Clift &lt;clift@ml.csiro.au&gt; for  SGI  (SysV)
patches.
<P>Many people complained about the old way of specifying the
command.  Thanks to whoever gave me the alternative  which
is now implemented.  It is much better.
<P>Randy  Fischer  &lt;fischer@ucet.ufl.edu&gt;  finally prodded me
into fixing the old lame non-handling of multi-homed host.
X
<P>
<H2>COPYRIGHT
</H2>
Copyright (C) 1992,1993,1994,1995 Robert Forsman
<P>This  program  is  free  software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License  as  published  by  the  Free Software Foundation;
either version 2 of the License, or (at your  option)  any
later version.
<P>This  program  is  distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty  of  MERCHANTABILITY  or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU  General  Public  License  for  more
details.
<P>You  should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software  Foundation,  Inc.,  675  Mass Ave, Cambridge, MA
02139, USA.
X
<P>
<H2>AUTHOR
</H2>
Robert Forsman<br>
thoth@cis.ufl.edu<br>
<a href="http://www.purplefrog.com/">Purple Frog Software</a><br>
<a href="http://www.purplefrog.com/~thoth/">http://www.purplefrog.com/~thoth/</a>
</body>
SHAR_EOF
chmod 0644 faucet.html ||
echo 'restore of faucet.html failed'
Wc_c="`wc -c < 'faucet.html'`"
test 7904 -eq "$Wc_c" ||
	echo 'faucet.html: original size 7904, current size' "$Wc_c"
fi
# ============= getpeername.html ==============
if test -f 'getpeername.html' -a X"$1" != X"-c"; then
	echo 'x - skipping getpeername.html (File already exists)'
else
echo 'x - extracting getpeername.html (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'getpeername.html' &&
<title>getpeername</title>
<P><H1>GETPEERNAME(1)
</H1>
X
<H2>NAME
</H2>
getpeername  -  get  information about this or that end of
the socket's connection
X
<P>
<H2>SYNOPSIS
</H2>
<b>getpeername</b>
X [<b> -verbose</b>
X ] [<b> -sock</b>
X ] [<i> fd</i>
X ]
X
<P><b>getsockname</b>
X [<b> -verbose</b>
X ] [<b> -peer</b>
X ] [<i> fd</i>
X ]
X
<P>
<H2>DESCRIPTION
</H2>
<b>getpeername</b>
X performs a getpeername(2) system call  on  one
of its file descriptors specified by<i> fd</i>
X and prints out the
results.  The default<i> fd</i>
X is 0 (stdin).  You may cause<b> get</b>
<b>peername</b>
X to behave like<b> getsockname</b>
X by providing the -sock
argument.
X
<P><b>getsockname</b>
X performs a getsockname(2) system call  on  one
of its file descriptors specified by<i> fd</i>
X and prints out the
results. The default<i> fd</i>
X is 0 (stdin).  You may cause<b>  get</b>
<b>sockname</b>
X to behave like<b> getpeername</b>
X by providing the -peer
argument.
<P>There is a  severe  limitation  of<b>  getpeername</b>
.   If  the
remote process has closed the connection, getpeername will
fail with a `Socket is not connected'  error.   This  will
happen with dismaying frequency when the remote process is
not dependent upon the local process for input and  it  is
only  sending  small  amounts of output before closing the
connection.  Hopefully the practical uses  of  getpeername
(if there are any) will not exercise this problem.
<P>You  can  use<b> getpeername</b>
X to find out the address of the
opposite end of a socket.  You can use<b> getsockname</b>
X to find
out the address of the local end of a socket.  They are in
fact the same program with different names.  We will refer
to  both  of them by the name<b> getpeername</b>
X in the following
description.
X
<P><b>getpeername</b>
X knows how to display  peer  information  about
UNIX  and  Internet  sockets.   If  you  try  to use it on
another type of socket, it  will  fail  with  an  "unknown
address family" error.  If you regularly deal with strange
sockets and wish getpeername to work with  them,  send  me
email.
<P>If  the  socket  is a UNIX domain socket, then getpeername
prints the name of the file (which is the port) on a  single line.  If<b> -verbose</b>
X was specified, getpeername prints a
more detailed report consisting of the word `Unix' on  the
first  line,  the  word `Port' on the second line, and the
name of the file on the third line.
<P>If the socket is  an  Internet  socket,  then  getpeername
prints  the  port number on the first line and the numeric
<P></H2>
address on the second line.  If<b>  -verbose</b>
X  was  specified,
getpeername  prints  a  more detailed report consisting of
the word `Internet' on the first line, the word `Port'  on
the  second  line,  the  port numer on the third line, the
word `Host' on the fourth line.  On the fifth and  following  lines it prints all of the numeric internet addresses
followed by all the host names returned  by  the  gethostbyaddr(3) library routine.
X
<P>
<H2>EASTER <b>EGG
</b>
</H2>
If  you specify<b> -verbose</b>
X twice, the program will print a
copyright notice.
X
<P>
<H2>EXAMPLES
</H2>
I have a feeling any practical uses of  the  getpeername
program are fairly complicated.  If you actually do use it
in a non-trivial way, drop me a line.
<Pre>
client$ hose mail.cis.ufl.edu smtp -in ./getpeername
25
128.227.224.13
</pre>
<P>You connected to mail.cis.ufl.edu on the SMTP port (port
25).  For a verbose report:
<Pre>
aviator:80 $ ./hose mail.cis.ufl.edu smtp -in ./getpeername -v
Internet
Port
25
Host
128.227.224.13
128.227.100.196
inlet.cis.ufl.edu
</pre>
<P>Now let's give an example of a race condition which will
cause getpeername to fail:
<Pre>
client$ hose www.cis.ufl.edu 80 -in ./getpeername
</pre>
<P>The HTTP daemon tries to read a request, finds that half
of  the  full  duplex  connection  closed  (by the special
behavior of the -in option on hose(1)) and drops the  connection  before getpeername can query the file descriptor.
We can cause the HTTP daemon to wait  for  us  by  leaving
both halves of the duplex connection open.
<Pre>client$ hose www.cis.ufl.edu 80 -fd0 ./getpeername -v
Internet
Port
25
Host
128.227.224.13
128.227.100.196
inlet.cis.ufl.edu
</pre>
<P>And,  finally, let's extract some useful information from
our socket.
<Pre>
client$ hose www.cis.ufl.edu 80 -fd0 sh -c " ./getpeername -v | \
X	tail +5 | egrep -v '^[0-9.]*$' | head -1"
sand.cis.ufl.edu
</pre>
X
<P>
<H2>ERRORS
</H2>
<b>Socket operation on non-socket
</b>
The<i> fd</i>
X you specified does not  refer  to  a  socket,  or
refers  to  a  socket  that has been closed.  This happens
when you run getpeername by itself (it  is  unlikely  that
any  of  the  file  descriptors attached to an interactive
shell are actually  sockets),  or  if  you  goof  up  your
faucet/hose  command  and  forgot  to  dup(2)  one of your
descriptors, or if the remote machine manages to close the
connection before getpeername could run.
X
<P><b>Bad file number
</b>
You  gave  it  a  bad  file  number for<i> fd</i>
.  If you have
enough skill to actually generate this error, you probably
know what is wrong.
<P>If you encounter any other errors, clue me in.
X
<P>
<H2>SEE ALSO
</H2>
<A HREF="netpipes.html"><b>netpipes</b></a>(1),
<A HREF="faucet.html"><b>faucet</b></a>(1),
<A HREF="hose.html"><b>hose</b></a>(1),
<A HREF="sockdown.html"><b>sockdown</b></a>(1),
<b>socket</b>(2),
<b>shutdown</b>(2),
X
X
<P>
<H2>NOTES
</H2>
Just avoid doing anything funky like passing<b> getpeername
</b>
strings and it should serve you well.
X
<P>
<H2>CREDITS
</H2>
``Hi Mom! Hi Dad!''
X
<P>
<H2>COPYRIGHT
</H2>
Copyright (C) 1995 Robert Forsman
<P>This  program  is  free  software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License  as  published  by  the  Free Software Foundation;
either version 2 of the License, or (at your  option)  any
later version.
<p>
This  program  is  distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty  of  MERCHANTABILITY  or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU  General  Public  License  for  more
details.
<P>You  should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software  Foundation,  Inc.,  675  Mass Ave, Cambridge, MA
02139, USA.
X
<P>
<H2>AUTHOR
</H2>
Robert Forsman<br>
thoth@cis.ufl.edu<br>
<a href="http://www.purplefrog.com/">Purple Frog Software</a><br>
<a href="http://www.purplefrog.com/~thoth/">http://www.purplefrog.com/~thoth/</a>
</body>
SHAR_EOF
chmod 0644 getpeername.html ||
echo 'restore of getpeername.html failed'
Wc_c="`wc -c < 'getpeername.html'`"
test 6557 -eq "$Wc_c" ||
	echo 'getpeername.html: original size 6557, current size' "$Wc_c"
fi
# ============= hose.html ==============
if test -f 'hose.html' -a X"$1" != X"-c"; then
	echo 'x - skipping hose.html (File already exists)'
else
echo 'x - extracting hose.html (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'hose.html' &&
<title>hose</title>
<body>
<H1>HOSE(1)</H1>
X
<P>
<H2>NAME</H2>
hose - the client end of a BSD network pipe
X
<P>
<H2>SYNOPSIS
</H2>
<b>hose</b>
<i>  hostname  port</i>
X  (<b>-in</b>
|<b>-out</b>
|<b>-err</b>
|<b>-fd</b>
<i>n</i>
|<b>-slave</b>
)  [<b>-unix</b>
]
[<b>-localport</b>
<i> port</i>
] [<b>-localhost</b>
<i> addr</i>
] [<b>-retry</b>
<i> n</i>
] [<b>-delay</b>
<i>  n</i>
]
[<b>-shutdown</b>
X [r|w][a] ]<i> command args
</i>
X
<P>
<H2>DESCRIPTION
</H2>
<b>hose</b>
X  attempts  to provide the functionality of pipes over
the  network.   It  behaves  as  the  client  end   of   a
server-client connection.  When used with<b> faucet(1)</b>
X it can
function as a replacement for
tar -cf - . | rsh other "cd destdir; tar -xf -"
<b>faucet</b>
X and<b> hose</b>
X are especially useful when you don't  have
easy access to the destination machine.
X
<P><b>hose</b>
X creates a BSD socket and, if the<b> -localport</b>
X option is
used, binds it to the port number (or service name) specified immediately afterwards.  If<b> -localhost</b>
X is also specified then its argument is a local address to  bind  to.  (
<b>-localhost</b>
X  is  only  useful  on machines with multiple IP
addresses.)
X
<P><b>hose</b>
X then tries to connect to the foreign machine<i> hostname
</i>
with foreign port<i> port.
</i>
<P>If  successful<b> hose</b>
X redirects the socket to stdin, stdout,
stderr, and/or arbitrary file descriptors according to the
<b>-in  -out  -err -fd</b>
<i>n</i>
X flags.<b>  hose</b>
X also automagically shuts
down the unused half of the  connection  if  only<b>  -in</b>
X  is
specified  or if only<b> -out</b>
X and/or<b> -err</b>
X are specified.  See
the<b> -shutdown</b>
X option for more information.
X
<P><b>hose</b>
X then exec(2)s a<i> command</i>
X with<i> args</i>
.
<P>However, the<b> -slave</b>
X flag turns<b> hose</b>
X into a primitive  sort
of  telnet.   The<i>  command</i>
X is ignored.  Instead,<b> hose</b>
X goes
into a loop where  it  copies  bytes  from  stdin  to  the
socket,  and  bytes  from  the  socket to stdout.  This is
actually more useful than telnet because telnet  tries  to
perform  interpretation  on  the byte stream and generally
gets in your way.<b>  hose</b>
X just passes bytes without  mucking
with them.
<P>The<b>  -unix</b>
X flag specifies that the<i> port</i>
X is not an internet
port number or service name, but instead it is a  filename
for a UNIX domain socket.  This option may be simulated by
using<b> -unix-</b>
X  as the host name to connect to, or by  renaming the<b> hose</b>
X program to<b> uhose</b>
.
X
<P><b>-retry</b>
<i>  n</i>
X allows the user to specify that should retry the
connect(2) call for<i> n</i>
X times (or forever if<i> n</i>
X is negative).
<b>-delay</b>
<i>  n</i>
X  specifies  how  many  seconds  to delay between
tries.
X
<P><b>-shutdown</b>
X is used to control two behaviors.  The first set
is controlled by the `r' and `w' flags.
If  the  `r'  is  present, then<b> hose</b>
X will close half the
connection to make it a read-only socket.   If  the  child
tries  to  write,  it will fail.  If the remote connection
tries to read, it will percieve the socket as closed.
If instead the `w' is present, then<b> hose</b>
X will close  the
other  half  of  the  connection  to  make it a write-only
socket.  If the child tries to read, it will percieve  the
socket  as  closed.   If  the  remote  connection tries to
write, it will fail.
The default behavior is to leave both halves open,  however  the  shutdown of half of the connection is automagically done by certain combinations of the<b> -in</b>
,<b>  -out</b>
,  and
<b>-err</b>
X  flags.  To suppress their automagic behavior you can
use (respectively) -fd0, -fd1, and -fd2.
<P>The other behavior is controlled by the `a' flag.  If the
`a' flag is present then<b> hose</b>
X will fork(2) before execcing
the<i> command</i>
X and when the child exits  it  will  perform  a
shutdown(2)  with  how=2.   This closes both halves of the
connection.  This option is not necessary for most  applications  since  the  closing  of  the  file descriptors is
detected by the remote process, but  some  less  sophisticated  network  devices (such as printers) require a shutdown(2) for proper operation.
To make things perfectly clear, the list  of  acceptable
arguments  to  the<b>  -shutdown</b>
X  option  are `r', `w', `ra',
`wa', `a'.
X
<P>
<H2>EXAMPLES
</H2>
This will connect to port 3000 on  the  machine  reef  and
connect the socket to the stdin of a tar command.
<pre>
example$ hose reef 3000 -in tar -xf - .
</pre>
The command actually exec(2)ed by the<b> hose</b>
X program is
tar -xf - .
The<b>  -in</b>
X  option means that the input of the child process
will have been redirected into  the  socket  connected  to
reef.
<P>This  connects  to  a  UNIX  domain  socket in the current
directory
<pre>
example$ hose -unix- u-socket -in csh -c \
X	"unfunky.perl.script | dd of=sample.pgm"
</pre>
The socket provides input to the csh command.
X
<H2>SEE ALSO</H2>
<A HREF="netpipes.html"><b>netpipes</b></a>(1),
<A HREF="faucet.html"><b>faucet</b></a>(1),
<A HREF="sockdown.html"><b>sockdown</b></a>(1),
<A HREF="getpeername.html"><b>getpeername</b></a>(1),
<b>socket</b>(2),
<b>bind</b>(2),
<b>connect</b>(2),
<b>shutdown</b>(2),
<b>services</b>(5),
<b>gethostbyaddr</b>(3)
X
X
<P>
<H2>NOTES
</H2>
Doubtless there are bugs in this  program,  especially  in
the  unix  domain  socket  portions.   I  welcome  problem
reports and would like to make these programs  as  "clean"
(no leftover files, sockets) as possible.
<P>Release  2.3  added support for multi-homed hosts: hosts
with multiple internet numbers (such as gateways).  Before
this  faucet  assumed  that the first internet number that
gethostbyname returned was  the  only  one.<b>   -foreignport
</b>
authentication was weakened by this inadequacy so I beefed
up the algorithms.<b>  -foreignport
</b>
will accept a connection from any of the internet numbers
associated with the host name.
X
<P>
<H2>CREDITS
</H2>
Thanks  to  Steve Clift &lt;clift@ml.csiro.au&gt; for SGI (SysV)
patches.
<P>Many people complained about the old way of specifying the
command.   Thanks to whoever gave me the alternative which
is now implemented.  It is much better.
<P>Thanks to Sten Drescher &lt;smd@hrt213.brooks.af.mil&gt; for the
-retry  and  -delay patches and giving me the idea for the
-shutdown option.  Evidently some printer doesn't appreciate the socket being close(2)d.
<P>Randy  Fischer  &lt;fischer@ucet.ufl.edu&gt;  finally prodded me
into fixing the old lame non-handling of multi-homed host.
X
<P>
<H2>COPYRIGHT
</H2>
Copyright (C) 1992,1993,1994,1995 Robert Forsman
<P>This  program  is  free  software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License  as  published  by  the  Free Software Foundation;
either version 2 of the License, or (at your  option)  any
later version.
<P>This  program  is  distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty  of  MERCHANTABILITY  or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU  General  Public  License  for  more
details.
<P>
You  should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software  Foundation,  Inc.,  675  Mass Ave, Cambridge, MA
02139, USA.
X
<P>
<H2>AUTHOR
</H2>
Robert Forsman<br>
thoth@cis.ufl.edu<br>
<a href="http://www.purplefrog.com/">Purple Frog Software</a><br>
<a href="http://www.purplefrog.com/~thoth/">http://www.purplefrog.com/~thoth/</a>
</body>
SHAR_EOF
chmod 0644 hose.html ||
echo 'restore of hose.html failed'
Wc_c="`wc -c < 'hose.html'`"
test 7541 -eq "$Wc_c" ||
	echo 'hose.html: original size 7541, current size' "$Wc_c"
fi
# ============= netpipes.html ==============
if test -f 'netpipes.html' -a X"$1" != X"-c"; then
	echo 'x - skipping netpipes.html (File already exists)'
else
echo 'x - extracting netpipes.html (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'netpipes.html' &&
<title>netpipes</title>
<body>
<H1>NETPIPES(1)</H1>
X
<H2>NAME </H2>
netpipes - a package to manipulate BSD TCP/IP stream sockets
X
<P>
<H2>SYNOPSIS</H2>
<b>faucet</b>
<i>  port</i>
X   (<b>-in</b>
|<b>-out</b>
|<b>-err</b>
|<b>-fd</b>
<i>n</i>
)   [<b>-once</b>
]   [<b>-verbose</b>
]
[<b>-quiet</b>
]  [<b>-unix</b>
]  [<b>-foreignhost</b>
<i> addr</i>
] [<b>-foreignport</b>
<i> port</i>
]
[<b>-localhost</b>
<i> addr</i>
] [<b>-daemon</b>
] [<b>-shutdown</b>
X (r|w)  ]  [<b>-serial</b>
]
<i>command args
</i>
X
<P><b>hose</b>
<i>  hostname  port</i>
X  (<b>-in</b>
|<b>-out</b>
|<b>-err</b>
|<b>-fd</b>
<i>n</i>
|<b>-slave</b>
)  [<b>-unix</b>
]
[<b>-localport</b>
<i> port</i>
] [<b>-localhost</b>
<i> addr</i>
] [<b>-retry</b>
<i> n</i>
] [<b>-delay</b>
<i>  n</i>
]
[<b>-shutdown</b>
X [r|w][a] ]<i> command args
</i>
X
<P><b>sockdown</b>
X [<i>fd</i>
X [<i>how</i>
] ]
X
<P><b>getpeername</b>
X [<b> -verbose</b>
X ] [<b> -sock</b>
X ] [<i> fd</i>
X ]
X
<P><b>getsockname</b>
X [<b> -verbose</b>
X ] [<b> -peer</b>
X ] [<i> fd</i>
X ]
X
<P>
<H2>DESCRIPTION
</H2>
The  netpipes  package  makes  TCP/IP  streams usable in
shell scripts.  It can also simplify client/server code by
allowing  the  programmer to skip all the tedious programming bits related to sockets and concentrate on writing  a
filter/service.
X
<P><b>faucet</b>
X is the server end of a TCP/IP stream.  It listens
on a port of the local machine  waiting  for  connections.
Every time it gets a connection it forks a process to perform a service for the connecting client.
X
<P><b>hose</b>
X is the client end of a TCP/IP stream.  It  actively
connects to a remote port and execs a process to request a
service.
X
<P><b>sockdown</b>
X is a simple program designed to shut down  part
or  all  of the socket connection.  It is primarily useful
when the processes connected to the  socket  perform  both
input and output.
X
<P><b>getpeername</b>
X  and<b> getsockname</b>
X are two names for a program
designed to print out the  addresses  of  the  ends  of  a
socket.<b>   getpeername</b>
X prints the address of the remote end
and<b> getsockname</b>
X prints the address of the local end.
X
<P>
<H2>EXAMPLES
</H2>
Here is a simple  command  I  often  perform  to  transfer
directory  trees  between  machines.   (rsh  does not work
because one machine is connected using  SLIP  and  .rhosts
are out of the question).
<Pre>
server$ faucet 3000 -out tar cf - .
client$ hose server 3000 -in tar xvf -
</Pre>
<p>
Here is a minimal HTTP client.  It is so minimal it speaks
old HTTP.
<pre>
cairo$ hose www.cis.ufl.edu 80 -in -out \
X	sh -c "(echo 'GET /'; sockdown) &amp; cat > result"
</pre>
<p>And of course, there is Nick Trown's metaserver for Netrek
<pre>
cairo$ hose metaserver.ecst.csuchico.edu 3521 -in cat
</pre>
<P>Finally,  allow me to apologize ahead of time for the convolutedness of the  following  example.   It  requires  an
understanding  of Bourne shell file descriptor redirection
syntax (and illustrates why csh and tcsh suck  eggs).   Do
not  try  to type this from your tcsh command line.  Get a
bash (GNU's Bourne Again SHell).
<pre>
server$ faucet 3000 -in -out -verbose enscript -2rGhp -
client$ ps aux | hose server 3000 -in -out \
X	sh -c " (cat <&amp;3; sockdown ) &amp; cat >&amp;4 " 3<&amp;0 4&gt;&amp;1 | \
X	lpr -Pps422
</pre>
This proves that hose <em>can</em>
X be used as part of a pipeline to
perform  a sort of remote procedure call (RPC).  After you
have figured out that example, you will know  how  to  use
Bourne  shell to shuffle file descriptors around.  It is a
handy skill.
<P>Now we go to the extreme, but simplify things by using the
<i>-slave</i>
X option of hose.  The following is a socket relay
<pre>
gateway$ faucet 3000 -in -out \
X	sh -c "hose server 4000 -slave "
</pre>
It's a handy little bugger when you want to tunnel through
a firewall on an occasional basis.
X
<P>
<H2>SEE <b>ALSO
</b>
</H2>
<A HREF="faucet.html"><b>faucet</b></a>(1),
<A HREF="hose.html"><b>hose</b></a>(1),
<A HREF="sockdown.html"><b>sockdown</b></a>(1),
<A HREF="getpeername.html"><b>getpeername</b></a>(1),
X
<P>
<H2>COPYRIGHT
</H2>
Copyright (C) 1995 Robert Forsman
<P>This program is free software;  you  can  redistribute  it
and/or modify it under the terms of the GNU General Public
License as published  by  the  Free  Software  Foundation;
either  version  2 of the License, or (at your option) any
later version.
<P>This program is distributed in the hope that  it  will  be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS  FOR  A  PARTICULAR
PURPOSE.   See  the  GNU  General  Public License for more
details.
<P>
You should have received a copy of the GNU General  Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 675  Mass  Ave,  Cambridge,  MA
02139, USA.
X
<P>
<H2>AUTHOR
</H2>
Robert Forsman<br>
thoth@cis.ufl.edu<br>
<a href="http://www.purplefrog.com/">Purple Frog Software</a><br>
<a href="http://www.purplefrog.com/~thoth/">http://www.purplefrog.com/~thoth/</a>
</body>
SHAR_EOF
chmod 0644 netpipes.html ||
echo 'restore of netpipes.html failed'
Wc_c="`wc -c < 'netpipes.html'`"
test 5041 -eq "$Wc_c" ||
	echo 'netpipes.html: original size 5041, current size' "$Wc_c"
fi
# ============= sockdown.html ==============
if test -f 'sockdown.html' -a X"$1" != X"-c"; then
	echo 'x - skipping sockdown.html (File already exists)'
else
echo 'x - extracting sockdown.html (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sockdown.html' &&
<title>sockdown</title>
<body>
<P><H1>SOCKDOWN(1)</H1>
X
<H2>NAME</H2>
sockdown - shutdown(2) a socket
X
<P>
<H2>SYNOPSIS
</H2>
<b>sockdown</b>
X [<i>fd</i>
X [<i>how</i>
] ]
X
<P>
<H2>DESCRIPTION
</H2>
<b>sockdown</b>
X  performs  the  shutdown(2) system call on one of
its file descriptors specified by<i> fd</i>
.  The possible values
for<i> how</i>
X are
<pre>
0		convert to write-only file descriptor
writeonly	symbolic for same as above
1		convert to read-only file descriptor
readonly	symbolic for same as above
2		complete shutdown.  no reads or writes allowed in the future
totally		symbolic for same as above
</pre>
The default<i> fd</i>
X is 1 (stdout) and the default<i> how</i>
X is 1.
X
<P>
<H2>EXAMPLES
</H2>
Imagine  you have a machine that can perform a service (in
this case conversion from ASCII to fancy postscript) :
<pre>
server$ faucet 3000 -in -out enscript -2rGhp -
</pre>
You may then connect to it  with  a  hose.   However,  the
first example enters deadlock :
<pre>
client$ hose server 3000 -in -out \
X	sh -c " cat blah.txt &amp; cat > blah.ps "
</pre>
The  enscript  blocks  waiting  for  input from the socket
because not all  of  the  client  processes  have  exited.
While  the  cat blah.txt is finished, the cat > blah.ps is
not, and will not be finished until  the  remote  enscript
process  finishes  writing.  The enscript process will not
finish writing until it  is  finished  reading,  but  that
client-&gt;server  half  of the socket is still open and will
not be closed until all the  client  processes  are  done.
The result is deadlock.
<P>So, we use sockdown to close half of the pipe
<pre>
client$ hose server 3000 -in -out \
X	sh -c " ( cat blah.txt ; sockdown ) &amp; cat > blah.ps "
</pre>
This way when the cat blah.txt is done, half of the socket
is shut down and the remote enscript process runs  out  of
input, causing it to flush its output and exit, so eventually the whole mess finishes cleanly.
<P>Note: the &amp; on the hose is necessary  to  prevent  another
deadlock.   If  we  simply used the ; to serialize the two
cat processes it is possible that the enscript would  fill
up  its write buffer before the first cat was done causing
both processes to block and preventing the second cat from
draining the pipe.
X
<P>
<H2>ERRORS
</H2>
<b>Socket operation on non-socket
</b>
The<i>  fd</i>
X  you specified does not refer to a socket.  This
happens when you run sockdown by itself  (it  is  unlikely
that  any  of the file descriptors attached to an interactive shell are actually sockets) or if you  goof  up  your
faucet/hose  command  and  forgot  to  dup(2)  one of your
descriptors.
X
<P><b>Bad file number
</b>
You gave it a bad file  number  for<i>  fd</i>
.   If  you  have
enough skill to actually generate this error, you probably
know what is wrong.
<P>If you encounter any other errors, clue me in.
X
<P>
<H2>SEE ALSO
</H2>
<A HREF="netpipes.html"><b>netpipes</b></a>(1),
<A HREF="faucet.html"><b>faucet</b></a>(1),
<A HREF="hose.html"><b>hose</b></a>(1),
<A HREF="getpeername.html"><b>getpeername</b></a>(1),
<b>socket</b>(2),
<b>shutdown</b>(2)
X
<P>
<H2>NOTES
</H2>
Any normal human would assume a program this simple has to
be bug free, but I am an experienced programmer.
<P>Just avoid doing anything funky  like  passing<b>  sockdown
</b>
strings and it should serve you well.  You should not have
to pass it any arguments unless you  are  doing  something
fairly funky.
<P>Perhaps I should ditch the<b> shutdown -a</b>
X semantics on hose
since a<b> sockdown 1 2</b>
X would do the job.
X
<P>
<H2>CREDITS
</H2>
``Hi Mom! Hi Dad!''
<H2>COPYRIGHT
</H2>
Copyright (C) 1995 Robert Forsman
<P>This  program  is  free  software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License  as  published  by  the  Free Software Foundation;
either version 2 of the License, or (at your  option)  any
later version.
<P>This  program  is  distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty  of  MERCHANTABILITY  or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU  General  Public  License  for  more
details.
<P>You  should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software  Foundation,  Inc.,  675  Mass Ave, Cambridge, MA
02139, USA.
X
<P>
<H2>AUTHOR
</H2>
Robert Forsman<br>
thoth@cis.ufl.edu<br>
<a href="http://www.purplefrog.com/">Purple Frog Software</a><br>
<a href="http://www.purplefrog.com/~thoth/">http://www.purplefrog.com/~thoth/</a>
</body>
SHAR_EOF
chmod 0644 sockdown.html ||
echo 'restore of sockdown.html failed'
Wc_c="`wc -c < 'sockdown.html'`"
test 4558 -eq "$Wc_c" ||
	echo 'sockdown.html: original size 4558, current size' "$Wc_c"
fi
# ============= COPYING ==============
if test -f 'COPYING' -a X"$1" != X"-c"; then
	echo 'x - skipping COPYING (File already exists)'
else
echo 'x - extracting COPYING (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'COPYING' &&
X		    GNU GENERAL PUBLIC LICENSE
X		       Version 2, June 1991
X
X Copyright (C) 1989, 1991 Free Software Foundation, Inc.
X                          675 Mass Ave, Cambridge, MA 02139, USA
X Everyone is permitted to copy and distribute verbatim copies
X of this license document, but changing it is not allowed.
X
X			    Preamble
X
X  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
he GNU Library General Public License instead.)  You can apply it to
your programs, too.
X
X  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
X
X  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
X
X  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.
X
X  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
X
X  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
X
X  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
X
X  The precise terms and conditions for copying, distribution and
modification follow.
X
X		    GNU GENERAL PUBLIC LICENSE
X   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
X
X  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".
X
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
X
X  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
X
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
X
X  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
X
X    a) You must cause the modified files to carry prominent notices
X    stating that you changed the files and the date of any change.
X
X    b) You must cause any work that you distribute or publish, that in
X    whole or in part contains or is derived from the Program or any
X    part thereof, to be licensed as a whole at no charge to all third
X    parties under the terms of this License.
X
X    c) If the modified program normally reads commands interactively
X    when run, you must cause it, when started running for such
X    interactive use in the most ordinary way, to print or display an
X    announcement including an appropriate copyright notice and a
X    notice that there is no warranty (or else, saying that you provide
X    a warranty) and that users may redistribute the program under
X    these conditions, and telling the user how to view a copy of this
X    License.  (Exception: if the Program itself is interactive but
X    does not normally print such an announcement, your work based on
X    the Program is not required to print an announcement.)
X
These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
X
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
X
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
X
X  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
X
X    a) Accompany it with the complete corresponding machine-readable
X    source code, which must be distributed under the terms of Sections
X    1 and 2 above on a medium customarily used for software interchange; or,
X
X    b) Accompany it with a written offer, valid for at least three
X    years, to give any third party, for a charge no more than your
X    cost of physically performing source distribution, a complete
X    machine-readable copy of the corresponding source code, to be
X    distributed under the terms of Sections 1 and 2 above on a medium
X    customarily used for software interchange; or,
X
X    c) Accompany it with the information you received as to the offer
X    to distribute corresponding source code.  (This alternative is
X    allowed only for noncommercial distribution and only if you
X    received the program in object code or executable form with such
X    an offer, in accord with Subsection b above.)
X
The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
X
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
X
X  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
X
X  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
X
X  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
X
X  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
X
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
X
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
X
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
X
X  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.
X
X  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
X
Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
X
X  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
X
X			    NO WARRANTY
X
X  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
X
X  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
X
X		     END OF TERMS AND CONDITIONS
X
X	Appendix: How to Apply These Terms to Your New Programs
X
X  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
X
X  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
X
X    <one line to give the program's name and a brief idea of what it does.>
X    Copyright (C) 19yy  <name of author>
X
X    This program is free software; you can redistribute it and/or modify
X    it under the terms of the GNU General Public License as published by
X    the Free Software Foundation; either version 2 of the License, or
X    (at your option) any later version.
X
X    This program is distributed in the hope that it will be useful,
X    but WITHOUT ANY WARRANTY; without even the implied warranty of
X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X    GNU General Public License for more details.
X
X    You should have received a copy of the GNU General Public License
X    along with this program; if not, write to the Free Software
X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X
Also add information on how to contact you by electronic and paper mail.
X
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
X
X    Gnomovision version 69, Copyright (C) 19yy name of author
X    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
X    This is free software, and you are welcome to redistribute it
X    under certain conditions; type `show c' for details.
X
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
X
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:
X
X  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
X  `Gnomovision' (which makes passes at compilers) written by James Hacker.
X
X  <signature of Ty Coon>, 1 April 1989
X  Ty Coon, President of Vice
X
This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.
SHAR_EOF
chmod 0644 COPYING ||
echo 'restore of COPYING failed'
Wc_c="`wc -c < 'COPYING'`"
test 17981 -eq "$Wc_c" ||
	echo 'COPYING: original size 17981, current size' "$Wc_c"
fi
exit 0



