[net.sources] A network library for non-guru's

josh@hi.uucp (Josh Siegel ) (04/16/87)

Contain below is my network library which I have been
developing over the last few weeks because I got tired
of doing the same thing over and over again...

It does:
	1) Basic networking (IP/TCP)
	2) pty's
	3) IO control
	4) Other misc functions...

This is the FIRST release and so the edges have not
been worked off.  Please,  send any comments or
bug reports to me.

Also,  this uses sockets so that it does not
work on System V.  Sorry...

It also does not make use of XDR.  This means that
 transfering data from machine to machine is still
 ugly.  If only BSD4.3 had XDR....

Have fun with it... lets see some network games!

---
Josh Siegel		(siegel@hc.dspo.gov)
                        (505) 277-2497  (Home)
		I'm a mathematician, not a programmer!
---

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	network
# This archive created: Wed Apr 15 22:15:16 1987
echo shar: creating directory network
mkdir network
cd network
echo shar: extracting README '(922 characters)'
sed 's/^XX//' << \SHAR_EOF > README
XX---
XX  Copyright 1987, Josh Siegel
XX  All rights reserved.
XX 
XX  Josh Siegel (siegel@hc.dspo.gov)
XX  Dept of Electrical and Computer Engineering,
XX  University of New Mexico,
XX  Albuquerque , New Mexico
XX---
XX
XXThis directory contains the first release of my network
XXroutines.
XX
XXOne of the problems with it is that I really don't have a
XXreal manual for it so users are going to have to use my
XXexamples to figure out how it works. There is a "man" page
XXfor the library but it is not very helpful. Hopefully I
XXmade the examples clear and consise so that they do the
XXtrick for now.  I plan to change this in the future.
XX
XXIf you make any changes,  please mark the changes clearly
XXso that I don't get blaimed for the mistakes down the
XXline.  Also, mail me the changes so that I can incorporate
XXthem into the master copy.
XX
XXAlso, I am not responsible for any loss of time or damage
XXdue to this software (I had to say it).
XX
XX			--Josh Siegel
SHAR_EOF
if test 922 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 922 characters)'
fi
echo shar: extracting basic.c '(4772 characters)'
sed 's/^XX//' << \SHAR_EOF > basic.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: basic.c,v 1.1 87/04/15 21:28:59 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/basic.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:28:59 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	basic.c,v $
XX * Revision 1.1  87/04/15  21:28:59  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XX
XXextern char *user_errlist[];
XXextern int errno;
XX
XX#include "net.h"
XX
XXpkill(fd)
XXint fd;
XX{
XX	shutdown(fd,2);
XX	if(close(fd)<0) 
XX		return(-1);
XX}
XX
XXchar *useport(port)
XXint port;
XX{
XX	static char buff[8];
XX
XX	sprintf(buff,"#%d",port);
XX
XX	return(buff);
XX}
XX
XX/* Myport:  I wrote this so that if 100 students are using the routines,
XX	    they have a way of avoiding using the same socket address.
XX	    This uses getuid() to figure out what to choose as a 
XX	    port.
XX
XX Problems:  Could this be done cleaner ?
XX*/
XX
XXchar *myport()
XX{
XX	static char buff[8]; /* Its static! Don't try to free it */ 
XX
XX	sprintf(buff,"#%d",MYPORT+getuid());
XX 
XX        return(buff); 
XX}
XX
XX/*
XXattach:
XX	This is used to establish a port to which other processes
XX	can connect.  It is very standard code except for the
XX	useport() and myport() hacks.
XX
XX*/
XX
XXattach(s)
XX	char            s[];
XX{
XX	int             f,*p;
XX	struct sockaddr_in sin;
XX	struct servent *sp;
XX	char buff[255];
XX
XX	bzero((char *) &sin,sizeof(sin));
XX
XX        /* Is this something passed to us from useport and myport? */
XX
XX	if(s[0]=='#') {
XX		sin.sin_port = htons(atoi(s+1));
XX	} else {
XX		sp = getservbyname(s, "tcp");
XX		if (sp == NULL)  {
XX			user_errlist[0]="service unknown";
XX			errno=255;
XX			return(-1);
XX		}
XX		sin.sin_port = sp->s_port;
XX	}
XX
XX	f = socket(AF_INET, SOCK_STREAM, 0);
XX	if (bind(f, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
XX		return(-1);
XX	}
XX	listen(f, 5);
XX	return (f);
XX}
XX
XX
XX/* 
XXAnswer: Excepts connection requests from clients.
XX
XXProblem: I could make it make note of where the connection came
XX	 from but I never felt I had a need 
XX
XX*/
XX	 
XXanswer(s)
XX	int             s;
XX{
XX	int             tmp;
XX	struct sockaddr_in from;
XX	int             len = sizeof(from);
XX
XX	bzero((char *) & from,len);
XX
XX	tmp = accept(s, &from, &len);
XX	return (tmp);
XX}
XX/*
XXPhone:  Connects to a established port setup by accept().  Again,
XX	very clean code except for the useport() and myport()
XX	hacks.
XX
XXThings to do:
XX	I could try to make this function call a interupt handler
XX	when connected so that it does not block for 30 or 40 seconds
XX	if the machine is down or something */
XX
XXphone(service, host)
XX	char            service[], host[];
XX{
XX
XX	struct sockaddr_in sin;
XX	struct servent *sp;
XX	struct hostent *hp;
XX	int             s,*p;
XX	char buff[255];
XX
XX	bzero((char *) &sin, sizeof(sin));
XX
XX	if(service[0]!='#') {
XX		sp = getservbyname(service, "tcp");
XX		if (sp == NULL)  {
XX			user_errlist[0]="service unknown";
XX			errno=255;
XX			return(-1);
XX		}
XX		sin.sin_port = sp->s_port;
XX	} else {
XX		/* Lets try to figure out something better... Ok? */
XX
XX		sin.sin_port = htons(atoi(service+1));
XX	}
XX
XX	hp = gethostbyname(host);
XX	if(hp==NULL) {
XX			errno=65;
XX			return(-1);
XX	}
XX	bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
XX	sin.sin_family = hp->h_addrtype;
XX	s = socket(AF_INET, SOCK_STREAM, 0);
XX	if (s < 0) 
XX		return(-1);
XX
XX	if (connect(s, &sin, sizeof(sin)) < 0) 
XX		return(-1);
XX	
XX
XX	return (s);
XX}
XX
XX/* Give them users the ability to choose what they wish to block! */
XX
XXaddfd(x)
XXint x;
XX{
XX	naddfd(netblk.nmask,x);
XX}
XXdelfd(x)
XXint x;
XX{
XX	ndelfd(netblk.nmask,x);
XX}
XXinitfd()
XX{
XX	netblk.nmask[0]=0;
XX	netblk.nmask[1]=0;
XX}
XX
XX/*
XXblock:  Blocks until their is something in the Que waiting
XX	to be read in. Remembers old stuff and goes in a
XX	round robin mannor of handling stuff on sockets.
XX	This means that if the user reads from a socket
XX	that I have not returned but will it a little
XX	while, this program will be lying!  In general,
XX	the use of isignal() can over come many if not
XX	all of these problems. Infact,  block might not
XX	even be needed anymore.  I sure never use it.
XX*/
XX
XXblock()
XX{
XX	static          long flags[2] ;
XX	static int first=1;
XX	int             n;
XX
XX	
XX	if(first) {
XX		flags[0]=0;
XX		flags[1]=0;
XX		first=0;
XX	}
XX
XX	if (!flags[0] || !flags[1]) {
XX		flags[0] = netblk.nmask[0];
XX		flags[1] = netblk.nmask[1];
XX		select(64, flags, 0, 0, 0);
XX	}
XX	for (n = 0; n < 64; n++)
XX		if (nisset(flags,n)) {
XX			naddfd(flags,n);
XX			return (n);
XX		}
XX	return (-1);
XX
XX}
SHAR_EOF
if test 4772 -ne "`wc -c basic.c`"
then
echo shar: error transmitting basic.c '(should have been 4772 characters)'
fi
echo shar: extracting ident.c '(1251 characters)'
sed 's/^XX//' << \SHAR_EOF > ident.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: ident.c,v 1.1 87/04/15 21:29:14 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/ident.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:29:14 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	ident.c,v $
XX * Revision 1.1  87/04/15  21:29:14  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XX
XX#include <pwd.h>
XX
XX/*
XXwhoami:  Returns a string of who the caller is in the
XX	form name@machine where machine is in the
XX	form returned by gethostname.
XX
XX*/
XXchar *hostname()
XX{
XX	static char buff[255];
XX
XX	gethostname(buff,255);
XX
XX	return(buff);
XX}
XX
XXchar *whoami()
XX{
XX	static char buff[64];
XX	struct passwd *pass;
XX
XX	pass=getpwent();
XX
XX	sprintf(buff,"%s@%s",pass->pw_name,hostname());
XX
XX	return(buff);
XX}
SHAR_EOF
if test 1251 -ne "`wc -c ident.c`"
then
echo shar: error transmitting ident.c '(should have been 1251 characters)'
fi
echo shar: extracting isignal.c '(1627 characters)'
sed 's/^XX//' << \SHAR_EOF > isignal.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: isignal.c,v 1.1 87/04/15 21:29:17 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/isignal.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:29:17 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	isignal.c,v $
XX * Revision 1.1  87/04/15  21:29:17  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XX
XX#include "net.h"
XX
XX/*
XX * Here we go... the IOSIG handler.  If this is called, we assume we got a
XX * IOSIG signal and something is coming down one of the pipes.  Only testing
XX * will prove if it is otherwise 
XX */
XX
XXiosighand()
XX{
XX
XX	static          int flags[2];
XX	int             n;
XX
XX	flags[0] = netblk.imask[0];
XX	flags[1] = netblk.imask[1];
XX
XX	select(64, flags, 0, 0, 0);
XX
XX	for (n = 0; n < 64; n++)
XX		if (nisset(flags,n))
XX			(netblk.protab[n]) (n);
XX}
XX
XXisignal(x, proc)
XX	int             x;
XX	int             (*proc) ();
XX{
XX	if (proc) {
XX
XX		naddfd(netblk.imask, x);
XX
XX		fcntl(x, F_SETFL, FASYNC);
XX
XX#ifndef SIGIO
XX#define SIGIO SIGPOLL
XX#endif NSIG
XX
XX		signal(SIGIO, iosighand);
XX
XX		netblk.protab[x] = proc;
XX
XX	} else {
XX		ndelfd(netblk.imask, x);
XX		fcntl(x, F_SETFL, 0);
XX	}
XX}
SHAR_EOF
if test 1627 -ne "`wc -c isignal.c`"
then
echo shar: error transmitting isignal.c '(should have been 1627 characters)'
fi
echo shar: extracting openpty.c '(2166 characters)'
sed 's/^XX//' << \SHAR_EOF > openpty.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: openpty.c,v 1.1 87/04/15 21:29:20 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/openpty.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:29:20 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	openpty.c,v $
XX * Revision 1.1  87/04/15  21:29:20  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XX
XX#include "netw.h"
XX#include "openpty.h"
XX#include <sys/ioctl.h>
XX
XX_loadtty(cond)
XXTCOND *cond;
XX{
XX        ioctl(0, TIOCGETP, (char *) &cond->sgttyb);
XX        ioctl(0, TIOCGETC, (char *) &cond->tchars);
XX        ioctl(0, TIOCGLTC, (char *) &cond->ltchars);
XX        ioctl(0, TIOCGETD, (char *) &cond->l);
XX        ioctl(0, TIOCLGET, (char *) &cond->lb);
XX}
XX
XXsettty(cond)
XXTCOND cond;
XX{
XX        ioctl(0, TIOCSETP, (char *) &cond.sgttyb);
XX        ioctl(0, TIOCSETC, (char *) &cond.tchars);
XX        ioctl(0, TIOCSLTC, (char *) &cond.ltchars);
XX        ioctl(0, TIOCSETD, (char *) &cond.l);
XX        ioctl(0, TIOCLSET, (char *) &cond.lb);
XX}
XX
XX/* 
XXopenpty:  
XX	executes a function with a pty between the two sides.
XX	It works very much like popen() except the process
XX	is on a completly seperate tty.  The returned
XX	file discripter works exactly like a two way
XX	socket
XX*/
XX	
XXopenpty(cond,task)
XXTCOND cond;
XX	int             (*task) ();
XX{
XX
XX	struct ptydesc  proc;
XX	int t;
XX
XX	if (_openpty(&proc) == -1)
XX		return (-1);
XX
XX
XX	if (fork()) {
XX		close(proc.pt_tfd);
XX		return (proc.pt_pfd);
XX	}
XX
XX	t = open("/dev/tty", 2);
XX
XX	if (t >= 0) {
XX		ioctl(t, TIOCNOTTY, 0);
XX		close(t);
XX	}
XX	dup2(proc.pt_tfd, 0);
XX	dup2(proc.pt_tfd, 1);
XX	dup2(proc.pt_tfd, 2);
XX
XX	for (t = 3; t < 64; t++)
XX		(void) close(t);
XX
XX	settty(cond);
XX
XX	(task) (); 
XX	exit(0);
XX}
SHAR_EOF
if test 2166 -ne "`wc -c openpty.c`"
then
echo shar: error transmitting openpty.c '(should have been 2166 characters)'
fi
echo shar: extracting perror.c '(1076 characters)'
sed 's/^XX//' << \SHAR_EOF > perror.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: perror.c,v 1.1 87/04/15 21:29:26 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/perror.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:29:26 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	perror.c,v $
XX * Revision 1.1  87/04/15  21:29:26  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XXextern char *sys_errlist[];
XX
XXchar *user_errlist[255];
XX
XXextern int errno;
XX
XXperror(s)
XXchar *s;
XX{
XX	if(errno<255) 
XX		printf("%s: %s\n",s,sys_errlist[errno]);
XX	 else 
XX		printf("%s: %s\n",s,user_errlist[errno-255]);
XX}
SHAR_EOF
if test 1076 -ne "`wc -c perror.c`"
then
echo shar: error transmitting perror.c '(should have been 1076 characters)'
fi
echo shar: extracting net.h '(750 characters)'
sed 's/^XX//' << \SHAR_EOF > net.h
XX/*
XX * $Header: net.h,v 1.1 87/04/15 21:29:42 josh Exp $
XX *
XX * $Log:	net.h,v $
XX * Revision 1.1  87/04/15  21:29:42  josh
XX * Initial revision
XX * 
XX */
XX
XX
XX#include <sys/types.h>
XX#include <sys/socket.h>
XX#include <netinet/in.h>
XX#include <netdb.h>
XX#include <stdio.h>
XX#include <signal.h>
XX#include <fcntl.h>
XX
XXstruct {
XX	int imask[2],nmask[2];
XX	/* imask: mask of pipes that are interupt handled */
XX	/* nmask: mask of pipes handled by the user */
XX
XX	int (*protab[64])();
XX	/* protab: The table of processes that handle pipes */
XX
XX	} _netblk;
XX
XX#define netblk _netblk
XX
XX#define MYPORT	3000
XX
XX
XX#define naddfd(x,y)  (x[y>>5] |=  (1<< (y>31 ? y-32 : y)))
XX#define ndelfd(x,y)  (x[y>>5] &= ~(1<< (y>31 ? y-32 : y)))
XX#define nisset(x,y)  (x[y>>5] &   (1<< (y>31 ? y-32 : y)))
SHAR_EOF
if test 750 -ne "`wc -c net.h`"
then
echo shar: error transmitting net.h '(should have been 750 characters)'
fi
echo shar: extracting netw.h '(517 characters)'
sed 's/^XX//' << \SHAR_EOF > netw.h
XX/*
XX * $Header: netw.h,v 1.1 87/04/15 21:29:45 josh Exp $
XX *
XX * $Log:	netw.h,v $
XX * Revision 1.1  87/04/15  21:29:45  josh
XX * Initial revision
XX * 
XX */
XX
XX
XX#include <sys/ioctl.h>
XX
XXtypedef struct {
XX        struct sgttyb   sgttyb;
XX        struct tchars   tchars;
XX        struct ltchars  ltchars;
XX        int             l, lb;
XX	} TCOND;
XX
XX#define loadtty(x) _loadtty(&x)
XX
XX#define stty(x,y,z) _stty(&x,y,z)
XX
XX#define COOKED 0
XX#define BAUD 1
XX
XX#ifndef FALSE
XX#define FALSE 0
XX#endif FALSE
XX
XX#ifndef TRUE
XX#define TRUE 1
XX#endif TRUE
SHAR_EOF
if test 517 -ne "`wc -c netw.h`"
then
echo shar: error transmitting netw.h '(should have been 517 characters)'
fi
echo shar: extracting tty.c '(1627 characters)'
sed 's/^XX//' << \SHAR_EOF > tty.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: tty.c,v 1.1 87/04/15 21:29:36 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/tty.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:29:36 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	tty.c,v $
XX * Revision 1.1  87/04/15  21:29:36  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XX
XX#include "netw.h"
XX
XX_stty(object, change, status)
XX	TCOND          *object;
XX	int             change, status;
XX{
XX	switch (change) {
XX	case COOKED:		/* 0x0 */
XX		object->sgttyb.sg_flags &= ~RAW;
XX		object->sgttyb.sg_flags &= ~CBREAK;
XX		break;
XX	case CBREAK:		/* 0x2 */
XX		object->sgttyb.sg_flags |= CBREAK;
XX		break;
XX	case LCASE:		/* 0x4 */
XX		if (status)
XX			object->sgttyb.sg_flags |= LCASE;
XX		else
XX			object->sgttyb.sg_flags &= ~LCASE;
XX		break;
XX	case RAW:		/* 0x20 */
XX		object->sgttyb.sg_flags |= RAW;
XX		break;
XX	case ECHO:		/* 0x8 */
XX		if (status)
XX			object->sgttyb.sg_flags |= ECHO;
XX		else
XX			object->sgttyb.sg_flags &= ~ECHO;
XX		break;
XX	case BAUD:		/* 0x1 */
XX		object->sgttyb.sg_ispeed = status;
XX		object->sgttyb.sg_ospeed = status;
XX		break;
XX	default:
XX		return(-1);
XX		break;
XX	}
XX}
SHAR_EOF
if test 1627 -ne "`wc -c tty.c`"
then
echo shar: error transmitting tty.c '(should have been 1627 characters)'
fi
echo shar: extracting Makefile '(1359 characters)'
sed 's/^XX//' << \SHAR_EOF > Makefile
XXCFLAGS        = -O
XX
XXDEST	      = /usr/local/lib
XX
XXMDEST	      = /usr/man/man3
XX
XXEXTHDRS	      = /usr/include/fcntl.h 
XX
XXHDRS	      = net.h \
XX		netw.h \
XX		openpty.h
XX
XXLIBRARY	      = libnet.a
XX
XXMAKEFILE      = Makefile
XX
XXOBJS	      = basic.o \
XX		ident.o \
XX		isignal.o \
XX		openpty.o \
XX		perror.o \
XX		proutines.o \
XX		tty.o \
XX		utmp.o
XX
XXPRINT	      = imprint -O -2
XX
XXSRCS	      = basic.c \
XX		ident.c \
XX		isignal.c \
XX		openpty.c \
XX		perror.c \
XX		proutines.c \
XX		tty.c \
XX		utmp.c
XX
XX
XX.c.o:
XX	$(CC) $(CFLAGS) -c $<
XX
XXall:		$(LIBRARY)
XX
XX$(LIBRARY):	$(OBJS)
XX		@echo -n "Loading $(LIBRARY) ... "
XX		@ar cru $(LIBRARY) $(OBJS)
XX		@ranlib $(LIBRARY)
XX		@echo "done"
XX
XXclean:		
XX		@rm -f $(OBJS) libnet.a
XX
XXdepend:;	@mkmf -f $(MAKEFILE) LIBRARY=$(LIBRARY) DEST=$(DEST)
XX
XXextract:;	@ar xo $(DEST)/$(LIBRARY)
XX		@rm -f __.SYMDEF
XX
XXindex:;		@ctags -wx $(HDRS) $(SRCS)
XX
XXinstall:	$(LIBRARY)
XX		@echo Installing $(LIBRARY) in $(DEST)
XX		install $(LIBRARY) $(DEST)
XX		ranlib $(DEST)/$(LIBRARY)
XX		@echo Copying the manual page to ${MDEST}
XX		cp netw.3 ${MDEST}
XX		@echo Copying the header file
XX		cp netw.h /usr/include
XX
XXlibrary:        $(LIBRARY)
XX
XXprint:;		@$(PRINT) $(HDRS) $(SRCS)
XX
XXtags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
XX
XXupdate:         $(DEST)/$(LIBRARY)
XX
XX$(DEST)/$(LIBRARY): $(SRCS) $(HDRS) $(EXTHDRS)
XX		@-ar xo $(DEST)/$(LIBRARY)
XX		@make -f $(MAKEFILE) DEST=$(DEST) install clean
XX###
SHAR_EOF
if test 1359 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 1359 characters)'
fi
echo shar: creating directory examples
mkdir examples
cd examples
echo shar: extracting Makefile '(583 characters)'
sed 's/^XX//' << \SHAR_EOF > Makefile
XXCFLAGS =	-g
XX
XXLIBS	=	../libnet.a
XX
XXall: server client login2 test1 test2 ptest
XX
XXserver: server.o getopt.o
XX	${CC} ${CFLAGS} -o server server.o getopt.o ${LIBS}
XX
XXclient: client.o getopt.o
XX	${CC} ${CFLAGS} -o client client.o getopt.o ${LIBS}
XX
XXlogin2:login.o
XX	${CC} ${CFLAGS} -o login2 login.o ${LIBS}
XX
XXtest1:test1.o
XX	${CC} ${CFLAGS} -o test1 test1.o ${LIBS}
XX
XXtest2:test2.o
XX	${CC} ${CFLAGS} -o test2 test2.o ${LIBS}
XX
XXptest:ptest.o
XX	${CC} ${CFLAGS} -o ptest ptest.o ${LIBS}
XX
XXgetopt.o:getopt.c
XX	${CC} ${CFLAGS} -DVMUNIX -c getopt.c
XX
XXclean:
XX	@rm -f *.o server client login2 test1 test2 ptest
SHAR_EOF
if test 583 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 583 characters)'
fi
echo shar: extracting README '(1341 characters)'
sed 's/^XX//' << \SHAR_EOF > README
XX
XXSamples:
XX	login.c  -  opens a pty and executes a /bin/login in it.
XX
XX	test1.c/test2.c - Establishes a basic connection between two points
XX		Very simple
XX
XX	client.c/server.c - Complicated example showing
XX		a server maintaining multiple connections and
XX		a client that connects to it.
XX
XX	ptest.c - Test the modified perror routine.
XX
XX
XXIndex of function usage:
XX
XXFUNCTION        FILE                    ROUTINE     LINE
XX----------------------------------------------------------
XXaddfd()		client.c		do_prog	    63  65
XX		server.c		do_prog	    75  84
XX
XXanswer()	server.c		do_prog	    80
XX
XXattach()	server.c		do_prog	    64
XX		test1.c			main	    7
XX
XXblock()		client.c		do_prog	    68
XX		server.c		do_prog	    78
XX
XXclrutmp()	login.c			gork	    20
XX
XXdelfd()		server.c		do_prog	    93
XX
XXhostname()	ptest.c			main	    9
XX		test2.c			main	    4
XX
XXinitfd()	client.c		do_prog	    61
XX		server.c		do_prog	    73
XX
XXisignal()	login.c			main	    55
XX
XXloadtty() 	login.c			--	    46
XX
XXopenpty()	login.c			main	    48
XX
XXphone()		client.c		do_prog	    57  59
XX		ptest.c			main	    9  13
XX		test2.c			main	    4
XX
XXpkill()		server.c		do_prog	    71  95
XX		server.c		exiter	    18
XX		test1.c			main	    12  13
XX		test2.c			main	    7
XX
XXstty()		login.c			main	    50  51  64  65
XX
XXuseport()	client.c		do_prog	    57  59
XX		server.c		do_prog	    64
XX		test1.c			main	    7
XX		test2.c			main	    4
SHAR_EOF
if test 1341 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 1341 characters)'
fi
echo shar: extracting client.c '(1319 characters)'
sed 's/^XX//' << \SHAR_EOF > client.c
XX#ifndef lint
XXstatic char     rcsid[] = "$Header$";
XX#endif
XX
XX#include <stdio.h>
XX#include <ctype.h>
XX
XXtypedef enum { false = 0, true = 1} bool; 
XX
XXchar           *progname;
XX
XXint             p_val;
XXchar           *h_string;
XXmain (argc, argv)
XX	int             argc;
XX	char           *argv[];
XX{
XX	extern int      opterr;
XX	extern char    *optarg;
XX	int             c;
XX	opterr = 1;
XX	progname = argv[0];
XX
XX	p_val = 2500;
XX	h_string = (char *) 0;
XX
XX	while ((c = getopt (argc, argv, "p:h:")) != EOF)
XX		switch (c)
XX		{
XX		case 'p':
XX			p_val = atoi (optarg);
XX			break;
XX		case 'h':
XX			h_string = optarg;
XX			break;
XX		case '?':
XX			usage ();
XX			break;
XX		}
XX
XX	do_prog ();
XX	exit (0);
XX}
XXusage ()
XX{
XX	fprintf (stderr, "Usage: %s [ -p port ] [ -h host ]\n", progname);
XX	exit (1);
XX}
XXdo_prog ()
XX{
XX	int             p,
XX		  	n,
XX	                c;
XX	char            buff[255];
XX	if (h_string)
XX		p = phone (useport (p_val), h_string);
XX	else
XX		p = phone (useport (p_val), hostname());
XX
XX	initfd ();
XX
XX	addfd (0);
XX
XX	addfd (p);
XX
XX	while (1)
XX	{
XX		c = block ();
XX
XX		if (c == 0)
XX		{
XX			if (gets (buff) == NULL)
XX				goto leave;
XX			write (p, buff, strlen (buff));
XX		}
XX		else
XX		{
XX			n = read (c, buff, 255);
XX			if (n)
XX				printf ("Strange... the daemon talked back\n");
XX			else
XX			{
XX				printf ("Daemon died\n");
XX				exit (0);
XX			}
XX		}
XX	}
XXleave:
XX	printf ("Quiting...\n");
XX}
SHAR_EOF
if test 1319 -ne "`wc -c client.c`"
then
echo shar: error transmitting client.c '(should have been 1319 characters)'
fi
echo shar: extracting getopt.c '(1262 characters)'
sed 's/^XX//' << \SHAR_EOF > getopt.c
XX/*	getopt.c	1.1	85/05/30	*/
XX /*  getopt.c 1.1  10/26/79  11:50:14  */
XX#include	<stdio.h>
XX#ifdef VMUNIX
XX#define	strchr	index
XX#endif
XX#define ERR(s, c)	if(opterr){ fputs (argv[0], stderr); fputs (s, stderr); fputc (c, stderr); fputc ('\n', stderr); }
XX
XXint     opterr = 1;
XXint     optind = 1;
XXint     optopt;
XXchar   *optarg;
XXchar   *strchr ();
XX
XXint
XX        getopt (argc, argv, opts)
XXchar  **argv,
XX       *opts;
XX{
XX    static int  sp = 1;
XX    register    c;
XX    register char  *cp;
XX
XX    if (sp == 1)
XX	if (optind >= argc ||
XX		argv[optind][0] != '-' || argv[optind][1] == '\0')
XX	    return EOF;
XX	else
XX	    if (strcmp (argv[optind], "--") == NULL) {
XX		optind++;
XX		return EOF;
XX	    }
XX    optopt = c = argv[optind][sp];
XX    if (c == ':' || (cp = strchr (opts, c)) == NULL) {
XX	ERR (": illegal option -- ", c);
XX	if (argv[optind][++sp] == '\0') {
XX	    optind++;
XX	    sp = 1;
XX	}
XX	return '?';
XX    }
XX    if (*++cp == ':') {
XX	if (argv[optind][sp + 1] != '\0')
XX	    optarg = &argv[optind++][sp + 1];
XX	else
XX	    if (++optind >= argc) {
XX		ERR (": option requires an argument -- ", c);
XX		sp = 1;
XX		return '?';
XX	    }
XX	    else
XX		optarg = argv[optind++];
XX	sp = 1;
XX    }
XX    else {
XX	if (argv[optind][++sp] == '\0') {
XX	    sp = 1;
XX	    optind++;
XX	}
XX	optarg = NULL;
XX    }
XX    return c;
XX}
SHAR_EOF
if test 1262 -ne "`wc -c getopt.c`"
then
echo shar: error transmitting getopt.c '(should have been 1262 characters)'
fi
echo shar: extracting login.c '(2128 characters)'
sed 's/^XX//' << \SHAR_EOF > login.c
XX#include <sys/ioctl.h>
XX#include <stdio.h>
XX#include "../netw.h"
XX/*
XX * Gork is the routine that shows up on the other end of the pty.  As far as
XX * it can tell, it is on its own terminal.  In this example,  I call
XX * /bin/login so that I can log in.  Note:  On a machine where the /etc/utmp
XX * file is locked up,  this sometimes leaves strange entries when you type
XX * w(1) after to log back out. Don't worry,  they will go away after reboot
XX * or you can use my rename(l) package to clear out the entry. 
XX */
XX
XXchar          **env;
XXgork ()
XX{
XX	char           *buf[2];
XX	buf[0] = "login";
XX	buf[1] = 0;
XX
XX	if (vfork () == 0)
XX		execve ("/bin/login", buf, 0);
XX
XX	printf ("Connected.\n");
XX
XX	(void) wait (0);
XX
XX	/* clrutmp has no effect on machines where /etc/utmp is locked up */
XX	clrutmp ();
XX
XX	printf ("\nDisconnected...\n");
XX}
XXint             s;
XX/* Read from the keyboard */
XXrread (fd)
XX	int             fd;
XX{
XX	int             n;
XX	char            buff[255];
XX	n = read (fd, buff, 255);
XX	write (s, buff, n);
XX}
XXmain (argc, argv, argp)
XX	int             argc;
XX	char           *argv[];
XXchar           *argp[];
XX{
XX	TCOND           tdef;
XX
XX	char            buff[255];
XX	int             n;
XX	struct sgttyb   b,
XX	                sbuf;
XX	env = argp;
XX
XX	loadtty (tdef);				 /* Load my terminal
XX						  * configuration */
XX
XX	s = openpty (tdef, gork);		 /* Put the function gork on
XX						  * the other end of the file
XX						  * descripter using the
XX						  * terminal defined in tdef. */
XX
XX	stty (tdef, RAW, 0);			 /* Change the definition to
XX						  * be raw */
XX	stty (tdef, ECHO, FALSE);		 /* Have it not echo */
XX
XX	settty (tdef);				 /* Set my terminal to tdef */
XX
XX	isignal (0, rread);			 /* Set rread to be called
XX						  * when something comes in
XX						  * on the keyboard */
XX
XX	while (1)
XX	{
XX		n = read (s, buff, 255);	 /* Read from the keyboard */
XX		if (n == EOF)			 /* Has the other end closed? */
XX			break;			 /* Guess so */
XX		write (1, buff, n);		 /* Write out whats been
XX						  * gotten from the pty */
XX	}
XX
XX	stty (tdef, COOKED, 0);			 /* Make tdef cooked again */
XX	stty (tdef, ECHO, TRUE);		 /* Turn echo back on */
XX
XX	settty (tdef);				 /* Set it */
XX}
SHAR_EOF
if test 2128 -ne "`wc -c login.c`"
then
echo shar: error transmitting login.c '(should have been 2128 characters)'
fi
echo shar: extracting ptest.c '(282 characters)'
sed 's/^XX//' << \SHAR_EOF > ptest.c
XXmain()
XX{
XX	int s;
XX
XX
XX	printf("You should see two sets of duplicate lines\n\n");
XX
XX	printf("phone: service unknown\n");
XX	s=phone("stuff_xyzzy",hostname());
XX
XX	if(s<0) perror("phone");
XX
XX	s=phone("ftp","non_existant");
XX
XX	printf("phone: Host is unreachable\n");
XX	if(s<0) perror("phone");
XX}
SHAR_EOF
if test 282 -ne "`wc -c ptest.c`"
then
echo shar: error transmitting ptest.c '(should have been 282 characters)'
fi
echo shar: extracting server.c '(1350 characters)'
sed 's/^XX//' << \SHAR_EOF > server.c
XX#ifndef lint
XXstatic char     rcsid[] = "$Header$";
XX#endif
XX
XX#include <stdio.h>
XX#include <ctype.h>
XX#include <signal.h>
XX
XXtypedef enum { false = 0, true = 1} bool;
XX
XXchar           *progname;
XX
XXint             p_val,s;
XX
XXexiter()
XX{
XX	fprintf(stderr,"Shutting down...\n");
XX	pkill(s);
XX	exit(0);
XX}
XX
XXmain(argc, argv)
XX	int             argc;
XX	char           *argv[];
XX{
XX	extern int      opterr;
XX	extern char    *optarg;
XX	int             c;
XX
XX	opterr = 1;
XX	progname = argv[0];
XX
XX	p_val = 2500;
XX
XX	while ((c = getopt(argc, argv, "p:")) != EOF)
XX		switch (c) {
XX		case 'p':
XX			p_val = atoi(optarg);
XX			break;
XX		case '?':
XX			usage();
XX			break;
XX		}
XX
XX	signal(SIGHUP,exiter);
XX	signal(SIGINT,exiter);
XX	signal(SIGQUIT,exiter);
XX	signal(SIGTERM,exiter);
XX
XX	do_prog();
XX	exit(0);
XX}
XX
XXusage()
XX{
XX	fprintf(stderr, "Usage: %s [ -p port ] \n", progname);
XX	exit(1);
XX}
XXdo_prog()
XX{
XX	int c,q,n;
XX	char buff[1024];
XX
XX	s=attach(useport(p_val));
XX
XX	if(s==-1) {
XX		perror("attach");
XX		exit(-1);
XX	}
XX
XX	pkill(0);
XX
XX	initfd();
XX
XX	addfd(s);
XX
XX	while(1) {
XX		c=block();
XX		if(c==s) {
XX			q=answer(s);
XX			if(q==-1) {
XX				perror("answer");
XX			} else {
XX				addfd(q);
XX				printf("Conenction accepted: %d\n",q);
XX			}
XX		} else {
XX			n=read(c,buff,sizeof(buff)-1);
XX			if(n) {
XX				buff[n]=0;
XX				printf("%d: %s\n",c,buff);
XX			} else {
XX				delfd(c);
XX				printf("File descriptor closed: %d\n",c);
XX				pkill(c);
XX			}
XX		}
XX	}
XX}
SHAR_EOF
if test 1350 -ne "`wc -c server.c`"
then
echo shar: error transmitting server.c '(should have been 1350 characters)'
fi
echo shar: extracting test1.c '(131 characters)'
sed 's/^XX//' << \SHAR_EOF > test1.c
XXmain()
XX{
XX	int s,q;
XX
XX	printf("attach\n");
XX
XX	s=attach(useport(2501));
XX
XX	printf("accept\n");
XX	q=answer(s);
XX
XX	pkill(q);
XX	pkill(s);
XX}
XX
XX
SHAR_EOF
if test 131 -ne "`wc -c test1.c`"
then
echo shar: error transmitting test1.c '(should have been 131 characters)'
fi
echo shar: extracting test2.c '(89 characters)'
sed 's/^XX//' << \SHAR_EOF > test2.c
XXmain() { 
XX	int s;
XX
XX	s=phone(useport(2501),hostname());
XX	printf("Done\n");
XX
XX	pkill(s);
XX}
XX
SHAR_EOF
if test 89 -ne "`wc -c test2.c`"
then
echo shar: error transmitting test2.c '(should have been 89 characters)'
fi
echo shar: done with directory examples
cd ..
echo shar: extracting netw.3 '(6725 characters)'
sed 's/^XX//' << \SHAR_EOF > netw.3
XX.\" @(#)netw.3 1.1 87/4/15 SMI; from UCB 4.2 
XX.TH NETW L  "14 March 1987" 
XX.SH NAME 
XXpkill,addfd, answer, attach, block, useport, delfd, initfd, myport, phone, clrutmp, setutmp, isignal, openpty, loadtty,  settty, whoami, hostname, stty \- Some Nice Network/IO Functions 
XX.SH SYNOPSIS 
XX.nf
XX.B #include <netw.h>
XX.LP
XX.B int pkill(fd)
XX.B int fd;
XX.LP
XX.B int attach(s)
XX.B char *s;
XX.LP
XX.B int answer(s)
XX.B int s;
XX.LP
XX.B int phone(service,host)
XX.B char *service,*host;
XX.LP
XX.B char *useport(port)
XX.B int port
XX.LP
XX.B char *myport()
XX.LP
XX.B int answer(s)
XX.B int s;
XX.LP
XX.B initfd()
XX.LP
XX.B addfd(x)
XX.B int x;
XX.LP
XX.B delfd(x)
XX.B int x;
XX.LP
XX.B int block()
XX.LP
XX.B char *whoami()
XX.LP
XX.B setutmp(string)
XX.B char *string;
XX.LP
XX.B clrutmp()
XX.LP
XX.B isignal(fd.proc)
XX.B int fd;
XX.B int (*proc)();
XX.LP
XX.B loadtty(cond)
XX.B TCOND cond;
XX.LP
XX.B settty(cond)
XX.B TCOND cond;
XX.LP
XX.B openpty(cond,task)
XX.B TCOND cond;
XX.B int (*task)();
XX.LP
XX.B char *hostname();
XX.LP
XX.B stty (tcond,change,value)
XX.B TCOND tcond;
XX.B int change,value;
XX.SH DESCRIPTION
XX.LP
XX.I pkill
XXis used to close down ANY kind of connection.  Much like
XX.I close
XXexcept that it is more exacting. Still, when closing a
XXa socket setup by
XX.I attach
XXit might not work correctly.
XX.LP
XX.I Attach
XXis used to setup a listening post at a socket location.  The string
XXpassed to 
XX.I attach
XXcontains the service the server is going to be.  It
XXwill error if the service passed to it does not exist or if the process
XXcannot use the port.  
XX.I Attach
XXreturns the file descripter to the listening post.
XX
XX   tmp = attach("game");
XX
XXNormally this function is used only by a server process.
XX
XX.LP
XX.I answer
XXaccepts a 
XX.I phone
XXfrom a person.
XX
XX	s = attach(myport(),hostname())
XX
XX	d = answer(s)
XX
XX.LP
XX.I phone
XXis the routine used to connect to one of the services(5) that the
XXprogram has access to.  The first argument is the service that
XXit is connecting to.  The second argument is the machine on which
XXthe other process (the one it is connecting too) lives.
XXIt returns a file descripter that can be
XXused for commincation between the two processes.
XX
XX   x = phone("game","sol");
XX
XXNormally this function is used only by the client process.
XX
XX.LP
XX.I useport
XXand
XX.I myport
XXwill let
XX.I phone
XXand
XX.I attach
XXconnect to a specific port instead of them going through the
XX.I services(5)
XXdatabase like they normally do.
XX
XX	x = attach(useport(3000));
XX
XX	y = phone(useport(3000));
XX
XX	z = answer(myport());
XX
XX.I myport
XXis special because it uses your uid to calculate which port
XXit is going to use.  This is useful if several students are using
XXsockets and you do not wish them to overlap.  The port a person
XXuses is getuid()+OFFSET.  OFFSET is defined at compile time.
XX.I WARNING: 
XXunless you are root, you cannot access any ports less then 1024.
XX.LP
XX.I answer
XXis used by the server to answer a phone call by the client.  The 
XXargument is the file descripter returned by
XX.I attach.
XXIt returns a socket that can be used for two directional
XXcommunication between
XXthe two processes.  It is the counter-point to phone.  
XX
XX   y = answer(tmp);
XX
XX.LP
XX.I initfd, addfd, delfd
XXare the helpful functions that are used to control how
XX.I block
XXreacts to external stimulus.  
XX.I initfd
XXshould be called first to initalize the common variables.
XX.I addfd
XXis used to add a file descripter to the descripters that
XX.I block 
XXreacts to.
XX.I delfd
XXwill delete the file descripter that is passed to 
XX.I delfd
XXfrom the descripters that
XX.I block
XXreacts to.
XX
XX	initfd();
XX
XX	addfd(s);
XX
XX	delfd(s);
XX
XX.LP
XX.I block
XXis the bottom routine that returns which file descripter has data
XXcoming through it.  It
XX.I only
XXchecks the file descripters that are told to it using
XX.I addfd.
XXIt returns the file descripter that is currently making noise.
XXAlso, 
XX.I block
XXacts in a round robbin type mannor.  If a new message comes
XXin along a file descripter,  that descripter will not be returned
XXtill all the descripters that previously have had messages
XXsent down them have been handled.  Then and only then will
XXit start again and look for new messages on sockets.  
XX.I block
XXwill block if there are no messages on any of the file descripters
XXthat it knows about.
XX
XX	c=block();
XX
XX.LP
XX.I whoami
XXreturns a pointer to a string that contains who the caller is in the
XXform of "name@hostname".  This will even work if the process owner does
XXnot have a entry in the utmp file.
XX
XX	name = whoami();
XX.LP
XX.I setutmp
XXsets a utmp entry for the terminal.  On most systems this call is
XXnot allowed except by the super-user and will return a error (<0). 
XXThe string passed is used as the host that is shown when
XXthe command 
XX.I who(1)
XXis called. 
XX.LP
XX.I clrutmp
XXwill clear the current utmp entry.  The restrictions are the
XXsame as in
XX.I setutmp.
XX.LP
XX.I isignal
XXallows you to set a function to handle a pipe in the same
XXway what 
XX.I signal(3)
XXallows you to set a function to handle a signal.  The function
XXis called with the file descripter as the first argument.
XX.LP
XX.I openpty
XXallows easy use of a pseudo terminal(
XX.I pty(4)
XX)  withen a program.  The first argument is a terminal
XXcondition as returned by
XX.I loadtty.  
XXThe second is the function that you wish to
XXcall. It returns a file descripter to the pty.
XX.I (see example below)
XX.LP
XX.I loadtty
XXloads a terminals current settings into the named buffer.  See
XX.I stty(1)
XXfor more details.
XX.LP
XX.I settty
XXsets the current terminal settings from the named buffer. See
XX.I stty(1)
XXfor more details.
XX.LP
XX.I hostname
XXreturns a pointer to a string that contains the hostname.
XX.LP
XX.I stty
XXis a function that can be used to change the current parameters
XXof a TCOND block.  It is very much like
XX.I stty(1)
XXin purpose.
XX.PP
XXIn the following example I use stty ,loadtty,and settty to change
XXmake my terminal stop echoing.
XX
XX	TCOND block;
XX
XX	loadtty(block);
XX	stty(block,ECHO,FALSE);
XX	settty(block);
XX
XX.PP
XXThe values 
XX.I stty
XXunderstands are the following:
XX.nf
XX
XX	options:
XX		COOKED: Make all IO cooked.
XX		CBREAK: Make IO half-baked.
XX		RAW:    Do no IO processing
XX		LCASE:  Change how upper and lowercase is handled
XX		ECHO:   Turn on or off echo.
XX		BAUD:   Set the baud rate.
XX.fi
XX.PP
XXRead the
XX.I stty(1)
XXmanual for more information on what this means.
XX
XX	
XX.SH COMMENTS
XX
XXEvery routine that returns a pointer to a string is really
XXreturning a pointer to a static string within the function.  This
XXmeans that you should not try to free it AND you should copy it
XXelsewhere so that it does not get overwritten.
XX
XX.SH BUGS
XX.PP
XXWhen dealing with sockets created using attach,  there is no
XXgood way to close the socket and sometimes they are left open.
XXLuckly, the system will clear them out in about 30 seconds.
XX.PP
XXAnother problem is that isignal is not triggered when the socket
XXis closed at the other end.  I have not figured out how to handle
XXthis yet.
XX.SH AUTHOR
XXJosh Siegel
SHAR_EOF
if test 6725 -ne "`wc -c netw.3`"
then
echo shar: error transmitting netw.3 '(should have been 6725 characters)'
fi
echo shar: extracting proutines.c '(3948 characters)'
sed 's/^XX//' << \SHAR_EOF > proutines.c
XX/*
XX *	openpty - open a pseudo-terminal
XX *
XX * The first time that the routine is called, the device directory is
XX * searched and a list of all candidate pseudo-terminals is compiled.
XX * Candidates are defined to be those entries in "/dev" whose names
XX * (1) are the same length as PTY_PROTO and (2) start with the
XX * initial string PTY_PREFIX.  Further, the master and slave sides
XX * must both exist.
XX *
XX * openpty() attempts to find an unused pseudo-terminal from the list
XX * of candidates.  If one is found, the master and slave sides are
XX * opened and the file descriptors and names of these two devices are
XX * returned in a "ptydesc" structure.  (The address of this structure
XX * is supplied by the caller.  Zero is returned if openpty() was
XX * successful, -1 is returned if no pty could be found.
XX *
XX *    written by John Bruner <unmvax!unm-la!lanl!cmcl2!seismo!mordor!jdb>
XX */
XX
XX#include <sys/types.h>
XX#include <sys/dir.h>
XX#include <fcntl.h>
XX#include <strings.h>
XX#include "openpty.h"
XX
XX#define	DEV_DIR		"/dev"		/* directory where devices live */
XX#define	PT_INDEX	(sizeof DEV_DIR)	/* location of 'p' in "pty" */
XX
XX#define	PTY_PROTO	"ptyp0"		/* prototype for pty names */
XX#define	PTY_PREFIX	"pty"		/* prefix required for name of pty */
XX
XXstruct ptyinfo {
XX	struct ptyinfo	*pi_next;
XX	char		*pi_pty;
XX	char		*pi_tty;
XX};
XX
XXstatic struct ptyinfo *ptylist;
XX
XXextern char *malloc();
XX
XXstatic char * devname(name)
XXchar *name;
XX{
XX	register char *fullname;
XX
XX	/*
XX	 * Construct the full name of a device in DEV_DIR.  Returns
XX	 * NULL if it failed (because malloc() failed).
XX	 */
XX
XX	fullname = malloc((unsigned)(sizeof DEV_DIR + 1 + strlen(name)));
XX	if (fullname != NULL) {
XX		(void)strcpy(fullname, DEV_DIR);
XX		(void)strcat(fullname, "/");
XX		(void)strcat(fullname, name);
XX	}
XX	return(fullname);
XX}
XX
XXstatic isapty(dp)
XXstruct direct *dp;
XX{
XX	static struct ptyinfo *pi;
XX
XX	/*
XX	 * We don't care about the gory details of the directory entry.
XX	 * Instead, what we really want is an array of pointers to
XX	 * device names (with DEV_DIR prepended).  Therefore, we create
XX	 * this array ourselves and tell scandir() to ignore every
XX	 * directory entry.
XX	 *
XX	 * If malloc() fails, the current directory entry is ignored.
XX	 */
XX
XX	if (pi == NULL &&
XX	    (pi = (struct ptyinfo *)malloc((unsigned)sizeof *pi)) == NULL)
XX		return(0);
XX		
XX	if (strlen(dp->d_name) == sizeof PTY_PROTO - 1 &&
XX	    strncmp(dp->d_name, PTY_PREFIX, sizeof PTY_PREFIX - 1) == 0) {
XX		pi->pi_pty = devname(dp->d_name);
XX		if (pi->pi_pty == NULL)
XX			return(0);
XX		pi->pi_tty = malloc((unsigned)(strlen(pi->pi_pty) + 1));
XX		if (pi->pi_tty == NULL) {
XX			free(pi->pi_pty);
XX			return(0);
XX		}
XX		(void)strcpy(pi->pi_tty, pi->pi_pty);
XX		pi->pi_tty[PT_INDEX] = 't';
XX		if (access(pi->pi_pty, 0) == 0 && access(pi->pi_tty, 0) == 0) {
XX			pi->pi_next = ptylist;
XX			ptylist = pi;
XX			pi = NULL;
XX		} else {
XX			free(pi->pi_pty);
XX			free(pi->pi_tty);
XX		}
XX	}
XX	return(0);
XX}
XX
XX_openpty(pt)
XXstruct ptydesc *pt;
XX{
XX	register struct ptyinfo *pi;
XX	static int fail;
XX	auto struct direct **dirlist;
XX	extern char *re_comp();
XX	extern int alphasort();
XX
XX	/*
XX	 * If scandir() fails or no possible pty's are found, then "fail"
XX	 * is set non-zero.  If "fail" is non-zero then the routine bombs
XX	 * out immediately.  Otherwise, the list of candidates is examined
XX	 * starting with the entry following the last one chosen.
XX	 */
XX
XX	if (fail)
XX		return(-1);
XX
XX	if (!ptylist) {		/* first time */
XX		if (scandir(DEV_DIR, &dirlist, isapty, alphasort) < 0 ||
XX		    ptylist == NULL) {
XX			fail = 1;
XX			return(-1);
XX		}
XX		for (pi=ptylist; pi->pi_next; pi=pi->pi_next)
XX			;
XX		pi->pi_next = ptylist;	/* make the list circular */
XX	}
XX
XX	pi = ptylist;
XX	do {
XX		if ((pt->pt_pfd = open(pi->pi_pty, O_RDWR)) >= 0) {
XX			if ((pt->pt_tfd = open(pi->pi_tty, O_RDWR)) >= 0) {
XX				ptylist = pi->pi_next;
XX				pt->pt_pname = pi->pi_pty;
XX				pt->pt_tname = pi->pi_tty;
XX				return(0);
XX			} else
XX				(void)close(pt->pt_pfd);
XX		}
XX		pi = pi->pi_next;
XX	} while (pi != ptylist);
XX	return(-1);
XX}
XX
SHAR_EOF
if test 3948 -ne "`wc -c proutines.c`"
then
echo shar: error transmitting proutines.c '(should have been 3948 characters)'
fi
echo shar: extracting openpty.h '(466 characters)'
sed 's/^XX//' << \SHAR_EOF > openpty.h
XX/*
XX * $Header: openpty.h,v 1.1 87/04/15 21:29:48 josh Exp $
XX *
XX * $Log:	openpty.h,v $
XX * Revision 1.1  87/04/15  21:29:48  josh
XX * Initial revision
XX * 
XX */
XX
XX
XX/*
XX *	This file defines the "ptydesc" structure which is returned
XX *	by the routine "openpty".
XX */
XX
XXstruct ptydesc {
XX	int		pt_pfd;		/* file descriptor of master side */
XX	int		pt_tfd;		/* file descriptor of slave side */
XX	char		*pt_pname;	/* master device name */
XX	char		*pt_tname;	/* slave device name */
XX};
SHAR_EOF
if test 466 -ne "`wc -c openpty.h`"
then
echo shar: error transmitting openpty.h '(should have been 466 characters)'
fi
echo shar: extracting utmp.c '(2928 characters)'
sed 's/^XX//' << \SHAR_EOF > utmp.c
XX#ifndef lint
XXstatic char *RCSid = "$Header: utmp.c,v 1.1 87/04/15 21:29:39 josh Exp $";
XX#endif
XX
XX/*
XX *------------------------------------------------------------------
XX * Copyright 1987, Josh Siegel
XX * All rights reserved.
XX *
XX * Josh Siegel (siegel@hc.dspo.gov)
XX * Dept of Electrical and Computer Engineering,
XX * University of New Mexico,
XX * Albuquerque , New Mexico
XX * (505) 277-2497
XX *
XX *------------------------------------------------------------------
XX *
XX * $Source: /usr/pcb/josh/other/network/RCS/utmp.c,v $
XX * $Revision: 1.1 $
XX * $Date: 87/04/15 21:29:39 $
XX * $State: Exp $
XX * $Author: josh $
XX * $Locker: josh $
XX *
XX *------------------------------------------------------------------
XX *
XX * $Log:	utmp.c,v $
XX * Revision 1.1  87/04/15  21:29:39  josh
XX * Initial revision
XX * 
XX *
XX *------------------------------------------------------------------
XX */
XX
XX
XX#include <stdio.h>
XX#include <utmp.h>
XX#include <pwd.h>
XX#include <sys/file.h>
XX
XX/*
XX * Allow the user to creat a entry in the utmp file. The problem is that this
XX * shows the normal hack how to really cause problems via /etc/utmp.  I have
XX * a program for the Sun and BSD43 that allows you to edit entries in
XX * /etc/utmp but this is another story 
XX */
XX
XXsetutmp(host)
XX	char            host[];
XX{
XX	struct passwd  *passwd;
XX	struct utmp     utmp;
XX	int             t, f;
XX	char           *p, *ttyname();
XX
XX	/* Get the tty slot in the /etc/utmp file */
XX	t = ttyslot();
XX
XX	if (t == 0)
XX		return (-2);	/* Not on a tty? */
XX
XX	/*
XX	 * We are going to let the user set the host because it can't hurt
XX	 * and I use it for my window managers 
XX	 */
XX
XX	strncpy(utmp.ut_host, host, 8);
XX
XX	/* Set the login time to the current time */
XX
XX	utmp.ut_time = time(0);
XX
XX	/* Lets get a path to the tty device */
XX
XX	p = ttyname(0);
XX
XX	if (p == NULL)
XX		return (-1);	/* No device and a tty slot? weard! */
XX
XX	strcpy(utmp.ut_line, p + 5);
XX
XX	/* Who is the bum we are dealing with */
XX
XX	passwd = getpwuid(getuid());
XX
XX	strcpy(utmp.ut_name, passwd->pw_name);
XX
XX	/* Can I open the utmp file?  On Suns I can */
XX
XX	f = open("/etc/utmp", O_WRONLY);
XX
XX	if (f == -1)
XX		return (-3);	/* Guess your not on a sun or not root */
XX
XX	lseek(f, (long) (t * sizeof(utmp)), 0);	/* Move out to the place */
XX	write(f, (char *) &utmp, sizeof(utmp));	/* Write it */
XX	close(f);		/* Close it */
XX
XX	/* What a nice guy I am :-) */
XX}
XX
XX/*
XX * Clear the entry from the utmp file.  This only clears the entry your 0
XX * descripter is attached to.  Work it out...  Its a hack!
XX */
XX
XXclrutmp()
XX{
XX	int             t, f;
XX	struct utmp     utmp;
XX
XX	t = ttyslot();
XX
XX	if (t == 0)
XX		return (-1);	/* descripter 0/1/2 not on a tty */
XX	bzero((char *) &utmp, sizeof(utmp));
XX	/* I don't trust machines to give me clean stack each time */
XX
XX	f = open("/etc/utmp", O_WRONLY);
XX	if (f < 0)
XX		return (-1);	/* Must not have access to /etc/utmp. */
XX
XX	lseek(f, (long) (t * sizeof(utmp)), 0);
XX	write(f, (char *) &utmp, sizeof(utmp));	/* Clear the entry */
XX	close(f);
XX	return(0);
XX}
SHAR_EOF
if test 2928 -ne "`wc -c utmp.c`"
then
echo shar: error transmitting utmp.c '(should have been 2928 characters)'
fi
echo shar: extracting INSTALL '(398 characters)'
sed 's/^XX//' << \SHAR_EOF > INSTALL
XXTo install:
XX
XX1) Look at the Makefile to make sure I did not install
XX   any trojan horses and to configure as you wish.
XX
XX2) Type "make install" (as root if need be)
XX
XX   If you just type "make" it will make a version of
XX   libnet.a in the current directory.  This is the
XX   configuration the examples/Makefile is setup for.
XX
XX3) Watch the fun.
XX
XX4) Look at the examples in the directory "examples".
XX
XX
XX
SHAR_EOF
if test 398 -ne "`wc -c INSTALL`"
then
echo shar: error transmitting INSTALL '(should have been 398 characters)'
fi
echo shar: done with directory network
cd ..
#	End of shell archive
exit 0
-- 
Josh Siegel		(siegel@hc.dspo.gov)
                        (505) 277-2497  (Home)
		I'm a mathematician, not a programmen? 

guy@gorodish.UUCP (04/16/87)

> It also does not make use of XDR.  This means that
>  transfering data from machine to machine is still
>  ugly.  If only BSD4.3 had XDR....

If you count the "User Contributed Software", 4.3BSD *does* have XDR
*and* Sun RPC; look in "/usr/src/new/sunrpc".

josh@hi.uucp (Josh Siegel ) (04/18/87)

In article <16852@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>> It also does not make use of XDR.  This means that
>>  transfering data from machine to machine is still
>>  ugly.  If only BSD4.3 had XDR....
>
>If you count the "User Contributed Software", 4.3BSD *does* have XDR
>*and* Sun RPC; look in "/usr/src/new/sunrpc".

Great!  This means I can use XDR!

On other points (I got some mail...):

I am not sure how far the source went so if you get
this message and not the source, send me a note so I check
on why not...

Also, I put the following in my code:

 * Copyright 1987, Josh Siegel
 * All rights reserved.

... well.. Thats not true and I am changing the header
in my files. I grant full permission to copy and distribute,
just as long as you DON'T sell it.  (Now I am asking for it..)

choose one of the following and paste it on top of all the files! 
				<<;-)=<-' or    ;-)

Actually,  since in the original posting,  I didn't expressly
allow you to patch my code,  you can't do this....

			--Josh Siegel

--- (Credit to Larry Wall for this humorious copyright notice)

You may copy this software in whole or in part as long as
you don't try to make money off of it or pretend you wrote it. 

--- (Credit to Kurt Zeilenga for this verbose translation)
/*
Copyright 1987 Josh B. Siegel

	This notice and any statement of authorship must be reproduced
	on all copies.  The author does not make any warranty expressed
	or implied, or assumes any liability or responsiblity for the
	use of this software.

	Any distributor of copies of this software shall grant the
	recipient permission for further redistribution as permitted
	by this notice.	 Any distributor must distribute this software
	without any fee or other monetary gains, unless expressed written
	permission is granted by the author.

	This software or its use shall not be: sold, rented, leased,
	traded, or otherwise marketed without the expressed written
	permission of the author.

	Permission is hereby granted to copy, reproduce, redistribute or
	otherwise use this software as long as the conditions above
	are meet.
*/
---
-- 
Josh Siegel		(siegel@hc.dspo.gov)
                        (505) 277-2497  (Home)
		I'm a mathematician, not a programmer!