[comp.sources.amiga] v90i199: netkeys 2.0 - control two amigas via dnet, Part01/02

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (07/07/90)

Submitted-by: sas.UUCP!walker%sas@rti.rti.org (Doug Walker)
Posting-number: Volume 90, Issue 199
Archive-name: comm/dnet/netkeys-2.0/part01

[ uuencoded executables enclosed  ...tad ]

NETKEYS 2.0 is a DNET server that will let you use one mouse and
keyboard to control two Amigas connected via a null modem.  Version
2.0 features the ability to simply move the mouse off one edge of
the screen and onto the other Amiga's screen.  A Software Distillery
project by Doug Walker.

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  channel.h dnet.h dnetlib.c makefile mshow.c netkeys.doc
#   netkeys.h nkutil.c snetkeys.c snetkeys.uu
# Wrapped by tadguy@xanth on Sat Jul  7 11:13:10 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'channel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'channel.h'\"
else
echo shar: Extracting \"'channel.h'\" \(1724 characters\)
sed "s/^X//" >'channel.h' <<'END_OF_FILE'
X
X/*
X *  CHANNEL.H
X *
X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
X *
X *  Channel structures for SCMD_* channel commands.
X */
X
X#ifndef DNET_H
Xtypedef unsigned char ubyte;
Xtypedef unsigned short uword;
Xtypedef unsigned long ulong;
Xtypedef struct MsgPort PORT;
Xtypedef struct IOStdReq IOR;
X#endif
X
X#define CSWITCH struct _CSWITCH
X#define COPEN	struct _COPEN
X#define CCLOSE	struct _CCLOSE
X#define CACKCMD struct _CACKCMD
X#define CEOFCMD struct _CEOFCMD
X#define CIOCTL	struct _CIOCTL
X
XCSWITCH {		/*  SWITCH current data channel */
X    ubyte   chanh;
X    ubyte   chanl;
X};
X
XCOPEN { 		/*  OPEN port on channel	*/
X    ubyte   chanh;
X    ubyte   chanl;
X    ubyte   porth;
X    ubyte   portl;
X    ubyte   error;	/*  error return 0=ok		*/
X    ubyte   pri;
X};
X
XCCLOSE {		/*  CLOSE a channel		*/
X    ubyte   chanh;
X    ubyte   chanl;
X};
X
XCACKCMD {		/*  Acknowledge an open/close	    */
X    ubyte   chanh;
X    ubyte   chanl;
X    ubyte   error;	/*  ERETRY ENOPORT ECLOSE1 ECLOSE2  */
X    ubyte   filler;
X};
X
XCEOFCMD {		/*  Send [R/W] EOF		*/
X    ubyte   chanh;
X    ubyte   chanl;
X    ubyte   flags;
X    ubyte   filler;
X};
X
XCIOCTL {
X    ubyte   chanh;	/* channel			*/
X    ubyte   chanl;
X    ubyte   cmd;	/* ioctl command		*/
X    ubyte   valh;	/* ioctl value			*/
X    ubyte   vall;
X    ubyte   valaux;	/* auxillary field		*/
X};
X
X#define CIO_SETROWS	1	/* PTY's only                   */
X#define CIO_SETCOLS	2	/* PTY's only                   */
X#define CIO_STOP	3	/* any channel, flow control	*/
X#define CIO_START	4	/* any channel, flow control	*/
X#define CIO_FLUSH	5
X
X#define CHAN	struct _CHAN
X
XCHAN {
X    PORT    *port;
X    IOR     *ior;
X    ubyte   state;
X    ubyte   flags;
X    char    pri;	/*  transmit priority	*/
X};
X
END_OF_FILE
if test 1724 -ne `wc -c <'channel.h'`; then
    echo shar: \"'channel.h'\" unpacked with wrong size!
fi
# end of 'channel.h'
fi
if test -f 'dnet.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dnet.h'\"
else
echo shar: Extracting \"'dnet.h'\" \(6639 characters\)
sed "s/^X//" >'dnet.h' <<'END_OF_FILE'
X
X/*
X *  DNET.H
X *
X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
X *
X */
X
X#define DNET_H
X
X#ifdef LATTICE
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/ports.h>
X#include <exec/libraries.h>
X#include <exec/devices.h>
X#include <exec/io.h>
X#include <exec/memory.h>
X#include <exec/interrupts.h>
X#include <intuition/intuition.h>
X#include <devices/console.h>
X#include <devices/timer.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <libraries/filehandler.h>
X#include <string.h>
X#include <stdlib.h>
X#include <proto/exec.h>
X#include <proto/dos.h>
X
X#define U_ARGS(a) a
X
X#else
X
X#define U_ARGS(a) ()    /* No support for prototypes - oh well */
X
X#endif
X
X
Xtypedef unsigned char	ubyte;
Xtypedef unsigned short	uword;
Xtypedef unsigned long	ulong;
X
Xtypedef struct MsgPort	    PORT;
Xtypedef struct timerequest  IOT;
Xtypedef struct IOStdReq     IOR;
Xtypedef struct List	    LIST;
Xtypedef struct Node	    NODE;
Xtypedef struct Process	    PROC;
Xtypedef struct Message	    MSG;
X
X#include "channel.h"
X
X#ifndef MAX(a,b)
X#define MAX(a,b) (((a)>(b))?(a):(b))
X#endif
X
X#define PKT struct _PKT
X#define PNODE	struct _PNODE
X
X#define BTOC(yow)           ((ubyte *)((long)(yow) << 2))
X#define DNETPORTNAME	    "DNET.UNIT."
X#define OFFSET(ptr,elem)    ((long)((char *)&(ptr)->elem - (char *)(ptr)))
X
X#define EMPTY	0	/*  empty (sent)                    */
X#define READY	1	/*  data ready (not sent yet)       */
X
X#define MAXCHAN 128	/*  Max # of channels supported     */
X#define SYNC	0xFF	/*  SYNC character		    */
X#define MAXPKT	200	/*  maximum packet size 	    */
X#define MINPKT	32	/*  minimum maximum packet size
X			    (for priority scheme)           */
X
X#define OVERHEAD    7	/*  for packets with data	    */
X
XPNODE {
X    NODE    node;
X    char    name[32];
X    ulong   seg;
X};
X
XPKT {
X    uword   iolength;	/*  send: length of packet, recv: length of data    */
X    ubyte   state;	/*  EMPTY, READY     */
X
X    ubyte   sync;	/*  THE PACKET	    */
X    ubyte   ctl;
X    ubyte   cchk;
X    ubyte   lenh;
X    ubyte   lenl;
X    ubyte   data[MAXPKT+2];
X};
X
X/*  RECEIVER STATES    */
X#define RS_SYNC 0	    /*	Waiting for sync		*/
X#define RS_CTL	1	    /*	Waiting for command		*/
X#define RS_CCHK 2	    /*	Waiting for check byte		*/
X#define RS_LEN1 3	    /*	Waiting for MSB length byte	*/
X#define RS_LEN2 4	    /*	Waiting for LSB length byte	*/
X#define RS_DATA 5	    /*	Waiting for data & checksum	*/
X
X#define DNCMD_OPEN	32  /*	Application open		*/
X#define DNCMD_SOPEN	33  /*	Server open			*/
X#define DNCMD_CLOSE	34  /*	Close a channel 		*/
X#define DNCMD_EOF	35  /*	Will no longer write to channel */
X
X#define DNCMD_WRITE	36  /*	Write data to a channel 	*/
X#define DNCMD_QUIT	37  /*	Kill the DNET server		*/
X#define DNCMD_IOCTL	38
X
X/*  REQUEST TYPES    */
X#define RTO_REQ 	1   /*	Network read timeout		*/
X#define WTO_REQ 	2   /*	Network write-ack timeout	*/
X#define RNET_REQ	3   /*	Network read data		*/
X#define WNET_REQ	4   /*	Network write data sent 	*/
X#define PKT_REQ 	5   /*	Returned packets from servers	*/
X#define OPEN_REQ	6
X#define IGWNET_REQ	7
X
X/* PACKET CONTROL BYTE */
X#define PKF_SEQUENCE	0xE0	/*  Sequence #			*/
X#define PKF_DATA	0x10	/*  1-65535 bytes		*/
X#define PKF_RESERVED	0x08	/*  reserved bit		*/
X#define PKF_MASK	0x07	/*  command mask		*/
X
X#define PKCMD_WRITE	1	/*  A DATA packet		*/
X#define PKCMD_CHECK	2	/*  Request ACK or NAK for win	*/
X#define PKCMD_ACK	3	/*  ACK a window		*/
X#define PKCMD_NAK	4	/*  NAK a window		*/
X#define PKCMD_RESTART	5	/*  Restart			*/
X#define PKCMD_ACKRSTART 6	/*  Restart Acknowledge 	*/
X#define PKCMD_RESERVE3	7
X/*  CHANNEL COMMANDS	*/
X#define SCMD_SWITCH	0x00	/*  switch active channel #	*/
X#define SCMD_OPEN	0x01	/*  open a channel		*/
X#define SCMD_CLOSE	0x02	/*  close a channel		*/
X#define SCMD_ACKCMD	0x03	/*  ack an open/close request	*/
X#define SCMD_EOFCMD	0x04	/*  Reof or Weof		*/
X#define SCMD_QUIT	0x05	/*  crash dnet			*/
X#define SCMD_IOCTL	0x06	/*  ioctl			*/
X
X#define SCMD_DATA	0x08	/*  stream command, DATA	*/
X
X#define CHAN_FREE	0x01	/*  free channel		*/
X#define CHAN_ROPEN	0x02	/*  remote open, wait port msg	*/
X#define CHAN_LOPEN	0x03	/*  local open, wait reply	*/
X#define CHAN_OPEN	0x04
X#define CHAN_CLOSE	0x05	/*  see flags			*/
X#define CHANF_ROK	0x01	/*  NOT read eof		*/
X#define CHANF_WOK	0x02	/*  remote will accept data	*/
X#define CHANF_LCLOSE	0x04
X#define CHANF_RCLOSE	0x08
X
Xstruct DChannel {
X    PORT    port;	      /*  receive data, replies      */
X    PORT    *dnetport;	      /* dnet's master port          */
X    LIST    rdylist;	      /* ready to be read	     */
X    uword   chan;	      /* channel # for open channels */
X    ubyte   eof;	      /* channel remotely closed/eof */
X    ubyte   filler;
X    int     qlen;	      /* allowed write queue size    */
X    int     queued;	      /* current # packets queued    */
X};
X
Xextern void  *ArbitrateNext();
X
X#ifndef NOEXT
Xextern IOT Rto; 	       /*  Read-Timeout/reset	       */
Xextern IOT Wto; 	       /*  Write-Timeout/retry	       */
Xextern IOR *RNet;	       /*  read-request 	       */
Xextern IOR *WNet;	       /*  write-request	       */
Xextern PKT Pkts[9];
Xextern PKT *Raux;	       /*  next packet in	       */
Xextern PKT *RPak[4];
Xextern PKT *WPak[4];
Xextern PORT *DNetPort;	       /*  Remote Command/Control in	   */
Xextern PORT *IOSink;	       /*  Return port for ALL IO	   */
Xextern CHAN Chan[MAXCHAN];
Xextern LIST TxList;	       /*  For pending DNCMD_WRITE reqs.   */
Xextern LIST SvList;
Xextern ubyte Rto_act;
Xextern ubyte Wto_act;
Xextern uword RChan;
Xextern uword WChan;
Xextern uword RPStart;
Xextern uword WPStart;
Xextern uword WPUsed;
Xextern uword RState;
Xextern ubyte DDebug;
Xextern ubyte Restart;
Xextern ubyte DeldQuit;
Xextern ubyte AutoHangup;
Xextern ulong NumCon;
Xextern ulong WTimeoutVal;
Xextern ulong RTimeoutVal;
Xextern long Baud;
Xextern char *HostName;	    /*	 The Amiga's HostName    */
X
Xextern ubyte RestartPkt[3];
Xextern ubyte AckPkt[8][3];
Xextern ubyte NakPkt[8][3];
Xextern ubyte CheckPkt[8][3];
X#endif
X
X#ifdef LATTICE
X/* One #ifdef LATTICE is worth 1000 U_ARGS macros! */
XPORT *DListen(uword);
Xvoid DUnListen(PORT *);
XPORT *DAccept(PORT *);
XDNAAccept(PORT *);
Xvoid DPri(struct DChannel *, int);
XPORT *DOpen(char * /*host*/, uword /*portnum*/,
X	    char /*txpri*/, char /*rxpri*/);
Xint DNRead(struct DChannel *, char *, int);
Xint DRead(struct DChannel *, char *, int);
Xvoid DQueue(struct DChannel *, int);
XDWrite(struct DChannel *, char *, int);
Xvoid DEof(struct DChannel *);
Xvoid DIoctl(struct DChannel *, ubyte, uword, ubyte);
Xint DQuit(char *);
Xvoid DClose(struct DChannel *);
Xvoid WaitMsg(IOR *);
Xint WaitQueue(struct DChannel *, IOR *);
X
X#endif
X
END_OF_FILE
if test 6639 -ne `wc -c <'dnet.h'`; then
    echo shar: \"'dnet.h'\" unpacked with wrong size!
fi
# end of 'dnet.h'
fi
if test -f 'dnetlib.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dnetlib.c'\"
else
echo shar: Extracting \"'dnetlib.c'\" \(10399 characters\)
sed "s/^X//" >'dnetlib.c' <<'END_OF_FILE'
X/*
X *  DNETLIB.C
X *
X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
X *
X *  Library Interface for DNET.
X */
X
X#include "dnet.h"
X
X#include <stdio.h>
X
X#ifndef BUG
X#define BUG(a)
X#define BUGGETC
X#endif
X
Xstatic struct DChannel *MakeChannel U_ARGS((IOR *, char *));
Xstatic void DeleteChannel U_ARGS((struct DChannel *));
Xstatic void FixSignal	  U_ARGS((struct DChannel *));
X
X#define NAMELEN sizeof("DNET.PORT.XXXXX")
X#define NAMEPAT "DNET.PORT.%ld"
X
XPORT *DListen(portnum)
Xuword portnum;
X{
X    PORT *port;
X    char *ptr;
X
X    port = NULL;
X    ptr = AllocMem(NAMELEN, MEMF_PUBLIC);   /*  memory the the name     */
X    sprintf(ptr, NAMEPAT, portnum);
X    Forbid();                               /*  task-atomic operation   */
X    if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
X       FreeMem(ptr, NAMELEN);
X    Permit();
X    return(port);
X}
X
Xvoid
XDUnListen(lisport)
XPORT *lisport;
X{
X   register char *ptr;
X   ptr = lisport->mp_Node.ln_Name;
X
X   if (lisport)
X   {
X      Forbid();                       /*  task-atomic operation       */
X      while (DNAAccept(lisport));     /*  remove all pending requests */
X      DeletePort(lisport);            /*  gone!                       */
X      Permit();
X      FreeMem(ptr, NAMELEN);
X   }
X}
X
X/*
X *  DAccept()
X *
X *  Note:   This call will work even if called by a task which does not
X *	    own the listen port.
X */
X
XPORT *
XDAccept(lisport)
XPORT *lisport;
X{
X    register IOR *ior;
X    register struct DChannel * chan;
X
XBUG(("DAccept: Entry, port %lx\n", lisport))
X
X    chan = NULL;
X    while (!chan && (ior = (IOR *)GetMsg(lisport))) {
X       switch(ior->io_Command) {
X	  case DNCMD_SOPEN:
X	     BUG(("DAccept: SOPEN command\n"))
X	     chan = MakeChannel(ior, NULL);
X	     break;
X	  default:
X	     BUG(("DAccept: Unrecognized command '%d'\n", ior->io_Command))
X	     ior->io_Error = 1;
X	     break;
X	}
X	BUG(("DAccept: Replying\n"))
X	ReplyMsg(&ior->io_Message);
X    }
X    BUG(("DAccept: After while loop\n"))
X    if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
X       SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
X
X    return(chan ? &chan->port : NULL);
X}
X
X/*
X *  Refuse a connection
X */
X
XDNAAccept(lisport)
XPORT *lisport;
X{
X    IOR *ior;
X
X    if (ior = (IOR *)GetMsg(lisport)) {
X	ior->io_Error = 1;
X	ReplyMsg(&ior->io_Message);
X    }
X    if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
X       SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
X    return(ior != NULL);
X}
X
Xvoid DPri(chan, pri)
Xstruct DChannel * chan;
Xint pri;
X{
X}
X
X
XPORT *
XDOpen(host, portnum, txpri, rxpri)
Xchar *host;
Xchar txpri, rxpri;
Xuword portnum;
X{
X    IOR ior;
X    struct DChannel *chan;
X
X    if (!host)
X       host = "0";
X    chan = MakeChannel(&ior, host);
X    if (rxpri > 126)
X	rxpri = 126;
X    if (rxpri < -127)
X	rxpri = -127;
X    if (txpri > 126)
X	txpri = 126;
X    if (txpri < -127)
X	txpri = -127;
X    if (chan->dnetport) {
X	ior.io_Command = DNCMD_OPEN;
X	ior.io_Unit = (void *)portnum;
X	ior.io_Offset = (long)chan;
X	ior.io_Message.mn_ReplyPort = &chan->port;
X	ior.io_Message.mn_Node.ln_Pri = txpri;
X	ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
X
X	PutMsg(chan->dnetport, &ior.io_Message);
X	WaitMsg(&ior);
X	if (ior.io_Error == 0) {
X	   chan->chan = (long)ior.io_Unit;
X	   FixSignal(chan);
X	   return(&chan->port);
X       }
X    }
X    DeleteChannel(chan);
X    return(NULL);
X}
X
X
XDNRead(chan, buf, bytes)
Xstruct DChannel * chan;
Xchar *buf;
Xint bytes;
X{
X    register IOR *ior;
X    int len;
X    long n;
X
X    len = 0;
X    if (chan->eof)
X       return(-1);
X    while (bytes && ((ior = (IOR *)
X	       RemHead((struct List *)&chan->rdylist)) ||
X	       (ior = (IOR *)GetMsg(&chan->port)))) {
X       if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG)
X       {
X	  if (!chan->queued)
X	  {
X	     BUG(("DNRead: Software Error"));
X	  }
X	  else
X	     --chan->queued;
X	  if (ior->io_Length)
X	     FreeMem((char *)ior->io_Data, (long)ior->io_Length);
X	 FreeMem((char *)ior, (long)sizeof(IOR));
X	 continue;
X       }
X      switch(ior->io_Command)
X      {
X	 case DNCMD_CLOSE:
X	 case DNCMD_EOF:
X	    chan->eof = 1;
X	    ReplyMsg(&ior->io_Message);
X	    break;
X
X	 case DNCMD_WRITE:
X	    n = ior->io_Length - ior->io_Actual;
X	    if (n <= bytes)
X	    {
X	       memcpy(buf, ((char *)ior->io_Data) + ior->io_Actual, n);
X	       bytes -= n;
X	       len += n;
X	       buf += n;
X	       ReplyMsg(&ior->io_Message);
X	    }
X	    else
X	    {
X	       memcpy(buf, (char *)ior->io_Data + ior->io_Actual, bytes);
X	       len += bytes;
X	       ior->io_Actual += bytes;
X	       bytes = 0;
X	       Forbid();   /*  DNET device is a task, no need to Disable() */
X	       ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
X	       AddHead(&chan->port.mp_MsgList, (struct Node *)ior);
X	       Permit();
X	    }
X	    break;
X	 default:
X	    ior->io_Error = 1;
X	    ReplyMsg(&ior->io_Message);
X      }
X    }
X    FixSignal(chan);
X    if (chan->eof)
X       SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
X    return(len);
X}
X
Xint DRead(chan, buf, bytes)
Xchar *buf;
Xstruct DChannel * chan;
Xint bytes;
X{
X   long len;
X   long n;
X
X   len = 0;
X   if (chan->eof)
X   {
X      BUG(("****DNET EOF!!!\n"));
X      return(-1);
X   }
X
X   while (bytes)
X   {
X      WaitPort(&chan->port);
X      n = DNRead(chan, buf, bytes);
X      len += n;
X      if (n < 0) break;
X      buf += n;
X      bytes -= n;
X      if (chan->eof) break;
X   }
X   return(len);
X}
X
Xvoid DQueue(chan, n)
Xstruct DChannel * chan;
Xint n;
X{
X    chan->qlen = n;
X}
X
XDWrite(chan, buf, bytes)
Xstruct DChannel * chan;
Xchar *buf;
Xint bytes;
X{
X    IOR tmpior;
X    IOR *ior;
X    int error;
X
X   error = bytes;
X   if (chan->qlen)
X   {
X      if (WaitQueue(chan, NULL) >= 0)
X      {
X	 ior = (IOR *)AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
X	 ior->io_Command = DNCMD_WRITE;
X	 ior->io_Unit = (void *)chan->chan;
X	 ior->io_Offset = (long)chan;
X	 ior->io_Message.mn_ReplyPort = &chan->port;
X	 ior->io_Data = (APTR)AllocMem(bytes, MEMF_PUBLIC);
X	 ior->io_Length = bytes;
X	 memcpy((char *)ior->io_Data, buf, (int)bytes);
X	 PutMsg(chan->dnetport, &ior->io_Message);
X	 ++chan->queued;
X      }
X      else
X      {
X	 error = -1;
X      }
X   }
X   else
X   {
X      tmpior.io_Command = DNCMD_WRITE;
X      tmpior.io_Unit = (void *)chan->chan;
X      tmpior.io_Offset = (long)chan;
X      tmpior.io_Message.mn_ReplyPort = &chan->port;
X      tmpior.io_Data = (APTR)buf;
X      tmpior.io_Length = bytes;
X      PutMsg(chan->dnetport, &tmpior.io_Message);
X      WaitMsg(&tmpior);
X      if (tmpior.io_Error)
X      {
X	 error = -1;
X	 BUG(("*****DWrite: io_Error %d\n", tmpior.io_Error));
X	 BUGGETC
X      }
X   }
X   FixSignal(chan);
X   return(error);
X}
X
Xvoid DEof(chan)
Xstruct DChannel * chan;
X{
X    IOR ior;
X
X    ior.io_Command = DNCMD_EOF;
X    ior.io_Unit = (void *)chan->chan;
X    ior.io_Offset = (long)chan;
X    ior.io_Message.mn_ReplyPort = &chan->port;
X    PutMsg(chan->dnetport, &ior.io_Message);
X    WaitMsg(&ior);
X    FixSignal(chan);
X}
X
Xvoid DIoctl(chan, cmd, val, aux)
Xstruct DChannel * chan;
Xubyte cmd;
Xuword val;
Xubyte aux;
X{
X    IOR ior;
X
X    ior.io_Command = DNCMD_IOCTL;
X    ior.io_Unit = (void *)chan->chan;
X    ior.io_Offset = (long)chan;
X    ior.io_Message.mn_ReplyPort = &chan->port;
X    ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
X    PutMsg(chan->dnetport, &ior.io_Message);
X    WaitMsg(&ior);
X    FixSignal(chan);
X}
X
Xint DQuit(host)
Xchar *host;
X{
X    IOR ior;
X    char buf[sizeof(DNETPORTNAME)+32];
X    PORT *replyport;
X    PORT *dnetport;
X
X    if (!host)
X	host = "0";
X    sprintf(buf, "%s%s", DNETPORTNAME, host);
X    if (dnetport = FindPort(buf)) {
X	replyport = CreatePort(NULL, 0);
X	ior.io_Command = DNCMD_QUIT;
X	ior.io_Unit = 0;
X	ior.io_Offset = 0;
X	ior.io_Message.mn_ReplyPort = replyport;
X	PutMsg(dnetport, &ior.io_Message);
X	WaitMsg(&ior);
X	DeletePort(replyport);
X    }
X    return(dnetport != NULL);
X}
X
X
Xvoid DClose(chan)
Xstruct DChannel * chan;
X{
X    IOR ior;
X    IOR *io;
X
XBUG(("DClose: Enter\n"))
X
X    ior.io_Command = DNCMD_CLOSE;
X    ior.io_Unit = (void *)chan->chan;
X    ior.io_Offset = (long)chan;
X    ior.io_Message.mn_ReplyPort = &chan->port;
X    PutMsg(chan->dnetport, &ior.io_Message);
X    ++chan->queued;
X    chan->qlen = 0;
X    WaitQueue(chan, &ior);
X    while ((io = (IOR *)RemHead((struct List *)&chan->rdylist)) ||
X	   (io = (IOR *)GetMsg(&chan->port))) {
X	io->io_Error = 1;
X	ReplyMsg(&io->io_Message);
X    }
X    DeleteChannel(chan);
X}
X
Xvoid WaitMsg(ior)
XIOR *ior;
X{
X    while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
X	Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit);
X    Forbid();
X    Remove((struct Node *)ior);
X    Permit();
X}
X
Xint WaitQueue(chan, skipior)
Xstruct DChannel * chan;
XIOR *skipior;
X{
X    register IOR *io;
X    short error;
X
X   error = 0;
X    while (chan->queued > chan->qlen) {     /*  until done  */
X	WaitPort(&chan->port);   /*  something   */
X	io = (IOR *)GetMsg(&chan->port);
X	if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
X	    if (error == 0)
X		error = io->io_Error;
X	    if (io != skipior) {
X		if (io->io_Length)
X		    FreeMem((char *)io->io_Data, io->io_Length);
X		FreeMem((char *)io, sizeof(IOR));
X	    }
X	    --chan->queued;
X	} else {
X	    AddTail(&chan->rdylist, (struct Node *)io);
X	}
X    }
X    return((int)error);
X}
X
Xstatic struct DChannel *MakeChannel(ior, host)
Xregister IOR *ior;
Xchar *host;
X{
X    struct DChannel * chan;
X    char buf[sizeof(DNETPORTNAME)+32];
X
XBUG(("MakeChannel: Entry\n"))
X
X    chan = (struct DChannel *)AllocMem(sizeof(struct DChannel),
X				       MEMF_PUBLIC|MEMF_CLEAR);
X
X    /*	Name, Pri */
X    chan->port.mp_Node.ln_Type = NT_MSGPORT;
X    chan->port.mp_SigBit = AllocSignal(-1);
X    chan->port.mp_SigTask = FindTask(NULL);
X    NewList(&chan->port.mp_MsgList);
X    NewList(&chan->rdylist);
X    chan->chan = (long)ior->io_Unit;
X    ior->io_Offset = (long)chan;
X    if (host) {
X       sprintf(buf, "%s%s", DNETPORTNAME, host);
X	ior->io_Message.mn_ReplyPort = FindPort(buf);
X    }
X    chan->dnetport = ior->io_Message.mn_ReplyPort;
X    return(chan);
X}
X
Xstatic void
XDeleteChannel(chan)
Xstruct DChannel * chan;
X{
X    FreeSignal(chan->port.mp_SigBit);
X    FreeMem((char *)chan, (long)sizeof(struct DChannel));
X}
X
Xstatic void
XFixSignal(chan)
Xregister struct DChannel * chan;
X{
X    if (chan->port.mp_MsgList.lh_Head !=
X	     (NODE *)&chan->port.mp_MsgList.lh_Tail ||
X       chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
X	SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
X}
X
END_OF_FILE
if test 10399 -ne `wc -c <'dnetlib.c'`; then
    echo shar: \"'dnetlib.c'\" unpacked with wrong size!
fi
# end of 'dnetlib.c'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(709 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X#
X#
X# For use with Lattice LMK.  To compile, type 'LMK'.
X#
X#
X
XLIBS   = lib:lc.lib lib:amiga.lib
X
XCFLAGS = -cwusf -v
XLC2FLAGS = 
XCLIENTOBJS = netkeys.o  nkutil.o dnetlib.o mshow.o
XSERVEROBJS = snetkeys.o nkutil.o dnetlib.o mshow.o
X
Xall:  netkeys snetkeys
X
Xnetkeys: $(CLIENTOBJS)
X  @echo >ram:tmp.with "from lib:cback.o $(CLIENTOBJS)"
X  @assign blinkwith:
X  blink with ram:tmp.with SC SD ND VERBOSE BATCH to $@ lib $(LIBS)
X
Xsnetkeys: $(SERVEROBJS)
X  @echo >ram:tmp.with "from $(SERVEROBJS)"
X  @assign blinkwith:
X  blink with ram:tmp.with SC SD ND VERBOSE BATCH to $@ lib $(LIBS)
X
Xnetkeys.o  : netkeys.c netkeys.h dnet.h
X   lc $(CFLAGS) netkeys.c
Xsnetkeys.o  : snetkeys.c netkeys.h dnet.h
Xnkutil.o    : nkutil.c
END_OF_FILE
if test 709 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'mshow.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mshow.c'\"
else
echo shar: Extracting \"'mshow.c'\" \(1595 characters\)
sed "s/^X//" >'mshow.c' <<'END_OF_FILE'
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1990 The Software Distillery.  All Rights Reserved.*/
X/* |. o.| || This program may not be distributed without the permission of   */
X/* | .  | || the authors.                                                    */
X/* | o  | ||                                                                 */
X/* |  . |// Written by Doug Walker                                           */
X/* ======          BBS:(919)-471-6436      VOICE:(919)-467-4764              */ 
X/*                 BIX: djwalker           USENET: ...!mcnc!rti!sas!walker   */
X/*                 405 B3 Gooseneck Dr, Cary, NC 27513, USA                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X/* This code shamelessly stolen from Matt Dillon's DMOUSE */
X
X#include "netkeys.h"
X
Xvoid mshow(struct GfxBase *GfxBase, UWORD *NoSprData, int on)
X{
X   static UWORD *SprSavePtr = NULL;
X   struct copinit *ci = GfxBase->copinit;
X
X   if(on)
X   {
X      if(SprSavePtr)
X      {
X         ci->sprstrtup[1] = (UWORD)(((ULONG)SprSavePtr) >> 16);
X         ci->sprstrtup[3] = (UWORD)(((ULONG)SprSavePtr) & 0xffff);
X         SprSavePtr = NULL;
X      }
X   }
X   else if(ci->sprstrtup[0] == 0x120 && ci->sprstrtup[2] == 0x122)
X   {
X      if(!SprSavePtr)
X         SprSavePtr = (UWORD *)(((ULONG)ci->sprstrtup[1] << 16) | 
X                                 (ULONG)ci->sprstrtup[3]);
X      ci->sprstrtup[1] = (UWORD)(((ULONG)NoSprData) >> 16);
X      ci->sprstrtup[3] = (UWORD)(((ULONG)NoSprData) & 0xffff);
X   }
X}
END_OF_FILE
if test 1595 -ne `wc -c <'mshow.c'`; then
    echo shar: \"'mshow.c'\" unpacked with wrong size!
fi
# end of 'mshow.c'
fi
if test -f 'netkeys.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'netkeys.doc'\"
else
echo shar: Extracting \"'netkeys.doc'\" \(8411 characters\)
sed "s/^X//" >'netkeys.doc' <<'END_OF_FILE'
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
X* |_o_o|\\ Copyright (c) 1989, 1990 The Software Distillery.              *
X* |. o.| ||          All Rights Reserved                                  *
X* | .  | ||          Written by Doug Walker                               *
X* | o  | ||          The Software Distillery                              *
X* |  . |//           405 B3 Gooseneck Drive                               *
X* ======             Cary, NC 27513                                       *
X*                    BBS:(919)-382-8265                                   *
X*                                                                        *
X* USENET: ...mcnc!rti!sas!walker     PLINK: dwalker      BIX: djwalker    *
X\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
XNetKeys is Copyright (c) 1989, 1990 The Software Distillery.
XPermission is granted to distribute programs and data in this distribution
Xprovided the following conditions are met:
X
X   1.  All files present in the distribution package must be redistributed
X       with the package, including this documentation file.  If you 
X       distribute on diskette, all files must be on a single diskette.
X
X   2.  The distributor may charge a fee to recover distribution costs.
X       The fee for diskette distribution should not be more than the cost 
X       to obtain the same diskette from Fred Fish or The Software Distillery,
X       whichever is greater.  Current charge from The Software Distillery
X       is $6 per disk for US and Canadian distribution, $7 elsewhere, including 
X       all postage and handling charges.
X
X   3.  The distributor agrees to cease distributing the programs and data
X       involved if requested to do so by the author or any member of The 
X       Software Distillery.
X
X------------------------------DISCLAIMER
X
XNeither The Software Distillery nor any of its members will be held liable for 
Xany damage arising from the failure of this program to perform as described,
Xor any destruction of other programs or data residing on a system 
Xattempting to run the program.  While we expect no damaging errors, the 
Xuser of this program uses it at his or her own risk.
X
X------------------------------ACKNOWLEDGEMENTS
X Written in Lattice C V5.05.  Thanks to Matt Dillon for DNET!
X
XContributions to continue development of this and other fine products for the
XAmiga may be sent to the Software Distillery at the above address.
X
XOther Products produced by the Software Distillery are:
X   BLINK      - the Turbo-charged Alink replacement
X   HACK       - The Amiga port of the famous UNIX game
X   LARN       - Another famous UNIX game
X   MEMWATCH   - Protects your machine from random trashes
X   MEMLIB     - A library of memory debugging routines
X   MAKE       - A software development tool one shouldn't be without
X   KERMIT     - The World renown file transfer protocol brought to the Amiga
X   ICONEXEC, SETALTERNATE, SETWINDOW - Icon manipulation tools
X   TSIZE      - A short utility for determining directory sizes.
X   POPCLI     - A hotkey utility and screen blanker.
X   PICKPACKET - A tutorial program for learning about the DOS packet interface
X   NET:       - An Amiga-to-Amiga network file system running on either the 
X                parallel or serial ports with no additional hardware.
X   FILEHANDLER- An example file system written entirely in C
X   
X
XAll of these are available on our BBS.
X
X-----------------------------THE GOOD STUFF
X
XNETKEYS solves a problem that I encountered when I bought my Amiga 2000.
XNaturally, I kept my A1000 around;  therefore, I became a two-Amiga Amigoid.
XUnfortunately, I discovered it was a pain to switch keyboards and mice to
Xget from one to the other Amiga.  The solution to this is NETKEYS.  NETKEYS
Xinstalls itself in the input event chain (AHEAD of Intuition) and, on demand,
Xintercepts all keystrokes and mouse events and ships them off to the other
Xmachine.  
X
XNETKEYS uses Matt Dillon's DNET networking package.  DNET is freely redist-
Xributable, available on Fred Fish #294 and on all the major nets.  To use 
XNETKEYS effectively, you will have to have the two machines sitting next to 
Xeach other, so you should connect them with a simple null modem cable and use
Xthe following command to start DNET on both machines:
X
XRUN DNET -s -X -h0 -Z0 -P0 -m0
X
X(If you have the older version 1.x of DNET, just use RUN DNET -s).  DNET will
Xuse the baud rate you have set in preferences.  If you find NETKEYS to be
Xhanging up or acting strangely, try a lower baud rate;  I find the fastest
XI can use is 9600.  After the DNET windows come up on both machines, you 
Xshould be able to type characters into one window and see them in the other.
XSelect STARTDNET from one of the machines' menus. If the other machines' 
Xwindow does not disappear, use the QUITDNET command or the BREAK command to 
Xget the DNET window back and try it again.  DNET uses the file 
XS:DNET.SERVERS to locate server programs; you will need to add a line like
X
X9494   sys:dnet/snetkeys  ram:   ;NETKEYS server
X
Xin order for DNET to find the NETKEYS server.  Change the path to reflect
Xthe actual path of the server, but don't modify the number 9494.
X
XOnce DNET has been set up properly, move to the machine whose keyboard
Xyou would like to use.  Type 'NETKEYS'.  NetKeys detaches itself from the
XCLI, so there is no need to use RUN or RUNBACK.  Once NetKeys is installed,
Xhitting Left-Amiga-R will toggle between the two machines.  Also, moving the
Xmouse cursor off the left edge of your machine will cause it to appear on
Xthe right edge of the remote machine;  and moving it off the right edge of
Xyour screen will cause it to appear on the left edge.
X
XIf you would like to use a key other than Left-Amiga-R, you can pass a 
Xparameter of the form '0x##' where ## is the hexadecimal raw key code for the
Xkey to be used.  For example, NETKEYS 0x13 would use Left-Amiga-R, just like
Xthe default; NETKEYS 0x14 would use Left-Amiga-T, and so forth.  You can 
Xchange the key NetKeys uses after invoking it by reinvoking it with different
Xparameters.
X
XIf you want to get rid of NETKEYS, just type NETKEYS QUIT.  Other options are
Xlisted below.
X
XHave fun! 
X
X--Doug
X
X------------------------------SYNTAX GUIDE
X
XParms to NETKEYS are letters;  each stands for a word.  You can type the
Xentire keyword if you like, but netkeys will only look at the first letter.
X
XNETKEYS [0xnn] [F|S] [L|R|W] [Q]
X
X   0xnn    -   Use the key with raw hexadecimal key code 0xnn as the hotkey
X               to swap displays.
X
X   F|S     -   [F]ast (default) or [S]mooth.  When the [F]ast option is 
X               active, NETKEYS will combine multiple mouse movement events 
X               into one in order to get faster results.  When [S]mooth is 
X               selected, it will not do this.  [F]ast is the default.
X
X   [L|R|W] -   [L]eft, [R]ight or [W]rap.  If [L]eft is active, the mouse
X               cursor will exit from the left edge of the main display and
X               appear on the right edge of the slave display.  If [R]ight
X               is active, the mouse cursor will exit from the right edge of
X               the main display and appear on the left edge of the slave.  If
X               [W]rap is active, both sides of the main display will cause
X               the cursor to appear on the slave.  [W]rap is the default.
X
X   [Q]         [Q]uit.  Terminates a running NETKEYS process.
X
XIf you enter a NETKEYS command and NETKEYS is already running, the parameters
Xof the running NETKEYS command are modified.  Thus, you can change from
XFAST to SMOOTH on the fly by issuing
X
X NETKEYS FAST   ;  start up NETKEYS in FAST mode
X NETKEYS SMOOTH ;  change to SMOOTH mode
X
XRemember that NETKEYS only looks at the first character of your parameters.
XTherefore, you have exactly the same effect as the above with
X
X NETKEYS FUTILE ;  first character is 'F' = FAST
X NETKEYS STUPID ;  first character is 'S' = SMOOTH
X
X------------------------------DISTRIBUTION LIST
X
Xchannel.h                   1724
Xdnet.h                      6639
Xnkutil.c                    2509
Xnetkeys.h                   4109
Xsnetkeys.c                  5856
Xnetkeys.c                  15146
Xmakefile                     709
Xnetkeys.doc                 8409
Xsnetkeys                    5840
Xnetkeys                     9396
Xmshow.c                     1595
Xdnetlib.c                  10399
END_OF_FILE
if test 8411 -ne `wc -c <'netkeys.doc'`; then
    echo shar: \"'netkeys.doc'\" unpacked with wrong size!
fi
# end of 'netkeys.doc'
fi
if test -f 'netkeys.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'netkeys.h'\"
else
echo shar: Extracting \"'netkeys.h'\" \(4109 characters\)
sed "s/^X//" >'netkeys.h' <<'END_OF_FILE'
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1990 The Software Distillery.  All Rights Reserved.*/
X/* |. o.| || This program may not be distributed without the permission of   */
X/* | .  | || the authors.                                                    */
X/* | o  | ||                                                                 */
X/* |  . |// Written by Doug Walker                                           */
X/* ======          BBS:(919)-471-6436      VOICE:(919)-467-4764              */ 
X/*                 BIX: djwalker           USENET: ...!mcnc!rti!sas!walker   */
X/*                 405 B3 Gooseneck Dr, Cary, NC 27513, USA                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/memory.h>
X#include <exec/interrupts.h>
X#include <exec/ports.h>
X#include <exec/libraries.h>
X#include <exec/io.h>
X#include <exec/tasks.h>
X#include <exec/execbase.h>
X#include <exec/devices.h>
X#include <devices/timer.h>
X#include <devices/input.h>
X#include <devices/inputevent.h>
X#include <intuition/intuitionbase.h>
X#include <libraries/dos.h>
X/*#include <graphics/gfxmacros.h>*/
X#include <hardware/custom.h>
X#include <hardware/dmabits.h>
X#include <hardware/cia.h>
X#include <resources/misc.h>
X#include <proto/dos.h>
X#include <proto/exec.h>
X/*#include <proto/intuition.h>*/
X#include <graphics/copper.h>
X#include <graphics/gfxbase.h>
X#include <proto/graphics.h>
X#include <string.h>
X
X#include "dnet.h"
X
X#define PORT_NETKEYS 9494
X
X
X
X#define NKMPNAME "NetKeys 2.0"
X#define BANNER "\x9B" "1m" NKMPNAME "\x9b" "0m by Doug Walker\n"\
X               "Copyright \xA9 1990 The Software Distillery\n"\
X               "235 Trillingham Ln, Cary NC 27513 USA\nBBS:(919)382-8265\n"
X
X#define INSTR  "Use 'NetKeys QUIT' to remove\n"\
X               "Installing, please wait...\n"
X
X#define DEFDOKEY     0x13
X#define MAXMSGS      100
X
X#define MSG(fh,st)  if(fh) Write(fh, st, strlen(st))
X
X#define IESZ  (sizeof(struct InputEvent))
X#define NKMSZ (sizeof(struct NETKEYMSG))
X
X/* Magic class to tell other side information */
X#define IECLASS_NKCONTROL    IECLASS_POINTERPOS
X
X/* Values for the 'Code' field of a IECLASS_NKCONTROL message                  */
X#define IECODE_NKHOTKEY  0x01  /* Hotkey transferred control to server         */
X#define IECODE_NKHOTQUIT 0x02  /* Hotkey ending control by server              */
X#define IECODE_NKLEFT    0x04  /* Mouse is exiting from left of handler screen */
X#define IECODE_NKRIGHT   0x08  /* Mouse is exiting from right of handler scrn  */
X
Xstruct NETKEYMSG
X{
X   struct Message m;
X   short msgtype;
X   struct InputEvent ie;   
X};
X
X/* Defines for the msgtype field */
X#define NKM_NONE    -1
X#define NKM_IEVENT   0
X#define NKM_QUIT     1
X#define NKM_CONTROL  2
X#define NKM_ACK      3
X#define NKM_HEREWEGO 4
X#define NKM_WEBEDONE 5
X
Xtypedef struct
X{
X   struct Task *buddy;
X   short dokey;
X   short state;
X   short nmsgs;
X   struct MsgPort *nkmp;
X   struct MsgPort *rtnp;
X   struct IntuitionBase *ibase;
X   short  swidth;
X   short exit;
X   int active;
X   struct DChannel *chan;
X   
X} GLOBAL_DATA;
X
X/* Defines for the global.state field */
X#define EM_SANITY -3  /* Failed sanity check - prolly too many msgs outstanding */
X#define EM_NOMEM  -2  /* Out of memory                                          */
X#define EM_QUIT   -1  /* Normal quit                                            */
X#define EM_DOIT    0  /* Keep on truckin'                                       */
X#define EM_LURK    1  /* Pass events through                                    */
X#define EM_RELURK  2  /* Start lurking immediately                              */
X
X#define NKM_HANDLER 2 /* Parms to InitDevice */
X#define NKM_SERVER  1
X
Xstruct InputEvent * __regargs myhandler(struct InputEvent *ev, GLOBAL_DATA *gptr);
X
X/* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
Xstruct IOStdReq * CreateIOReq(struct MsgPort *, int);
Xvoid DeleteIOReq(struct IOStdReq *);
X
Xvoid mshow(struct GfxBase *GfxBase, UWORD *NoSprData, int on);
END_OF_FILE
if test 4109 -ne `wc -c <'netkeys.h'`; then
    echo shar: \"'netkeys.h'\" unpacked with wrong size!
fi
# end of 'netkeys.h'
fi
if test -f 'nkutil.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nkutil.c'\"
else
echo shar: Extracting \"'nkutil.c'\" \(2509 characters\)
sed "s/^X//" >'nkutil.c' <<'END_OF_FILE'
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1990 The Software Distillery.  All Rights Reserved.*/
X/* |. o.| || This program may not be distributed without the permission of   */
X/* | .  | || the authors.                                                    */
X/* | o  | ||                                                                 */
X/* |  . |// Written by Doug Walker                                           */
X/* ======          BBS:(919)-471-6436      VOICE:(919)-467-4764              */ 
X/*                 BIX: djwalker           USENET: ...!mcnc!rti!sas!walker   */
X/*                 405 B3 Gooseneck Dr, Cary, NC 27513, USA                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/memory.h>
X#include <exec/ports.h>
X#include <exec/io.h>
X#include <proto/exec.h>
X
Xstruct IOStdReq * CreateIOReq(struct MsgPort *, int);
Xvoid DeleteIOReq(struct IOStdReq *);
X
Xstruct MsgPort * CreatePort(name, pri)
Xchar *name;
Xint pri;
X{
X   UBYTE sigbit;
X   register struct MsgPort *port;
X
X   if ((sigbit = AllocSignal(-1)) == -1)
X      return((struct MsgPort *)0);
X
X   if ((port = (struct MsgPort *)AllocMem(sizeof(struct MsgPort),
X                        MEMF_CLEAR|MEMF_PUBLIC)) == 0)
X      {
X      FreeSignal(sigbit);
X      return((struct MsgPort *) (0));
X      }
X   port->mp_Node.ln_Name = name;
X   port->mp_Node.ln_Pri = pri;
X   port->mp_Node.ln_Type = NT_MSGPORT;
X   port->mp_Flags = PA_SIGNAL;
X   port->mp_SigBit = sigbit;
X   port->mp_SigTask = (struct Task *)FindTask(0);
X   AddPort(port);
X   return(port);
X}
X
Xvoid DeletePort(port)
Xstruct MsgPort *port;
X{
XRemPort(port);
XFreeSignal(port->mp_SigBit);
XFreeMem((char *)port,sizeof(struct MsgPort));
X}
X
Xstruct IOStdReq *
XCreateIOReq(port, size)
Xstruct MsgPort *port;
Xint size;
X{
X   struct IOStdReq *ioReq;
X
X   if ((ioReq = (struct IOStdReq *)
X                AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL)
X      {
X      ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
X      ioReq->io_Message.mn_Node.ln_Pri  = 0;
X      ioReq->io_Message.mn_Length       = size;
X      ioReq->io_Message.mn_ReplyPort    = port;
X      }
X   return(ioReq);
X}
X
Xvoid DeleteIOReq(ioReq)
Xstruct IOStdReq *ioReq;
X{
XioReq->io_Message.mn_Node.ln_Type = 0xff;
XioReq->io_Device = (struct Device *) -1;
XioReq->io_Unit = (struct Unit *) -1;
X
XFreeMem( (char *)ioReq, ioReq->io_Message.mn_Length);
X}
X
END_OF_FILE
if test 2509 -ne `wc -c <'nkutil.c'`; then
    echo shar: \"'nkutil.c'\" unpacked with wrong size!
fi
# end of 'nkutil.c'
fi
if test -f 'snetkeys.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'snetkeys.c'\"
else
echo shar: Extracting \"'snetkeys.c'\" \(5856 characters\)
sed "s/^X//" >'snetkeys.c' <<'END_OF_FILE'
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1990 The Software Distillery.  All Rights Reserved.*/
X/* |. o.| || This program may not be distributed without the permission of   */
X/* | .  | || the authors.                                                    */
X/* | o  | ||                                                                 */
X/* |  . |// Written by Doug Walker                                           */
X/* ======          BBS:(919)-471-6436      VOICE:(919)-467-4764              */ 
X/*                 BIX: djwalker           USENET: ...!mcnc!rti!sas!walker   */
X/*                 405 B3 Gooseneck Dr, Cary, NC 27513, USA                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X/* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
X
X#include "netkeys.h"
X#include <proto/intuition.h>
X
Xstruct DChannel *chan;
X
Xstruct MsgPort *lisport;
X
Xint InitDevice(void);
Xint TermDevice(void);
X
Xvoid _main(char *);
X
Xvoid _main(x)
Xchar *x;
X{
X   short swidth;
X   short exit;
X   int state;
X   struct Screen wbdat;
X   struct MsgPort  *inputDevPort = NULL;
X   struct IOStdReq *inputRequestBlock = NULL;
X   struct InputEvent ie;
X   struct IntuitionBase *IntuitionBase = NULL;
X   struct GfxBase *GfxBase = NULL;
X   UWORD *NoSprData = NULL;
X   ULONG rc;
X
X   if (
X       InitDevice()                                               ||
X
X       ((inputDevPort = CreatePort(0,0)) == NULL)                           ||
X
X       ((inputRequestBlock = 
X               CreateIOReq(inputDevPort, sizeof(struct IOStdReq))) == NULL) ||
X
X       !(IntuitionBase = (struct IntuitionBase *)
X                                       OpenLibrary("intuition.library", 0)) ||
X
X       !(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0))   ||
X
X       !(NoSprData = AllocMem(12, MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR))        ||
X
X      OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
X   {
X      goto abort;
X   }
X
X   NoSprData[0] = 0xFE00;
X   NoSprData[1] = 0xFF00;
X   
X
X   /* If we have an appropriate version of intuition, ask for info */
X   /* about the workbench screen                                   */
X   if(IntuitionBase->LibNode.lib_Version < 33
X      || !(GetScreenData((char *)&wbdat, sizeof(struct Screen), 
X                              WBENCHSCREEN, NULL)))
X   {
X      /* Either we're running on an old version of the system, or the */
X      /* GetScreenData call failed for some reason.  In either case,  */
X      /* simply assume a 640x200 screen and be done with it.          */
X      swidth  = 639;
X   }
X   else
X   {
X      /* Use the wb width, and STDSCREENHEIGHT. */
X      swidth  = wbdat.Width-1;
X   }
X
X   inputRequestBlock->io_Command = IND_WRITEEVENT;
X   inputRequestBlock->io_Flags   = 0;
X   inputRequestBlock->io_Length  = IESZ;
X   inputRequestBlock->io_Data    = (APTR)&ie;
X
X   state = 0;
X   mshow(GfxBase, NoSprData, 0);
X   while(1)
X   {
X      rc = Wait(SIGBREAKF_CTRL_C | (1 << chan->port.mp_SigBit));
X
X      if(rc & SIGBREAKF_CTRL_C)          /* Received ctrl-c */
X         goto abort;
X
X      if(DRead(chan, (char *)&ie, IESZ) != IESZ)
X         goto abort;
X
X      if(ie.ie_Class == IECLASS_NKCONTROL) /* Special 'control' record */
X      {
X         exit = ie.ie_Code;
X         if(ie.ie_Code & IECODE_NKHOTQUIT)
X         {
X            mshow(GfxBase, NoSprData, 0);
X            state = 0;
X            continue;
X         }
X
X         if(!(ie.ie_Code & IECODE_NKHOTKEY))
X         {
X            IntuitionBase->MouseX = (ie.ie_X == 0 ? swidth-1 : 1);
X            IntuitionBase->MouseY = ie.ie_Y;
X         }
X
X         state = 1;
X         mshow(GfxBase, NoSprData, 1);
X         continue;
X      }
X      else if(state == 0)
X         continue;
X
X      if(
X         ie.ie_Class == IECLASS_RAWMOUSE &&
X         (ie.ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE) &&
X         ie.ie_Code == IECODE_NOBUTTON &&
X         ( 
X           (
X              (exit & IECODE_NKRIGHT)          &&
X              ie.ie_X < 0                     &&
X              IntuitionBase->MouseX == 0
X           )
X           ||
X           (
X              (exit & IECODE_NKLEFT)           &&
X              ie.ie_X > 0                     &&
X              IntuitionBase->MouseX == swidth
X           )
X         )
X        )
X      {
X         mshow(GfxBase, NoSprData, 0);
X         ie.ie_X = IntuitionBase->MouseX;
X         ie.ie_Y = IntuitionBase->MouseY;
X         ie.ie_Class = IECLASS_NKCONTROL;
X         DWrite(chan, (char *)&ie, IESZ);
X         state = 0;
X         continue;
X      }
X
X      ie.ie_NextEvent = NULL;
X      DoIO((struct IORequest *)inputRequestBlock);
X   }
X
Xabort:
X   if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
X
X   if(GfxBase)
X   {
X      if(NoSprData)
X      {
X         mshow(GfxBase, NoSprData, 1);
X         FreeMem(NoSprData, 12);
X      }
X      CloseLibrary((struct Library *)GfxBase);
X   }
X
X   TermDevice();
X
X   if (inputRequestBlock != NULL)
X   {
X      if (inputRequestBlock->io_Device != NULL)
X         CloseDevice((struct IORequest *)inputRequestBlock);
X      DeleteIOReq(inputRequestBlock);
X   }
X
X   if (inputDevPort != NULL)  DeletePort(inputDevPort);
X}
X
Xint InitDevice(void)
X{
X   struct MsgPort *myport;
X   struct Message *msg;
X
X   chan = NULL;
X   lisport = NULL;
X
X   myport = &(((struct Process *)FindTask(0L))->pr_MsgPort);
X   lisport = DListen(PORT_NETKEYS);
X   do
X   {
X      WaitPort(myport);
X   }
X   while(!(msg=GetMsg(myport)));
X
X   ReplyMsg(msg);
X
X   if(!lisport) return(1);
X
X   Wait(1<<lisport->mp_SigBit);
X   
X   if(!(chan = (struct DChannel *)DAccept(lisport)))
X      return(1);
X
X   return(0);
X}
X
Xint TermDevice(void)
X{
X   if(chan)
X   {
X      DClose(chan);
X      chan = NULL;
X   }
X
X   if(lisport)
X   {
X      DUnListen(lisport);
X      lisport = NULL;
X   }
X
X   return(0);
X}
X
Xvoid MemCleanup(void);
Xvoid MemCleanup(){}
END_OF_FILE
if test 5856 -ne `wc -c <'snetkeys.c'`; then
    echo shar: \"'snetkeys.c'\" unpacked with wrong size!
fi
# end of 'snetkeys.c'
fi
if test -f 'snetkeys.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'snetkeys.uu'\"
else
echo shar: Extracting \"'snetkeys.uu'\" \(8214 characters\)
sed "s/^X//" >'snetkeys.uu' <<'END_OF_FILE'
Xbegin 666 snetkeys
XM```#\P`````````"``````````$```5A````1@```^D```5A3E7^<$CG)P*1Q
XMR"M(_G0K2/YX*TC^?"M(_I8K2/Z:80`#%DJ`9@`"4D*G0J=.N@/64$\K0/Z:H
XM2H!G``(^2'@`,"\`3KH$6E!/*T#^EDJ`9P`"*$/Z`K!P`"QX``1.KOW8*T#^P
XM?$J`9P`"$$/Z`JIP`$ZN_=@K0/YX2H!G``'\<`PB/``!``-.KO\Z*T#^=$J`R
XM9P`!YD'Z`I)P`")M_I9R`$ZN_D1*@&8``=`@;?YT,+S^`#%\_P```B!M_GP,+
XM:``A`!1E&D'M_IX@/````5IR`9/)+&W^?$ZN_E9*@&8&/CP"?V`(,"W^JBX`;
XM4T<@;?Z6,7P`"P`<0B@`'G`6(4``)$'M_H`B;?Z6(T@`*'H`0J<O+?YT+RW^/
XM>$ZZ#2)/[P`,<``@;`$($"@`#W(!)`'AH@!"$``@`BQX``1.KO["*T#^<`@`9
XM``QF``$P2'@`%DAM_H`O+`$(3KH'W$_O``QR%K"!9@`!%!`M_H19`&9F/"W^$
XMAC`M_H8(```!9Q9"IR\M_G0O+?YX3KH,M$_O``QZ`&".,"W^A@@```!F'C`MZ
XM_HIF""`'2,!3@&`"<`$@;?Y\,4``1C%M_HP`1'H!2'@``2\M_G0O+?YX3KH,E
XM<D_O``Q@`/].2H5G`/]($"W^A%4`9@``@C`M_H@(```/9W8P+?Z&#$``_V9LW
XM"`8``V<0,"W^BFP*(&W^?$IH`$9G&`@&``)G4#`M_HIO2B!M_GPP*`!&L$=F(
XM/D*G+RW^="\M_GA.N@P*(&W^?#MH`$;^BCMH`$3^C!M\``3^A$AX`!9(;?Z`T
XM+RP!"$ZZ!T1/[P`8>@!@`/Z^0JW^@")M_I8L>``$3J[^.&``_JI*K?Y\9PPB;
XM;?Y\+'@`!$ZN_F)*K?YX9S1*K?YT9R)(>``!+RW^="\M_GA.N@N83^\`#")M*
XM_G1P#"QX``1.KO\N(FW^>"QX``1.KOYB80`!$$JM_I9G'B!M_I9*J``49PHB$
XM2"QX``1.KOX^+RW^EDZZ`?Q83TJM_IIG"B\M_II.N@%\6$],WT#D3EU.=6ENX
XM='5I=&EO;BYL:6)R87)Y`&=R87!H:6-S+FQI8G)A<GD``&EN<'5T+F1E=FEC,
XM90``3E7_^$CG(`*1R"E(`0@I2`$,(D@L>``$3J[^VB!`0^@`7$AX)18K2?_\8
XM3KH!LEA/*4`!#"!M__PL>``$3J[^@"!M__PL>``$3J[^C"M`__A*@&?@(FW_Y
XM^"QX``1.KOZ&2JP!#&8$<`%@+G``(&P!#!`H``]R`20!X:(@`DZN_L(O+`$,]
XM3KH"2EA/*4`!"$J`9@1P`6`"<`!,WT`$3EU.=4JL`0AG#B\L`0A.N@?T6$]"%
XMK`$(2JP!#&<.+RP!#$ZZ`<Y83T*L`0QP`$YU3G5(YP,R)F\`&"XO`!QP_RQXA
XM``1.KOZV+``,!@#_9@1P`&!(<"(B/``!``%.KO\Z)$`@"F8,<``0!DZN_K!PZ
XM`&`J)4L`"B`'%4``"15\``0`"$(J``X51@`/D\E.KO[:)4``$")*3J[^GB`*=
XM3-],P$YU2.<`$B9O``PB2RQX``1.KOZ8<``0*P`/3J[^L")+<").KO\N3-]("
XM`$YU3E7__$CG`1(F;P`8+B\`'"`'(CP``0`!+'@`!$ZN_SHK0/_\2H!G%B!`Z
XM$7P`!0`(0B@`"2(',4$`$B%+``Y,WTB`3EU.=4CG`!(F;P`,%WP`_P`(,'S_\
XM_R=(`!0G2``8<``P*P`2(DLL>``$3J[_+DS?2`!.=4Y5__A(YP$"/B\`&D*M<
XM__QP$'(!+'@`!$ZN_SIR`#('+P%(>@!J+P`K0/_X3KH/,$_O``PL>``$3J[_7
XM?")M__A.KOYZ2H!F%$*G+RW_^$ZZ_J!03RM`__Q*@&8.(FW_^'`0+'@`!$ZN)
XM_RXL>``$3J[_=B`M__Q,WT"`3EU.=41.150N4$]25"Y86%A86`!$3D54+E!/C
XM4E0N)6QD`#``1$Y%5"Y53DE4+@``)7,E<P``2.<`,B9O`!`D:P`*(`MG+"QXQ
XM``1.KO]\+PMA``"Z6$]*@&;T+PM.NOZ(6$\L>``$3J[_=B)*<!!.KO\N3-],O
XM`$YU3E7_^$CG,#*5RB`*9CX@;0`(+'@`!$ZN_HPF0"!+(`AG*C`K`!P,0``A,
XM9@Y"IR\+80`&[%!/)$!@!A=\``$`'R)++'@`!$ZN_H9@OB!M``C0_``8(FT`!
XM"")I`!2SR&<@<``@;0`($"@`#W(!)`'AHG8`%@#GH2`"+'@`!$ZN_LX@"F<$+
XM($I@`I'((`A,WTP,3EU.=4Y5__Q(YS`2)F\`'"!++'@`!$ZN_HPK0/_\2H!GN
XM#B!`$7P``0`?(D!.KOZ&0>L`&")K`!2SR&<8<``0*P`/<@$D`>&B=@`6`.>A%
XM(`).KO[.2JW__%;`1`!(@$C`3-](#$Y=3G5.50``3EU.=4Y5_\Q(YP<2)F\`/
XM4#XO`%8<+P!;&B\`7R`+9@1'^OZ,+PM(;?_080`%]E!/*T#_S')^N@%C`BH!K
XM#`4`@60">H&\`6,"+`$,!@"!9`)\@2!`2J@`(F=<.WP`(/_L<@`R!RM!_^@K:
XM0/_\*T#_WAM&_]ER`!(%*T'_VB!H`")#[?_0+'@`!$ZN_I)(;?_080`$TEA/)
XM$"W_[TH`9A@@+?_H(&W_S#%``#0O"&$`!D@@+?_,8`HO+?_,80`&%G``3.U(A
XMX/^X3EU.=4Y5__1(YS<R)F\`-"XO`#Q\`$HK`#9G!G#_8``!1$J'9P`!$D'KT
XM`"8L>``$3J[^_B1`($H@"&80($M.KOZ,)$`@2B`(9P``[G`'L"H`"&8N2JL`0
XM/&<$4ZL`/$JJ`"1G$")J`"@@*@`D+'@`!$ZN_RXB2G`P+'@`!$ZN_RY@H#`J:
XM`!P,0``D9R(,0``C9P@,0``B9@``C!=\``$`-B)*+'@`!$ZN_H9@`/]V("H`0
XM("(J`"22@"H!NH=N*B!J`"C1P"`%(FT`#&`"$MA3@&3ZGH7<A=NM``PB2BQX.
XM``1.KOZ&8`#_/"!J`"C1P"`'(FT`#&`"$MA3@&3ZW(??J@`@?@`L>``$3J[_.
XM?!5\``4`"$'K`!0B2DZN_Q!.KO]V8`#_`!5\``$`'R)*+'@`!$ZN_H9@`/[LP
XM+PMA``3T6$]**P`V9QQP`!`K``]R`20!X:)V`!8`YZ$@`BQX``1.KO[.(`9,5
XMWTSL3EU.=4CG!S(F;P`<)&\`("XO`"1\`$HK`#9G!'#_8#!*AV<J($LL>``$8
XM3J[^@"\'+PHO"V$`_F9/[P`,*@#<A4J%:PK5Q9Z%2BL`-F?2(`9,WTS@3G5(J
XMYP$0)F\`#"XO`!`G1P`X3-\(@$YU3E7_R$CG`S(F;P!4)&\`6"XO`%PL!TJKE
XM`#AG>D*G+PMA``+L4$]*@&MH<#`B/``!``$L>``$3J[_.B!`,7P`)``<<@`R5
XM*P`T(4$`&"%+`"PA2P`.*T#_S"`'<@%.KO\Z(&W_S"%``"@A1P`D(`<B2BQH$
XM`"A@`AS94X!D^B!K`"(B;?_,+'@`!$ZN_I)2JP`\8$9\_V!".WP`)/_L<``P-
XM*P`T*T#_Z"M+__PK2__>*TK_^"M'__0@:P`B0^W_T"QX``1.KOZ22&W_T&$`+
XM`?Y83THM_^]G`GS_+PMA``.`(`9,[4S`_[1.74YU3E7_T$CG`!(F;P!`.WP`8
XM(__L<``P*P`T*T#_Z"M+__PK2__>(&L`(D/M_]`L>``$3J[^DDAM_]!A``&F/
XM+HMA``,R3.U(`/_(3EU.=4Y5_]!(YP<2)F\`3!XO`%,\+P!6&B\`6SM\`";_!
XM['``,"L`-"M`_^@K2__\*TO_WG``,`9(0$)`<@`2!>&!@(%R`!('@($K0/_X+
XM(&L`(D/M_]`L>``$3J[^DDAM_]!A``$T+HMA``+`3.U(X/^\3EU.=4Y5_YQ(F
XMYP`2)F\`="`+9@1'^OI:+PM(>OI62'KZ7DAM_Z5.N@D*3^\`$$/M_Z4L>``$0
XM3J[^>BM`_YQG0D*G0J=.NOA^.WP`)?_L0JW_Z$*M__PK0/_>*T#_H"!M_YQ#W
XM[?_0+'@`!$ZN_I)(;?_080``LBZM_Z!.NOBX3^\`#$JM_YQ6P$0`2(!(P$S?J
XM2`!.74YU3E7_S$CG`!(F;P!$.WP`(O_L<``P*P`T*T#_Z"M+__PK2__>(&L`B
XM(D/M_]`L>``$3J[^DE*K`#Q"JP`X2&W_T"\+80``D%!/0>L`)BQX``1.KO[^S
XM*T#_S$J`9@X@2TZN_HPK0/_,2H!G%B!M_\P1?``!`!\B2"QX``1.KOZ&8,@O0
XM"V$``7I,[4@`_\1.74YU2.<@$B9O`!!P![`K``AG'"!K``YP`!`H``]R`20!D
XMX:(@`BQX``1.KO["8-PL>``$3J[_?")+3J[_!$ZN_W9,WT@$3G5.5?_Z2.<!'
XM,B9O`!Y^`"`K`#RPJP`X;U8@2RQX``1.KOZ`($M.KOZ,)$!P![`J``AF,$I'D
XM9@9^`!XJ`!^U[0`,9QI*J@`D9PPB:@`H("H`)$ZN_RXB2G`P3J[_+E.K`#Q@E
XMK$'K`"8B2DZN_PI@H"`'2,!,WTR`3EU.=4Y5_]!(YP`R)F\`1"1O`$AP0"(\8
XM``$``2QX``1.KO\Z($`1?``$``@K0/_\</].KOZV(&W__!%```^3R4ZN_MH@5
XM;?_\(4``$$/H`!0O"4ZZ!_P@;?_\T/P`)BZ(3KH'[EA/("L`&"!M__PQ0``T_
XM)T@`+"`*9R8O"DAZ^!1(>O@<2&W_T4ZZ!LA/[P`00^W_T2QX``1.KOYZ)T``;
XM#B!M__PA:P`.`"(@"$S?3`!.74YU2.<`$B9O``QP`!`K``\L>``$3J[^L")+Z
XM<$!.KO\N3-](`$YU2.<P$B9O`!1!ZP`8(FL`%+/(9@Q!ZP`J(FL`)K/(9QQPR
XM`!`K``]R`20!X:)V`!8`YZ$@`BQX``1.KO[.3-](#$YU``!.5?_\2.<A,"9O`
XM`!PD;P`@+B\`)"MK`";__$J'9RQ*K```9VP@+```(@!"04A!(&W__#%!``HD6
XM/```___`@C%```Z3R2E)``!@1B!M__P,:`$@``AF.@QH`2(`#&8R2JP``&86A
XM<``P*``*2$!"0'(`,B@`#H"!*4```"`*0D!(0#%```H@"@*```#__S%```Y,$
XMWPR$3EU.=4Y5_\1(YR<P)F\`7"1O`&!^`'P`>@!P`!M\`"#_^W(`*T'_]G3_(
XM*T+_\D'M_]`;0/_Q&T#__"M!_^0K0?_H*TC_S$H39T)P`!`3<AA=06LXL'L0[
XM"&;V3OL0!``C8```(``@8```%@`K8```#``M8````GX!8`Y\`6`*>@%@!AM\L
XM``'__%*+8+H0$W(PL`%F!E*+&T'_^W`JL!-F$"!20^@`!"2)*U#_]E*+8`Y(L
XM;?_V+PM.N@2$4$_7P!`3<BZP`68F4HMP*K`39A`@4D/H``0DB2M0__)2BV`.7
XM2&W_\B\+3KH$5E!/U\`0$W)LL`%F"AM\``'_\5*+8`AR:+`!9@)2BQ`;<@`2F
XM`!M`__!P,%U`:P`"5+)[``AF]$[[``0`8V```BH`<V```>@`6&```7X`>&``>
XM`7@`<&```5X`;V```0P`=6```.(`9&````)*+?_Q9PP@4D/H``0DB2`08`H@C
XM4D/H``0DB2`0*T#_[&P*<@%$K?_L*T'_Z$JM_^AG!'`M8`I*!F<$<"M@`G`@D
XM&T#_T'``$`8B+?_H@H!P`!`%@H!G"%*M_\Q2K?_D+RW_["\M_\Q.N@+F4$\KR
XM0/_(("W_\DJ`:@9R`2M!__(@+?_((BW_\I*`2.T``O_$;RX@;?_,(DC3P6`"$
XM$MA3@&3Z<``0+?_[(BW_Q"!M_\Q@`A#`4X%D^B`M__(K0/_(T:W_Y$'M_]`K)
XM2/_,2@=G``%0&WP`(/_[8``!1DHM__%G#"!20^@`!"2)(!!@"B!20^@`!"2)$
XM(!`K0/_L8`#_8DHM__%G#"!20^@`!"2)(!!@"B!20^@`!"2)(!`K0/_L2BW_3
XM_&<2(&W_S!#\`#!R`2M!_^0K2/_,+P`O+?_,3KH"0%!/*T#_R&``_R@;?``P(
XM__L@+?_R2H!J!G`(*T#_\DHM__%G#"!20^@`!"2)(!!@"B!20^@`!"2)(!`KQ
XM0/_L2BW__&<6(&W_S!#\`#`0_`!X<@(K0?_D*TC_S"\`+RW_S$ZZ`AQ03RM`Y
XM_\AP6+`M__!F`/Z^2&W_T$ZZ`5!83V``_K`@4D/H``0DB2)0*TG_S&8(0?H`W
XMW"M(_\P@;?_,2AAF_%.(D>W_S"M(_^0@+?_R2H!K*K'`;R8K0/_D8"!P`2M`]
XM_^0@4D/H``0DB2`0&T#_T$(M_]%@!G``8```C"`M_^0B+?_VLH!L"'0`*T+_&
XM]F`$D:W_]DH'9S93K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.)3K?_V9
XM;4AP`!`M__LO`"!M`!!.D%A/8.A3K?_V;1)P`!`M__LO`"!M`!!.D%A/8.A3\
XMK?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.(@"TS?#.1.74YU``!.5?_VB
XM2.<!,"9O`!XD;P`B*VT`$/_V'AI*!V<T<"6^`&8BL!)F!%**8!HO"TAM__8OY
XM"F$`^\Q/[P`,*T#_^F<$)$!@TG``$`<O`$Z36$]@QDS?#(!.74YU2.<@,"9O^
XM`!`D2TH29R1P`!`20>P`!0@P``$(`&<*<@`2`'0@DH)@!'(`$@`4@5**8-@@Y
XM"TS?#`1.=0``````````<&$@+P`((&\`!$Y5__0B3W(*3KH!7`9!`#`2P4J``
XM9O`@"1#AO\EF^D(0D(].74YU```@+P`((&\`!$Y5__0B3R(``D$`!P9!`#`2=
XMP>:(9O`@"1#AO\EF^D(0D(].74YU```P,3(S-#4V-S@Y86)C9&5F("\`""!ON
XM``1#[P`$,@`"00`/$OL0W.B(9O(@"2(/6($0X;*)9OI"$)"!3G4@;P`$(DAR3
XM`'``+P(,$``K9P8,$``M9@)22!`8!```,&T2#```"6X,)`'E@=*"TH'2@&#F4
XM#!$`+68"1($D'R`(4X`@;P`(((&0B4YU+P<N+P`(4JP!%"`'(&P!$!#`*4@!]
XM$"X?3G5.50``2.<`,"9O`!`D;P`40JP!%"E+`1!(;0`0+PI(>O_&3KK^/B!L+
XM`1!"$"`L`11,[0P`__A.74YU2H!J```>1(!*@6H```Q$@6$``"!$@4YU80``T
XM&$2`1(%.=4J!:@``#$2!80``!D2`3G4O`DA!-`%F```B2$!(04A"-`!G```&+
XMA,$P`DA`-`"$P3`"2$(R`B0?3G4O`W80#$$`@&0```;AF5%##$$(`&0```;I3
XMF5E##$$@`&0```;EF55#2D%K```&XYE30S0`YJA(0D)"YJI(0X#!-@`P`C0#[
XM2$'$P9""9```"%-#T(%D_G(`,@-(0^>X2$#!028?)!].=2!O``0@B%B00J@`(
XM!"%(``A.=0`````#\@```^H```!&```````@("`@("`@("`H*"@H*"`@("`@H
XM("`@("`@("`@("`@($@0$!`0$!`0$!`0$!`0$!"$A(2$A(2$A(2$$!`0$!`0@
XM$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!`0$!$!`0$!`0@H*"@H*"`@("`@("B
XM`@("`@("`@("`@("`@(0$!`0("`@("`@("`@("@H*"@H("`@("`@("`@("`@D
XM("`@("`@2!`0$!`0$!`0$!`0$!`0$(2$A(2$A(2$A(00$!`0$!`0@8&!@8&!6
XM`0$!`0$!`0$!`0$!`0$!`0$!`0$0$!`0$!""@H*"@H("`@("`@("`@("`@(":
XC`@("`@("`A`0$!`@`````````````````````````````_("E
X``
Xend
Xsize 5840
END_OF_FILE
if test 8214 -ne `wc -c <'snetkeys.uu'`; then
    echo shar: \"'snetkeys.uu'\" unpacked with wrong size!
fi
# end of 'snetkeys.uu'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.