[comp.sources.amiga] v90i087: NetKeys 1.0 - intercept input events and send to attached amiga, Part01/02

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

Submitted-by: walker@sas.UUCP (Doug Walker)
Posting-number: Volume 90, Issue 087
Archive-name: comm/dnet/netkeys-1.0/part01

[ uuencoded executables included.  ...tad ]

NetKeys is a DNET server that, on command, will intercept all input
mouse and keyboard events and send them to an attached Amiga.  This
means if you have two Amigae sitting next to each other, you can
control both of them with a single mouse and keyboard.  A Software
Distillery project by Doug Walker, based on POPCLI by John Toebes and
DNET by Matt Dillon.

#!/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 netkeys.c netkeys.doc
#   netkeys.h nkutil.c snetkeys.c snetkeys.uu
# Wrapped by tadguy@xanth on Sat Feb 24 12:37:43 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'\" \(673 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
X
XCFLAGS = -cwusf -v
XLC2FLAGS = 
XCLIENTOBJS = netkeys.o  nkutil.o dnetlib.o
XSERVEROBJS = snetkeys.o nkutil.o dnetlib.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 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 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 673 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'netkeys.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'netkeys.c'\"
else
echo shar: Extracting \"'netkeys.c'\" \(8812 characters\)
sed "s/^X//" >'netkeys.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 * Based on POPCLI III, written by John Toebes
X * Uses Matt Dillon's DNET
X */
X
X#include "netkeys.h"
X
Xstruct DChannel *chan;
X
X/* Declarations for CBACK */
Xextern BPTR _Backstdout;         /* standard output when run in background */
Xlong _BackGroundIO = 1;          /* Flag to tell it we want to do I/O      */
Xlong _stack = 4000;              /* Amount of stack space our task needs   */
Xchar *_procname = "NetKeys I";   /* The name of the task to create         */
Xlong _priority = 20;             /* The priority to run us at              */
X
Xint InitDevice(int);
Xint TermDevice(void);
X
Xstruct InputEvent * __regargs myhandler(struct InputEvent *ev, GLOBAL_DATA *gptr)
X{
X   struct InputEvent *ep, *laste;
X   struct NETKEYMSG *nkm;
X
X   if(gptr->state < EM_DOIT) return(ev);  /* In the process of quitting */
X
X   /* run down the list of events to see if they pressed the magic button */
X   for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
X   {
X      if(ep->ie_Class == IECLASS_RAWKEY || ep->ie_Class == IECLASS_RAWMOUSE)
X      {
X         if ((ep->ie_Class == IECLASS_RAWKEY)    &&
X              ep->ie_Code  == gptr->dokey        &&
X             (ep->ie_Qualifier & IEQUALIFIER_LCOMMAND))
X         {
X            /* Remove the event from the chain */
X            if (laste == NULL)
X               ev = ep->ie_NextEvent;
X            else
X               laste->ie_NextEvent = ep->ie_NextEvent;
X
X            /* Telling us to toggle... */
X            gptr->state = (gptr->state == EM_DOIT ? EM_LURK : EM_DOIT);
X
X            Signal(gptr->buddy, 1 << gptr->nkmp->mp_SigBit);
X         }
X         else if(gptr->state != EM_LURK)
X         {
X            /* Remove the event from the chain */
X            if (laste == NULL)
X               ev = ep->ie_NextEvent;
X            else
X               laste->ie_NextEvent = ep->ie_NextEvent;
X
X            if(!(nkm=(struct NETKEYMSG *)GetMsg(gptr->rtnp)) )
X            {
X               if(gptr->nmsgs > MAXMSGS ||
X                  !(nkm = AllocMem(NKMSZ, MEMF_CLEAR|MEMF_PUBLIC)))
X               {
X                  gptr->state = EM_LURK;
X                  break;
X               }
X            }
X            /* Copy the data and queue it to our port */
X            nkm->ie = *ep;
X            PutMsg((struct MsgPort *)gptr->nkmp, (struct Message *)nkm);
X         }
X      }
X      else
X         laste = ep;
X   }
X
X   /* pass on the pointer to the event */
X   return(ev);
X}
X
X
Xint _main(char *cmd);
Xint _main(char *cmd)
X{
X   struct MsgPort  *inputDevPort = NULL;
X   struct MsgPort  *oldport;
X   struct IOStdReq *inputRequestBlock = NULL;
X   struct Interrupt handlerStuff;
X   GLOBAL_DATA global;
X   struct NETKEYMSG *msg, *oldmsg, *tmpmsg;
X   int quit = 0;
X   int force = 0;
X
X   MSG(_Backstdout, BANNER);
X
X   memset(&global, 0, sizeof(global));
X   global.buddy = FindTask(0L);
X   global.dokey  = DEFDOKEY;
X   global.state = EM_LURK;
X   if(!(global.rtnp = CreatePort(0,0)))
X   {
X      MSG(_Backstdout, "Can't CreatePort\n");
X      goto abort;
X   }
X
X   oldport = FindPort(NKMPNAME);
X
X   if(cmd && *cmd)
X   {
X      long tmpl = DEFDOKEY;
X      while(*cmd != ' ') cmd++;
X      while(*cmd == ' ') cmd++;
X      if(cmd[0] == '0' && cmd[1] == 'x')
X      {
X        stch_l(cmd+2, &tmpl);
X        global.dokey = tmpl;
X      }
X      else if(cmd[0] == 'Q' || cmd[0] == 'q')
X      {
X         quit = 1;
X      }
X      else if(cmd[0] == 'F' || cmd[0] == 'f')
X      {
X         force = 1;
X      }
X   }
X
X   if(!(oldmsg = AllocMem(NKMSZ, MEMF_CLEAR|MEMF_PUBLIC)))
X   {
X      MSG(_Backstdout, "No memory\n");
X      goto abort;
X   }
X   if(quit)
X   {
X      if(!oldport)
X      {
X         MSG(_Backstdout, "Netkeys not installed\n");
X         goto abort;
X      }
X      else
X      {
X         oldmsg->msgtype = NKM_QUIT;
X         oldmsg->ie.ie_Class = force;
X         oldmsg->m.mn_Node.ln_Type = NT_MESSAGE;
X         oldmsg->m.mn_ReplyPort = global.rtnp;
X         PutMsg(oldport, (struct Message *)oldmsg);
X         WaitPort(global.rtnp);
X         MSG(_Backstdout, "NetKeys removed\n");
X         goto abort;      
X      }
X   }
X
X   if(oldport)
X   {
X      /* Modify the hotkey for the existing guy */
X      oldmsg->msgtype = NKM_CONTROL;
X      oldmsg->ie.ie_Class = global.dokey;
X      PutMsg(oldport, (struct Message *)oldmsg);
X      WaitPort(global.rtnp);
X      MSG(_Backstdout, "NetKeys now using 0x%02.2x\n");
X      goto abort;
X   }
X
X   FreeMem(oldmsg, NKMSZ);
X   oldmsg = NULL;
X
X   MSG(_Backstdout, INSTR);
X
X   if (
X       ((global.nkmp = CreatePort(NKMPNAME, 0)) == NULL)                    ||
X
X       ((inputDevPort = CreatePort(0,0)) == NULL)                           ||
X
X       InitDevice(NKM_HANDLER)                                              ||
X
X       ((inputRequestBlock = 
X               CreateIOReq(inputDevPort, sizeof(struct IOStdReq))) == NULL) ||
X
X      OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
X      {
X         MSG(_Backstdout, "Can't initialize\n");
X         goto abort;
X      }
X
X   MSG(_Backstdout, "NetKeys installed\n");
X
X   if(_Backstdout) Close(_Backstdout);
X   _Backstdout = 0;
X
X   handlerStuff.is_Data = (APTR)&global;
X   handlerStuff.is_Code = (VOID (*)()) myhandler;
X   handlerStuff.is_Node.ln_Pri = 52;
X
X   inputRequestBlock->io_Command = IND_ADDHANDLER;
X   inputRequestBlock->io_Data    = (APTR)&handlerStuff;
X
X   DoIO((struct IORequest *)inputRequestBlock);
X
X   while(global.state >= EM_DOIT && 
X        !(SIGBREAKF_CTRL_C & Wait((1<<global.nkmp->mp_SigBit) | SIGBREAKF_CTRL_C)))
X   {
X      while(msg=(struct NETKEYMSG *)GetMsg(global.nkmp))
X      {
X         if(msg->msgtype == NKM_QUIT)
X         {
X            ReplyMsg((struct Message *)msg);
X            goto abort;
X         }
X         else if(msg->msgtype == NKM_CONTROL)
X         {
X            global.dokey = msg->ie.ie_Code;
X            ReplyMsg((struct Message *)msg);
X            continue;
X         }
X
X         tmpmsg = NULL;
X         if( msg->ie.ie_Class == IECLASS_RAWMOUSE &&
X             msg->ie.ie_Code == IECODE_NOBUTTON)
X         {
X            while((tmpmsg = (struct NETKEYMSG *)GetMsg(global.nkmp)) &&
X                   tmpmsg->msgtype == NKM_IEVENT &&
X                   tmpmsg->ie.ie_Class == IECLASS_RAWMOUSE &&
X                   tmpmsg->ie.ie_Code == IECODE_NOBUTTON &&
X                   (tmpmsg->ie.ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE))
X            {
X               tmpmsg->ie.ie_X += msg->ie.ie_X;
X               tmpmsg->ie.ie_Y += msg->ie.ie_Y;
X               PutMsg(global.rtnp, (struct Message *)msg);
X               msg = tmpmsg;
X               tmpmsg = NULL;
X            }
X         }
Xputit:
X         if(DWrite(chan, (char *)&msg->ie, IESZ) != IESZ)
X            break;
X
X         PutMsg(global.rtnp, (struct Message *)msg);
X
X         if(tmpmsg)
X         {
X            msg = tmpmsg;
X            tmpmsg = NULL;
X            goto putit;
X         }
X      }
X   }
X
Xabort:
X   TermDevice();
X
X   if (inputRequestBlock != NULL)
X   {
X      if (inputRequestBlock->io_Device != NULL)
X      {
X         inputRequestBlock->io_Command = IND_REMHANDLER;
X         inputRequestBlock->io_Data = (APTR)&handlerStuff;
X         DoIO((struct IORequest *)inputRequestBlock);
X
X         CloseDevice((struct IORequest *)inputRequestBlock);
X      }
X      DeleteIOReq(inputRequestBlock);
X   }
X
X   if (inputDevPort != NULL)  DeletePort(inputDevPort);
X
X   if(global.nkmp)
X   {
X      while(msg=(struct NETKEYMSG *)GetMsg(global.nkmp)) FreeMem(msg, NKMSZ);
X      DeletePort(global.nkmp);
X   }
X
X   if(global.rtnp)
X   {
X      while(msg=(struct NETKEYMSG *)GetMsg(global.rtnp)) FreeMem(msg, NKMSZ);
X      DeletePort(global.rtnp);
X   }
X
X   if(_Backstdout) Close(_Backstdout);
X
X   return(0);
X}
X
Xint active = 0;
Xstruct DChannel *chan = NULL;
X
Xint InitDevice(int which)
X{
X   if(active) return(1);
X   active = 1;
X
X   if(!(chan=(struct DChannel *)DOpen(NULL, (uword)(PORT_NETKEYS), 127, 127)))
X      return(1);
X
X   return(0);
X}
X
Xint TermDevice(void)
X{
X   if(!active) return(1);
X
X   active = 0;
X
X   if(chan) DClose(chan);
X
X   chan = NULL;
X
X   return(0);
X}
X
Xvoid MemCleanup(void);
Xvoid MemCleanup(){}
END_OF_FILE
if test 8812 -ne `wc -c <'netkeys.c'`; then
    echo shar: \"'netkeys.c'\" unpacked with wrong size!
fi
# end of 'netkeys.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'\" \(6313 characters\)
sed "s/^X//" >'netkeys.doc' <<'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  | ||    Dave Baker     Ed Burnette  Jay Denebeim John Mainwaring     */
X/* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
X/* ======                    BBS:(919)-471-6436                              */ 
X/*                                                                           */
X/* Doug Walker, 405 B3 Gooseneck Dr, Cary, NC 27513 USA
X/* USENET: ...mcnc!rti!sas!walker   BIX: djwalker   PLINK: dwalker           */
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, including 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 authors 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 should 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.  Thus, at the press of a key, you can be typing into a CLI on the
Xremote machine.  (Maybe this isn't a very common problem, but I wanted it
Xbad enough to write it :-)
X
XNETKEYS uses Matt Dillon's DNET networking package.  DNET is freely redistrib-
Xutable, available on Fred Fish #294 and on all the major nets.  To use NETKEYS
Xeffectively, you will have to have the two machines sitting next to each other,
Xso you should connect them with a simple null modem cable and use the following
Xcommand to start DNET on both machines:
X
XRUN DNET -s -X -h0 -Z0 -P0 -m0 -b19200
X
X(If you have the older version 1 of DNET, just use RUN DNET -s).  After the
XDNET windows come up on both machines, select STARTDNET from one of the
Xmachines' menus.  If the other machines' window does not disappear, use
Xthe QUITDNET command or the BREAK command to get the DNET window back and
Xtry it again.  DNET uses the file S:DNET.SERVERS to locate server programs;
Xyou 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.
X
XIf you would like to use a key other than Left-Amiga-R, you can pass a parameter
Xof the form '0x##' where ## is the hexadecimal raw key code for the key to be
Xused.  For example, NETKEYS 0x13 would use Left-Amiga-R, just like the default; 
XNETKEYS 0x14 would use Left-Amiga-T, and so forth.  You can change the key 
XNetKeys uses after invoking it with the same command.
X
XIf you want to get rid of NETKEYS, just type NETKEYS QUIT.
X
XHave fun! 
X
X--Doug
X
X------------------------------DISTRIBUTION LIST
X
Xchannel.h                   1724
Xdnet.h                      6639
Xnkutil.c                    2509
Xmakefile                     673
Xnetkeys                     7788
Xsnetkeys                    5084
Xnetkeys.c                   8812
Xdnetlib.c                  10399
Xsnetkeys.c                  3022
Xnetkeys.h                   3254
Xnetkeys.doc                 6311
END_OF_FILE
if test 6313 -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'\" \(3254 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/intuition.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 <proto/graphics.h>*/
X#include <string.h>
X#include <stdio.h>
X
X#include "dnet.h"
X
X#define PORT_NETKEYS 9494
X
X
X
X#define NKMPNAME "NetKeys 1.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) 471-6436\n"
X
X#define INSTR  "Left-Amiga-R to toggle machines;  Use 'NetKeys QUIT' to remove\n"\
X               "Installing...\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
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_IEVENT  0
X#define NKM_QUIT    1
X#define NKM_CONTROL 2
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   char  work[256];
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
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 *);
END_OF_FILE
if test 3254 -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'\" \(3022 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
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   struct MsgPort  *inputDevPort = NULL;
X   struct IOStdReq *inputRequestBlock = NULL;
X   struct InputEvent ie;
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      OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
X   {
X      goto abort;
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   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      ie.ie_TimeStamp.tv_secs = 
X      ie.ie_TimeStamp.tv_micro = 0;
X      ie.ie_NextEvent = NULL;
X      DoIO(inputRequestBlock);
X   }
X
Xabort:
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 3022 -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'\" \(7155 characters\)
sed "s/^X//" >'snetkeys.uu' <<'END_OF_FILE'
Xbegin 666 snetkeys
XM```#\P`````````"``````````$```2E````10```^D```2E3E7_W$CG(0"1;
XMR"M(__@K2/_\80`!$DJ`9@``OD*G0J=.N@'.4$\K0/_\2H!G``"J2'@`,"\`J
XM3KH"3E!/*T#_^$J`9P``E")`0?H`SG``(@`L>``$3J[^1$J`9GP@;?_X,7P`>
XM"P`<0B@`'G`6(4``)$'M_^(B;?_X(T@`*'``(&P!!!`H``]R`20!X:(`0A``7
XM(`(L>``$3J[^PBX`"`<`#&8V2'@`%DAM_^(O+`$$3KH&7D_O``QR%K"!9AQP8
XM`"M`__0K0/_P0JW_XB)M__@L>``$3J[^.&"D80``Z$JM__AG'B!M__A*J``4R
XM9PHB2"QX``1.KOX^+RW_^$ZZ`=!83TJM__QG"B\M__Q.N@%46$],WP"$3EU.T
XM=6EN<'5T+F1E=FEC90``3E7_^"\"D<@I2`$$*4@!"")(+'@`!$ZN_MH@0$/H(
XM`%Q(>"46*TG__$ZZ`:A83RE``0@@;?_\+'@`!$ZN_H`@;?_\+'@`!$ZN_HPK;
XM0/_X2H!GX")M__@L>``$3J[^ADJL`0AF!'`!8"YP`"!L`0@0*``/<@$D`>&B%
XM(`).KO["+RP!"$ZZ`CQ83RE``01*@&8$<`%@`G``)!].74YU2JP!!&<.+RP!1
XM!$ZZ!]I83T*L`01*K`$(9PXO+`$(3KH!PEA/0JP!"'``3G5.=4CG`S`F;P`4)
XM+B\`&'#_+'@`!$ZN_K8L``P&`/]F!'``8$AP(B(\``$``4ZN_SHD0"`*9@QP2
XM`!`&3J[^L'``8"HE2P`*(`<50``)%7P`!``(0BH`#A5&``^3R4ZN_MHE0``0?
XM(DI.KOZ>(`I,WPS`3G4O"R9O``@B2RQX``1.KOZ8<``0*P`/3J[^L")+<").7
XMKO\N)E].=4Y5__Q(YP$0)FT`""XM``P@!R(\``$``2QX``1.KO\Z*T#__$J`7
XM9Q8@0!%\``4`"$(H``DB!S%!`!(A2P`.3-\(@$Y=3G4O"R9O``@7?`#_``@P3
XM?/__)T@`%"=(`!AP`#`K`!(B2RQX``1.KO\N)E].=4Y5__@O!SXM``I"K?_\6
XM<!!R`2QX``1.KO\Z<@`R!R\!2'H`:"\`*T#_^$ZZ"B9/[P`,+'@`!$ZN_WPBI
XM;?_X3J[^>DJ`9A1"IR\M__A.NOZJ4$\K0/_\2H!F#B)M__AP$"QX``1.KO\NB
XM+'@`!$ZN_W8@+?_\+A].74YU1$Y%5"Y03U)4+EA86%A8`$1.150N4$]25"XE1
XM;&0`,`!$3D54+E5.250N```E<R5S``!(YP`P)F\`#"1K``H@"V<L+'@`!$ZNR
XM_WPO"V$``+983TJ`9O0O"TZZ_I183RQX``1.KO]V(DIP$$ZN_RY,WPP`3G5.(
XM5?_X2.<P,I7*(`IF/B!M``@L>``$3J[^C"9`($L@"&<J,"L`'`1``"%F#D*G0
XM+PMA``;:4$\D0&`&%WP``0`?(DLL>``$3J[^AF"^(&T`"-#\`!@L;0`((FX`T
XM%+/(9QQP`!`N``]R`20!X:)V`!8`YZ$@`BQX``1.KO[.(`IG!"!*8`*1R"`(R
XM3-],#$Y=3G5.5?_\2.<P$"9M``@@2RQX``1.KOZ,*T#__$J`9PX@0!%\``$`%
XM'R)`3J[^AD'K`!@B:P`4L\AG&'``$"L`#W(!)`'AHG8`%@#GH2`"3J[^SDJMJ
XM__Q6P$0`2(!(P$S?"`Q.74YU3E4``$Y=3G5.5?_,2.<'$"9M``@^+0`.'"T`T
XM$QHM`!<@"V8$1_K^D"\+2&W_T&$`!>A03RM`_\QR?KH!8P(J`0P%`(%D`GJ!D
XMO`%C`BP!#`8`@60"?($@0$JH`")G7#M\`"#_['(`,@<K0?_H*T#__"M`_]X;%
XM1O_9<@`2!2M!_]H@:``B0^W_T"QX``1.KOZ22&W_T&$`!,183Q`M_^]*`&880
XM("W_Z"!M_\PQ0``T+PAA``8V("W_S&`*+RW_S&$`!@AP`$SM".#_O$Y=3G5.E
XM5?_T2.<W,"9M``@N+0`0?`!**P`V9P9P_V```4)*AV<``1!!ZP`F+'@`!$ZN)
XM_OXD0"!*(`AF$"!+3J[^C"1`($H@"&<``.QP![`J``AF+DJK`#QG!%.K`#Q*O
XMJ@`D9Q`B:@`H("H`)"QX``1.KO\N(DIP,"QX``1.KO\N8*`P*@`<!$``(F<,D
XM4T!G"%-`9QA@``",%WP``0`V(DHL>``$3J[^AF``_W@@*@`@(BH`))*`*@&Z&
XMAVXJ(&H`*-'`(`4B;0`,8`(2V%.`9/J>A=R%VZT`#")*+'@`!$ZN_H9@`/\^H
XM(&H`*-'`(`<B;0`,8`(2V%.`9/K<A]^J`"!^`"QX``1.KO]\%7P`!0`(0>L`U
XM%")*3J[_$$ZN_W9@`/\"%7P``0`?(DHL>``$3J[^AF``_NXO"V$`!.183THK-
XM`#9G''``$"L`#W(!)`'AHG8`%@#GH2`"+'@`!$ZN_LX@!DS?#.Q.74YU2.<'A
XM,"9O`!@D;P`<+B\`('P`2BL`-F<$</]@,$J'9RH@2RQX``1.KOZ`+P<O"B\+R
XM80#^:$_O``PJ`-R%2H5K"M7%GH5**P`V9](@!DS?#.!.=4CG`1`F;P`,+B\`_
XM$"='`#A,WPB`3G5.5?_(2.<#,B9M``@D;0`,+BT`$"P'2JL`.&=Z0J<O"V$`B
XM`N!03TJ`:VAP,"(\``$``2QX``1.KO\Z($`Q?``D`!QR`#(K`#0A00`8(4L`Q
XM+"%+``XK0/_,(`=R`4ZN_SH@;?_,(4``*"%'`"0@!R)*+&@`*&`"'-E3@&3ZO
XM(&L`(B)M_\PL>``$3J[^DE*K`#Q@1GS_8$([?``D_^QP`#`K`#0K0/_H*TO_#
XM_"M+_]XK2O_X*T?_]"!K`")#[?_0+'@`!$ZN_I)(;?_080`!\EA/2BW_[V<"-
XM?/\O"V$``W`@!DSM3,#_M$Y=3G5.5?_0+PLF;0`(.WP`(__L<``P*P`T*T#_*
XMZ"M+__PK2__>(&L`(D/M_]`L>``$3J[^DDAM_]!A``&<+HMA``,D)FW_S$Y=8
XM3G5.5?_02.<'$"9M``@>+0`//"T`$AHM`!<[?``F_^QP`#`K`#0K0/_H*TO_7
XM_"M+_]YP`#`&2$!"0'(`$@7A@8"!<@`2!X"!*T#_^"!K`")#[?_0+'@`!$ZNI
XM_I)(;?_080`!+"Z+80`"M$SM".#_P$Y=3G5.5?^<+PLF;0`((`MF!$?Z^F8OX
XM"TAZ^F)(>OIJ2&W_I4ZZ!`Y/[P`00^W_I2QX``1.KOYZ*T#_G&="0J="ITZZ)
XM^)8[?``E_^Q"K?_H0JW__"M`_]XK0/^@(&W_G$/M_]`L>``$3J[^DDAM_]!AG
XM``"L+JW_H$ZZ^-!/[P`,2JW_G%;`1`!(@$C`)E].74YU3E7_S"\+)FT`"#M\I
XM`"+_['``,"L`-"M`_^@K2__\*TO_WB!K`")#[?_0+'@`!$ZN_I)2JP`\0JL`H
XM.$AM_]`O"V$``(Y03T'K`"8L>``$3J[^_BM`_\Q*@&8.($M.KOZ,*T#_S$J`;
XM9Q8@;?_,$7P``0`?(D@L>``$3J[^AF#(+PMA``%X)FW_R$Y=3G5(YR`0)F\`,
XM#'`'L"L`"&<<(&L`#G``$"@`#W(!)`'AHB`"+'@`!$ZN_L)@W"QX``1.KO]\U
XM(DM.KO\$3J[_=DS?"`1.=4Y5__A(YP$P)FT`"'X`("L`/+"K`#AO5B!++'@`8
XM!$ZN_H`@2TZN_HPD0'`'L"H`"&8P2D=F!GX`'BH`'[7M``QG&DJJ`"1G#")JJ
XM`"@@*@`D3J[_+B)*<#!.KO\N4ZL`/&"L0>L`)B)*3J[_"F"@(`=(P$S?#(!.Q
XM74YU3E7_T$CG`#`F;0`()&T`#'!`(CP``0`!+'@`!$ZN_SH@0!%\``0`""M`Z
XM__QP_TZN_K8@;?_\$4``#Y/)3J[^VB!M__PA0``00^@`%"\)3KH'%B!M__S0?
XM_``F+HA.N@<(6$\@*P`8(&W__#%``#0G2``L(`IG)B\*2'KX)DAZ^"Y(;?_1^
XM3KH!TD_O`!!#[?_1+'@`!$ZN_GHG0``.(&W__"%K``X`(B`(3-\,`$Y=3G4OZ
XM"R9O``AP`!`K``\L>``$3J[^L")+<$!.KO\N)E].=4CG,!`F;P`00>L`&")KG
XM`!2SR&8,0>L`*B)K`":SR&<<<``0*P`/<@$D`>&B=@`6`.>A(`(L>``$3J[^U
XMSDS?"`Q.=4CG(#`F;P`0)$M*$F<D<``0$D'L``$(,``!"`!G"G(`$@!T()*"H
XM8`1R`!(`%(%2BF#8(`M,WPP$3G4``````````'!A("\`""!O``1.5?_T(D]RN
XM"DZZ`5P&00`P$L%*@&;P(`D0X;_)9OI"$)"/3EU.=0``("\`""!O``1.5?_TZ
XM(D\B``)!``<&00`P$L'FB&;P(`D0X;_)9OI"$)"/3EU.=0``,#$R,S0U-C<X@
XM.6%B8V1E9B`O``@@;P`$0^\`!#(``D$`#Q+[$-SHB&;R(`DB#UB!$.&RB6;ZR
XM0A"0@4YU(&\`!")(<@!P`"\"#!``*V<&#!``+68"4D@0&`0``#!M$@P```EN3
XM#"0!Y8'2@M*!TH!@Y@P1`"UF`D2!)!\@"%.`(&\`"""!D(E.=2\'+B\`"%*LX
XM`1`@!R!L`0P0P"E(`0PN'TYU3E4``$CG`#`F;P`0)&\`%$*L`1`I2P$,2&T`R
XM$"\*2'K_QDZZ!)`@;`$,0A`@+`$03.T,`/_X3EU.=4J`:@``'D2`2H%J```,U
XM1(%A```@1(%.=6$``!A$@$2!3G5*@6H```Q$@6$```9$@$YU+P)(030!9@``<
XM(DA`2$%(0C0`9P``!H3!,`)(0#0`A,$P`DA",@(D'TYU+P-V$`Q!`(!D```&[
XMX9E10PQ!"`!D```&Z9E90PQ!(`!D```&Y9E50TI!:P``!N.94T,T`.:H2$)"T
XM0N:J2$.`P38`,`(T`TA!Q,&0@F0```A30]"!9/YR`#(#2$/GN$A`P4$F'R0?U
XM3G5.5?_$2.<G,"9O`%PD;P!@?@!\`'H`<``;?``@__MR`"M!__9T_RM"__)!-
XM[?_0&T#_\1M`__PK0?_D*T'_Z"M(_\Q*$V<L<``0$P1``"!G%%=`9Q110&<(Q
XM54!F%GX!8`Y\`6`*>@%@!AM\``'__%*+8-`0$W(PL`%F!E*+&T'_^W`JL!-F^
XM#"!26)(K4/_V4HM@#DAM__8O"TZZ_@)03]?`$!-R+K`!9B)2BW`JL!-F#"!2?
XM6)(K4/_R4HM@#DAM__(O"TZZ_=A03]?`$!-R;+`!9@H;?``!__%2BV`(<FBP-
XM`68"4HL0&W(`$@`;0/_P!$$`6&<``7X$00`+9P`""E-!9R0$00`+9P`!$E-!"
XM9P`!4%=!9P`!NE5!9P``Y%=!9P`!4F```?A*+?_Q9P@@4EB2(!!@!B!26)(@"
XM$"M`_^QL"G(!1*W_["M!_^A*K?_H9P1P+6`*2@9G!'`K8`)P(!M`_]!P`!`&&
XM(BW_Z(*`<``0!8*`9PA2K?_,4JW_Y"\M_^PO+?_,3KK\>E!/*T#_R"`M__)*?
XM@&H&<@$K0?_R("W_R"(M__*2@$CM``+_Q&\T(&W_S")(T\$O`"\)+PA.N@)FG
XM3^\`#'``$"W_^R(M_\0@;?_,8`(0P%.!9/H@+?_R*T#_R-&M_^1![?_0*TC__
XMS$H'9P`!,!M\`"#_^V```29*+?_Q9P@@4EB2(!!@!B!26)(@$"M`_^Q@`/]D:
XM2BW_\6<((%)8DB`08`8@4EB2(!`K0/_L2BW__&<2(&W_S!#\`#!R`2M!_^0K6
XM2/_,+P`O+?_,3KK[WE!/*T#_R&``_S(;?``P__L@+?_R2H!J!G`(*T#_\DHMP
XM__%G""!26)(@$&`&(%)8DB`0*T#_[$HM__QG%B!M_\P0_``P$/P`>'("*T'_9
XMY"M(_\PO`"\M_\Q.NOO"4$\K0/_(<%BP+?_P9@#^T$AM_]!.NOKV6$]@`/["9
XM(%)8DB)0*TG_S&8(0?H`V"M(_\P@;?_,2AAF_%.(D>W_S"M(_^0@+?_R2H!K5
XM)K'`;R(K0/_D8!QP`2M`_^0@4EB2(!`;0/_00BW_T6`&<`!@``",("W_Y"(MG
XM__:R@&P(=``K0O_V8`21K?_V2@=G-E.M_^1M&'``(&W_S!`8+P`K2/_,(&T`(
XM$$Z06$]@XE.M__9M2'``$"W_^R\`(&T`$$Z06$]@Z%.M__9M$G``$"W_^R\`+
XM(&T`$$Z06$]@Z%.M_^1M&'``(&W_S!`8+P`K2/_,(&T`$$Z06$]@XB`+3-\,U
XMY$Y=3G4``$Y5__1(YP$P)F\`("1O`"0K;0`0__8>&DH'9S1P);X`9B*P$F8$\
XM4HI@&B\+2&W_]B\*80#\%D_O``PK0/_Z9P0D0&#2<``0!R\`3I-83V#&3-\,P
XM@$Y=3G4``"!O``0@B%B00J@`!"%(``A.=0``(&\`!")O``@@+P`,;Q:SR&4,K
XMT<#3P!,@4X!F^DYU$MA3@&;Z3G4``````_(```/J````10`@("`@("`@("`H<
XM*"@H*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0$!`0$!"$A(2$A(2$T
XMA(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!`0$!$!`0$!`0@H*"\
XM@H*"`@("`@("`@("`@("`@("`@("`@(0$!`0("`@("`@("`@("@H*"@H("`@6
XM("`@("`@("`@("`@("`@2!`0$!`0$!`0$!`0$!`0$(2$A(2$A(2$A(00$!`0`
XM$!`0@8&!@8&!`0$!`0$!`0$!`0$!`0$!`0$!`0$0$!`0$!""@H*"@H("`@("^
XL`@("`@("`@("`@("`@("`A`0$!`@`````````````````````````````_("W
X``
Xend
Xsize 5084
END_OF_FILE
if test 7155 -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.