]> granicus.if.org Git - python/commitdiff
Putting Python-specific GUSI modifications under CVS.
authorJack Jansen <jack.jansen@cwi.nl>
Tue, 18 Aug 1998 14:52:38 +0000 (14:52 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Tue, 18 Aug 1998 14:52:38 +0000 (14:52 +0000)
Mac/GUSI-mods/into-include/GUSI.h [new file with mode: 0644]
Mac/GUSI-mods/into-include/GUSI_P.h [new file with mode: 0644]
Mac/GUSI-mods/into-src/GUSI.r [new file with mode: 0644]
Mac/GUSI-mods/into-src/GUSIDispatch.cp [new file with mode: 0644]
Mac/GUSI-mods/into-src/GUSINetDB.cp [new file with mode: 0644]
Mac/GUSI-mods/into-src/GUSISIOUX.cp [new file with mode: 0644]

diff --git a/Mac/GUSI-mods/into-include/GUSI.h b/Mac/GUSI-mods/into-include/GUSI.h
new file mode 100644 (file)
index 0000000..07ce429
--- /dev/null
@@ -0,0 +1,366 @@
+/*********************************************************************
+Project        :       GUSI                            -       Grand Unified Socket Interface
+File           :       GUSI.h                  -       Socket calls
+Author :       Matthias Neeracher
+Language       :       MPW C/C++
+
+$Log$
+Revision 1.1  1998/08/18 14:52:33  jack
+Putting Python-specific GUSI modifications under CVS.
+
+Revision 1.2  1994/12/31  01:45:54  neeri
+Fix alignment.
+
+Revision 1.1  1994/02/25  02:56:49  neeri
+Initial revision
+
+Revision 0.15  1993/06/27  00:00:00  neeri
+f?truncate
+
+Revision 0.14  1993/06/20  00:00:00  neeri
+Changed sa_constr_ppc
+
+Revision 0.13  1993/02/14  00:00:00  neeri
+AF_PAP
+
+Revision 0.12  1992/12/08  00:00:00  neeri
+getcwd()
+
+Revision 0.11  1992/11/15  00:00:00  neeri
+remove netdb.h definitions
+
+Revision 0.10  1992/09/26  00:00:00  neeri
+Separate dirent and stat
+
+Revision 0.9  1992/09/12  00:00:00  neeri
+Hostname stuff
+
+Revision 0.8  1992/09/07  00:00:00  neeri
+readlink()
+
+Revision 0.7  1992/08/03  00:00:00  neeri
+sa_constr_ppc
+
+Revision 0.6  1992/07/21  00:00:00  neeri
+sockaddr_atlk_sym
+
+Revision 0.5  1992/06/26  00:00:00  neeri
+choose()
+
+Revision 0.4  1992/05/18  00:00:00  neeri
+PPC stuff
+
+Revision 0.3  1992/04/27  00:00:00  neeri
+getsockopt()
+
+Revision 0.2  1992/04/19  00:00:00  neeri
+C++ compatibility
+
+Revision 0.1  1992/04/17  00:00:00  neeri
+bzero()
+
+*********************************************************************/
+
+#ifndef _GUSI_
+#define _GUSI_
+
+#include <sys/types.h>
+
+/* Feel free to increase FD_SETSIZE as needed */
+#define GUSI_MAX_FD    FD_SETSIZE
+
+#include <sys/cdefs.h>
+#include <compat.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <Types.h>
+#include <Events.h>
+#include <Files.h>
+#include <AppleTalk.h>
+#include <CTBUtilities.h>
+#include <Packages.h>
+#include <PPCToolBox.h>
+#include <StandardFile.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <machine/endian.h>
+
+typedef enum spin_msg {
+       SP_MISC,                                /* some weird thing, usually just return immediately if you get this */
+       SP_SELECT,                      /* in a select call */
+       SP_NAME,                                /* getting a host by name */
+       SP_ADDR,                                /* getting a host by address */
+       SP_STREAM_READ, /* Stream read call */
+       SP_STREAM_WRITE,        /* Stream write call */
+       SP_DGRAM_READ,          /* Datagram read call */
+       SP_DGRAM_WRITE, /* Datagram write call */
+       SP_SLEEP,                       /* sleeping, passes ticks left to sleep */
+       SP_AUTO_SPIN            /* Autospin, passes argument to SpinCursor */
+} spin_msg;
+
+typedef int (*GUSISpinFn)(spin_msg msg, long param);
+typedef void (*GUSIEvtHandler)(EventRecord * ev);
+typedef GUSIEvtHandler GUSIEvtTable[24];
+
+/*
+ * Address families, defined in sys/socket.h
+ *
+#define        AF_UNSPEC                0              // unspecified
+#define        AF_UNIX                  1              // local to host (pipes, portals)
+#define        AF_INET                  2              // internetwork: UDP, TCP, etc.
+#define        AF_CTB                   3              // Apple Comm Toolbox (not yet supported)
+#define        AF_FILE                  4              // Normal File I/O (used internally)
+#define        AF_PPC                   5              // PPC Toolbox
+#define        AF_PAP                   6              // Printer Access Protocol (client only)
+#define        AF_APPLETALK    16              // Apple Talk
+
+*/
+
+#define        ATALK_SYMADDR 272               /* Symbolic Address for AppleTalk                       */
+
+/*
+ * Some Implementations of GUSI require you to call GUSISetup for the
+ * socket families you'd like to have defined. It's a good idea to call
+ * this for *all* implementations.
+ *
+ * GUSIDefaultSetup() will include all socket families.
+ *
+ * Never call any of the GUSIwithXXX routines directly.
+ */
+
+__BEGIN_DECLS
+void GUSIwithAppleTalkSockets();
+void GUSIwithInternetSockets();
+void GUSIwithPAPSockets();
+void GUSIwithPPCSockets();
+void GUSIwithUnixSockets();
+void GUSIwithSIOUXSockets();
+void GUSIwithMPWSockets();
+
+void GUSISetup(void (*socketfamily)());
+void GUSIDefaultSetup();
+void GUSILoadConfiguration(Handle);
+__END_DECLS
+/*
+ * Types,  defined in sys/socket.h
+ *
+
+#define        SOCK_STREAM              1              // stream socket 
+#define        SOCK_DGRAM               2              // datagram socket
+
+*/
+
+/*
+ * Defined in sys/un.h
+ *
+struct sockaddr_un {
+       short           sun_family;
+       char            sun_path[108];
+};
+
+*/
+
+#ifndef PRAGMA_ALIGN_SUPPORTED
+#error Apple had some fun with the conditional macros again
+#endif
+
+#if PRAGMA_ALIGN_SUPPORTED
+#pragma options align=mac68k
+#endif
+
+struct sockaddr_atlk {
+       short                   family;
+       AddrBlock       addr;
+};
+
+struct sockaddr_atlk_sym {
+       short                   family;
+       EntityName      name;
+};
+
+struct sockaddr_ppc {
+       short                                   family;
+       LocationNameRec location;
+       PPCPortRec                      port;
+};
+
+/* Definitions for choose() */
+
+#define        CHOOSE_DEFAULT  1               /*      Use *name as default name                                               */
+#define        CHOOSE_NEW              2               /* Choose new entity name, not existing one     */
+#define        CHOOSE_DIR              4               /* Choose a directory name, not a file          */
+
+typedef struct {
+       short                   numTypes;
+       SFTypeList      types;
+} sa_constr_file;
+
+typedef struct {
+       short                   numTypes;
+       NLType          types;
+} sa_constr_atlk;
+
+/* Definitions for sa_constr_ppc */
+
+#define PPC_CON_NEWSTYLE               0x8000  /* Required */
+#define PPC_CON_MATCH_NAME             0x0001  /* Match name */
+#define PPC_CON_MATCH_TYPE     0x0002  /* Match port type */
+#define PPC_CON_MATCH_NBP              0x0004  /* Match NBP type */
+
+typedef struct {
+       short                   flags;
+       Str32                   nbpType;
+       PPCPortRec      match;
+} sa_constr_ppc;
+
+#if PRAGMA_ALIGN_SUPPORTED
+#pragma options align=reset
+#endif
+
+__BEGIN_DECLS
+/* 
+ * IO/Socket stuff, defined elsewhere (unistd.h, sys/socket.h
+ *
+
+int socket(int domain, int type, short protocol);
+int bind(int s, void *name, int namelen);
+int connect(int s, void *addr, int addrlen);
+int listen(int s, int qlen);
+int accept(int s, void *addr, int *addrlen);
+int close(int s);
+int read(int s, char *buffer, unsigned buflen);
+int readv(int s, struct iovec *iov, int count);
+int recv(int s, void *buffer, int buflen, int flags);
+int recvfrom(int s, void *buffer, int buflen, int flags, void *from, int *fromlen);
+int recvmsg(int s,struct msghdr *msg,int flags);
+int write(int s, const char *buffer, unsigned buflen);
+int writev(int s, struct iovec *iov, int count);
+int send(int s, void *buffer, int buflen, int flags);
+int sendto (int s, void *buffer, int buflen, int flags, void *to, int tolen);
+int sendmsg(int s,struct msghdr *msg,int flags);
+int select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+int getdtablesize(void);
+int getsockname(int s, void *name, int *namelen);
+int getpeername(int s, struct sockaddr *name, int *namelen);
+int shutdown(int s, int how);
+int fcntl(int s, unsigned int cmd, int arg);
+int dup(int s);
+int dup2(int s, int s1);
+int ioctl(int d, unsigned int request, long *argp);
+int getsockopt(int s, int level, int optname, char *optval, int * optlen);
+int setsockopt(int s, int level, int optname, char *optval, int optlen);
+int isatty(int);
+int remove(const char *filename);
+int rename(const char *oldname, const char *newname);
+int creat(const char*);
+int faccess(char*, unsigned int, long*);
+long lseek(int, long, int);
+int open(const char*, int);
+int unlink(char*);
+int symlink(char* linkto, char* linkname);
+int readlink(char* path, char* buf, int bufsiz);
+int truncate(char *path, long length);
+int ftruncate(int fd, long length);
+int chdir(char * path);
+int mkdir(char * path);
+int rmdir(char * path);
+char * getcwd(char * buf, int size);
+*/
+
+/* 
+ * Defined in stdio.h
+ */
+#ifdef __MWERKS__
+void fsetfileinfo (char *filename, unsigned long newcreator, unsigned long newtype);
+#endif
+
+void fgetfileinfo (char *filename, unsigned long * creator, unsigned long * type);
+
+#ifdef __MWERKS__
+FILE *fdopen(int fd, const char *mode);
+int fwalk(int (*func)(FILE * stream));
+#endif
+
+int choose(
+               int             domain,
+               int             type,
+               char *  prompt,
+               void *  constraint,
+               int             flags,
+               void *  name,
+               int *   namelen);
+
+/* 
+ * Hostname routines, defined in netdb.h
+ *
+struct hostent * gethostbyname(char *name);
+struct hostent * gethostbyaddr(struct in_addr *addrP, int, int);
+int gethostname(char *machname, long buflen);
+struct servent * getservbyname (char * name, char * proto);
+struct protoent * getprotobyname(char * name);
+
+*/
+
+char * inet_ntoa(struct in_addr inaddr);
+struct in_addr inet_addr(char *address);
+
+/* 
+ * GUSI supports a number of hooks. Every one of them has a different prototype, but needs
+ * to be passed as a GUSIHook
+ */
+
+typedef enum {
+       GUSI_SpinHook,  /* A GUSISpinFn, to be called when a call blocks */
+       GUSI_ExecHook, /* Boolean (*hook)(const GUSIFileRef & ref), decides if file is executable */
+       GUSI_FTypeHook,/* Boolean (*hook)(const FSSpec & spec) sets a default file type */
+       GUSI_SpeedHook /* A long integer, to be added to the cursor spin variable */
+} GUSIHookCode;
+
+typedef void (*GUSIHook)(void);
+void GUSISetHook(GUSIHookCode code, GUSIHook hook);
+GUSIHook GUSIGetHook(GUSIHookCode code);
+
+/* 
+ * What to do when a routine blocks
+ */
+
+/* Defined for compatibility */
+#define GUSISetSpin(routine)   GUSISetHook(GUSI_SpinHook, (GUSIHook)routine)
+#define GUSIGetSpin()                  (GUSISpinFn) GUSIGetHook(GUSI_SpinHook)
+
+int GUSISetEvents(GUSIEvtTable table);
+GUSIEvtHandler * GUSIGetEvents(void);
+
+extern GUSIEvtHandler  GUSISIOWEvents[];
+
+#define SIGPIPE        13
+#define SIGALRM        14
+
+/* 
+ * BSD memory routines, defined in compat.h
+ *
+
+#define index(a, b)                                            strchr(a, b)
+#define rindex(a, b)                                           strrchr(a, b)
+#define bzero(from, len)                               memset(from, 0, len)
+#define bcopy(from, to, len)                   memcpy(to, from, len)
+#define bcmp(s1, s2, len)                              memcmp(s1, s2, len)
+#define bfill(from, len, x)                    memset(from, x, len)
+
+ */
+
+__END_DECLS
+
+#endif /* !_GUSI_ */
diff --git a/Mac/GUSI-mods/into-include/GUSI_P.h b/Mac/GUSI-mods/into-include/GUSI_P.h
new file mode 100644 (file)
index 0000000..1bc5523
--- /dev/null
@@ -0,0 +1,471 @@
+/*********************************************************************
+Project        :       GUSI                            -       Grand Unified Socket Interface
+File           :       GUSI_P.h                        -       Private stuff
+Author :       Matthias Neeracher
+Language       :       MPW C/C++
+
+$Log$
+Revision 1.1  1998/08/18 14:52:33  jack
+Putting Python-specific GUSI modifications under CVS.
+
+Revision 1.3  1994/12/31  01:30:26  neeri
+Reorganize filename dispatching.
+
+Revision 1.2  1994/08/10  00:41:05  neeri
+Sanitized for universal headers.
+
+Revision 1.1  1994/02/25  02:57:01  neeri
+Initial revision
+
+Revision 0.22  1993/07/17  00:00:00  neeri
+GUSIRingBuffer::proc -> defproc
+
+Revision 0.21  1993/07/17  00:00:00  neeri
+GUSIO_MAX_DOMAIN -> AF_MAX
+
+Revision 0.20  1993/06/27  00:00:00  neeri
+Socket::{pre,post}_select
+
+Revision 0.19  1993/06/27  00:00:00  neeri
+Socket::ftruncate
+
+Revision 0.18  1993/02/09  00:00:00  neeri
+Socket::lurking, Socket::lurkdescr
+
+Revision 0.17  1993/01/31  00:00:00  neeri
+GUSIConfiguration::daemon
+
+Revision 0.16  1993/01/17  00:00:00  neeri
+Destructors for Socketdomain
+
+Revision 0.15  1993/01/17  00:00:00  neeri
+SAFESPIN
+
+Revision 0.14  1993/01/03  00:00:00  neeri
+GUSIConfig
+
+Revision 0.13  1992/09/24  00:00:00  neeri
+Include GUSIRsrc_P.h
+
+Revision 0.12  1992/09/13  00:00:00  neeri
+SPINVOID didn't return
+
+Revision 0.11  1992/08/30  00:00:00  neeri
+AppleTalkIdentity()
+
+Revision 0.10  1992/08/03  00:00:00  neeri
+RingBuffer
+
+Revision 0.9  1992/07/30  00:00:00  neeri
+Initializer Features
+
+Revision 0.8  1992/07/26  00:00:00  neeri
+UnixSockets.choose()
+
+Revision 0.7  1992/07/13  00:00:00  neeri
+Make AppleTalkSockets global
+
+Revision 0.6  1992/06/27  00:00:00  neeri
+choose(), hasNewSF
+
+Revision 0.5  1992/06/07  00:00:00  neeri
+Feature
+
+Revision 0.4  1992/05/21  00:00:00  neeri
+Implemented select()
+
+Revision 0.3  1992/04/19  00:00:00  neeri
+C++ rewrite
+
+Revision 0.2  1992/04/18  00:00:00  neeri
+changed read/write/send/recv dispatchers
+
+Revision 0.1  1992/04/18  00:00:00  neeri
+ppc Domain
+
+*********************************************************************/
+
+#ifndef __GUSI_P__
+#define __GUSI_P__
+
+#define __useAppleExts__
+
+#include <GUSI.h>
+#include <GUSIRsrc_P.h>
+#include <TFileSpec.h>
+
+
+#include <sys/errno.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+extern "C" {
+
+#include <stdio.h>
+#include <string.h>
+
+int            GUSI_error(int err);
+void * GUSI_error_nil(int err);
+}
+
+#include <Memory.h>
+#include <Gestalt.h>
+#include <Traps.h>
+#include <AppleEvents.h>
+#include <Processes.h>
+#include <MixedMode.h>
+
+#if MSLGUSI
+using namespace std;
+#endif
+
+#if GENERATING68K
+#pragma segment GUSI
+#endif
+
+#define GUSI_MAX_DOMAIN                        AF_MAX
+#define DEFAULT_BUFFER_SIZE    4096
+
+/*
+ *     In use and shutdown status.
+ */
+#define        SOCK_STATUS_USED                0x1             /* Used socket table entry */
+#define        SOCK_STATUS_NOREAD      0x2             /* No more reading allowed from socket */
+#define        SOCK_STATUS_NOWRITE     0x4             /* No more writing allowed to socket */
+
+/*
+ *     Socket connection states.
+ */
+#define        SOCK_STATE_NO_STREAM            0       /* Socket doesn't have a MacTCP stream yet */
+#define        SOCK_STATE_UNCONNECTED  1       /* Socket is unconnected. */
+#define        SOCK_STATE_LISTENING            2       /* Socket is listening for connection. */
+#define        SOCK_STATE_LIS_CON              3       /* Socket is in transition from listen to connected. */
+#define        SOCK_STATE_CONNECTING   4       /* Socket is initiating a connection. */
+#define        SOCK_STATE_CONNECTED            5       /* Socket is connected. */
+#define        SOCK_STATE_CLOSING      6       /* Socket is closing */
+#define        SOCK_STATE_LIS_CLOSE    7       /* Socket closed while listening */
+
+#define                min(a,b)                                ( (a) < (b) ? (a) : (b))
+#define                max(a,b)                                ( (a) > (b) ? (a) : (b))
+
+extern GUSISpinFn GUSISpin;
+extern "C" int GUSIDefaultSpin(spin_msg, long);
+extern int GUSICheckAlarm();
+
+#define GUSI_INTERRUPT(mesg,param)     (GUSICheckAlarm() || (GUSISpin && (*GUSISpin)(mesg,param)))
+
+/* SPIN returns a -1 on user cancel for fn returning integers */
+#define                SPIN(cond,mesg,param)                                                   \
+                                       do {                                                                                            \
+                                               if (GUSI_INTERRUPT(mesg,param))         \
+                                                       return GUSI_error(EINTR);                       \
+                                       } while(cond)
+
+/* SPINP returns a NULL on user cancel, for fn returning pointers */                           
+#define                SPINP(cond,mesg,param)                                                  \
+                                       do {                                                                                            \
+                                               if (GUSI_INTERRUPT(mesg,param)) {       \
+                                                       GUSI_error(EINTR);                                      \
+                                                       return NULL;                                                    \
+                                               }                                                                                               \
+                                       } while(cond)
+
+/* SPINVOID just returns on user cancel, for fn returning void */                              
+#define                SPINVOID(cond,mesg,param)                                               \
+                                       do {                                                                                            \
+                                               if (GUSI_INTERRUPT(mesg,param)) {       \
+                                                               GUSI_error(EINTR);                              \
+                                                               return;                                                         \
+                                                       }                                                                                       \
+                                       } while(cond)
+                                       
+/* SAFESPIN doesn't return, you have to check errno */                         
+#define                SAFESPIN(cond,mesg,param)                                               \
+                                       do {                                                                                            \
+                                               if (GUSI_INTERRUPT(mesg,param)) {       \
+                                                       GUSI_error(EINTR);                                      \
+                                                       break;                                                                  \
+                                               } else                                                                          \
+                                                       errno = 0;                                                              \
+                                       } while(cond)
+
+//
+// Library functions are never allowed to clear errno, so we have to save
+//
+class ErrnoSaver {
+public:
+       ErrnoSaver()  { fSavedErrno = ::errno; ::errno = 0;     }
+       ~ErrnoSaver() { if (!::errno) ::errno = fSavedErrno;  }
+private:
+       int fSavedErrno;
+};
+
+#define SAVE_AND_CLEAR_ERRNO   ErrnoSaver saveErrno
+                       
+class SocketTable;
+
+#if PRAGMA_ALIGN_SUPPORTED
+#pragma options align=mac68k
+#endif
+
+class Socket {
+       friend class SocketTable;
+       
+       short                   refCount;
+protected:
+                                       Socket();
+public:
+       virtual int     bind(void * name, int namelen);
+       virtual int connect(void * address, int addrlen);
+       virtual int listen(int qlen);
+       virtual Socket * accept(void * address, int * addrlen);
+       virtual int     read(void * buffer, int buflen);
+       virtual int write(void * buffer, int buflen);
+       virtual int recvfrom(void * buffer, int buflen, int flags, void * from, int * fromlen);
+       virtual int sendto(void * buffer, int buflen, int flags, void * to, int tolen);
+       virtual int getsockname(void * name, int * namelen);
+       virtual int getpeername(void * name, int * namelen);
+       virtual int getsockopt(int level, int optname, void *optval, int * optlen);
+       virtual int setsockopt(int level, int optname, void *optval, int optlen);
+       virtual int     fcntl(unsigned int cmd, int arg);
+       virtual int     ioctl(unsigned int request, void *argp);
+       virtual int     fstat(struct stat * buf);
+       virtual long lseek(long offset, int whence);
+       virtual int ftruncate(long offset);
+       virtual int     isatty();
+       virtual int shutdown(int how);
+       virtual void pre_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
+       virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception);
+       virtual void post_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
+       virtual                 ~Socket();
+       
+       void operator++()       {       ++refCount;                                                     }
+       void operator--()       {       if (!--refCount) delete this;   }
+};
+
+
+#if PRAGMA_ALIGN_SUPPORTED
+#pragma options align=reset
+#endif
+
+class SocketDomain {
+       static SocketDomain *           domains[GUSI_MAX_DOMAIN];
+       static ProcessSerialNumber      process;
+protected:
+       SocketDomain(int domain);
+       virtual ~SocketDomain();
+public:
+       inline static SocketDomain *    Domain(int domain);
+       static void Ready();
+       
+       // Optionally override the following
+       
+       virtual Socket * socket(int type, short protocol);
+       
+       // Optionally override the following
+       
+       virtual int socketpair(int type, short protocol, Socket * sockets[]);
+       
+       // Optionally define the following
+       
+       virtual int choose(
+                                               int             type, 
+                                               char *  prompt, 
+                                               void *  constraint,             
+                                               int             flags,
+                                               void *  name, 
+                                               int *   namelen);
+       
+       // Never override the following
+       
+       void DontStrip();
+};
+
+class SocketTable {
+       Socket *        sockets[GUSI_MAX_FD];
+       Boolean needsConsole;
+public:
+       SocketTable();
+       ~SocketTable();
+       
+       void            InitConsole();
+       int             Install(Socket * sock, int start = 0);
+       int             Remove(int fd);
+       Socket * operator[](int fd);
+};
+
+struct GUSISuffix {
+       char            suffix[4];
+       OSType  suffType;
+       OSType  suffCreator;
+};
+
+#if PRAGMA_ALIGN_SUPPORTED
+#pragma options align=mac68k
+#endif
+
+//
+// I learned the hard way not to rely on bit field alignments
+//
+
+struct GUSIConfigRsrc {
+       OSType                  defaultType;
+       OSType                  defaultCreator;
+       
+       char                            autoSpin;
+       unsigned char   flags;
+       
+       OSType                  version;
+       short                           numSuffices;
+       GUSISuffix              suffices[1];
+};
+
+#if PRAGMA_ALIGN_SUPPORTED
+#pragma options align=reset
+#endif
+
+struct GUSIConfiguration {
+       OSType                  defaultType;
+       OSType                  defaultCreator;
+       
+       char                            autoSpin;
+       
+       Boolean                 noChdir;                // Set current directory without chdir()
+       Boolean                         accurStat;      // Return # of subdirectories + 2 in st_nlink
+       Boolean                 hasConsole;     // Do we have our own console ?
+       Boolean                 noAutoInitGraf; // Never automatically do InitGraf
+       Boolean                 sharedOpen;     // Open files with shared permissions
+       Boolean                 sigPipe;                // raise SIGPIPE on write to closed socket
+       Boolean                 noAppleEvents; // Don't solicit AppleEvents for MPW tools
+       Boolean                 delayConsole;   // Do not open console until needed
+       
+       OSType                  version;
+       short                           numSuffices;
+       GUSISuffix *    suffices;
+       
+       GUSIConfiguration();
+       void GUSILoadConfiguration(Handle config);
+       
+       void SetDefaultFType(const TFileSpec & name) const;
+       void DoAutoSpin() const;
+       void AutoInitGraf()     const { if (!noAutoInitGraf) DoAutoInitGraf();  }
+       void DoAutoInitGraf() const;
+       Boolean DelayConsole() const;
+private:
+       static Boolean firstTime;
+       static short    we;
+};
+
+extern GUSIConfiguration       GUSIConfig;
+extern SocketTable                                     Sockets;
+
+typedef pascal OSErr (*OSErrInitializer)();
+typedef pascal void  (*voidInitializer)();
+
+class Feature {
+       Boolean good;
+public:
+       Feature(unsigned short trapNum, TrapType tTyp);
+       Feature(OSType type, long value);
+       Feature(OSType type, long mask, long value);
+       Feature(const Feature & precondition, OSErrInitializer init);
+       Feature(OSErrInitializer init);
+       Feature(const Feature & precondition, voidInitializer init);
+       Feature(voidInitializer init);
+       Feature(const Feature & cond1, const Feature & cond2);
+
+       operator void*() const {        return (void *) good;   }
+};
+
+extern Feature hasMakeFSSpec;
+extern Feature hasAlias;
+extern Feature hasNewSF;
+extern Feature hasProcessMgr;
+extern Feature hasCRM;
+extern Feature hasCTB;
+extern Feature hasStdNBP;
+extern Feature hasCM;
+extern Feature hasFT;
+extern Feature hasTM;
+extern Feature hasPPC;
+extern Feature hasRevisedTimeMgr;
+
+class ScattGath        {
+       Handle                  scratch;
+protected:
+       void *                  buf;
+       int                                             len;
+       int                                             count;
+       const struct iovec *    io;
+
+       ScattGath(const struct iovec *iov, int cnt);
+       virtual ~ScattGath();
+public:
+       void *                  buffer()                        {       return buf;                     }
+       int                             buflen()                        {       return len;                     }
+       int                             length(int l)   {       return len = l; }
+       operator void *()                                       {       return buf;                     }
+};
+
+class Scatterer : public ScattGath {
+public:
+       Scatterer(const struct iovec *iov, int count);
+       virtual ~Scatterer();
+};
+
+class Gatherer : public ScattGath {
+public:
+       Gatherer(const struct iovec *iov, int count);
+       virtual ~Gatherer();
+};
+
+typedef pascal void (*Deferred)(void *);
+
+class RingBuffer {
+       // Valid bytes are between consume and produce
+       // Free bytes are between produce and consume
+       // bytes between endbuf-spare and endbuf are neither
+       Ptr             buffer;
+       Ptr             endbuf;
+       Ptr             consume;
+       Ptr             produce;
+       u_short free;
+       u_short valid;
+       u_short spare;
+       Boolean lock;
+       Deferred        defproc;
+       void *  arg;
+       
+public:
+                               RingBuffer(u_short bufsiz);
+                               ~RingBuffer();
+       
+       Ptr             Producer(long & len);                   //      Find continuous memory for producer
+       Ptr             Consumer(long & len);                   //      Find continuous memory for consumer
+       void            Validate(long len);                             // Validate this, unallocate rest
+       void            Invalidate(long len);
+       void            Produce(Ptr from, long & len);//        Allocate, copy & validate
+       void            Consume(Ptr to, long & len);    // Copy & invalidate
+       
+       long            Free()                                                          { return free;                                                                  }               
+       long            Valid()                                                         { return valid;                                                         }
+       
+       void            Defer()                                                         { lock = true;                                                                  }
+       void            Undefer()                                                       { lock = false; if (defproc) defproc(arg);}
+       Boolean Locked()                                                                { return lock;                                                                  }
+       void            Later(Deferred def, void * ar){ defproc = def; arg = ar;                                        }
+       
+       operator void *()                                                               { return buffer;                                                                }
+};
+
+Boolean GUSIInterrupt();
+
+Boolean CopyIconFamily(short srcResFile, short srcID, short dstResFile, short dstID);
+
+pascal OSErr PPCInit_P();
+
+OSErr AppleTalkIdentity(short & net, short & node);
+
+void CopyC2PStr(const char * cstr, StringPtr pstr);
+
+#endif
diff --git a/Mac/GUSI-mods/into-src/GUSI.r b/Mac/GUSI-mods/into-src/GUSI.r
new file mode 100644 (file)
index 0000000..6da7fd6
--- /dev/null
@@ -0,0 +1,168 @@
+/*********************************************************************
+Project        :       GUSI                            -       Grand Unified Socket Interface
+File           :       GUSI.r                  -       Include this
+Author :       Matthias Neeracher
+Language       :       MPW Rez 3.0
+
+$Log$
+Revision 1.1  1998/08/18 14:52:37  jack
+Putting Python-specific GUSI modifications under CVS.
+
+Revision 1.3  1994/12/30  19:33:34  neeri
+Enlargened message box for select folder dialog.
+
+Revision 1.2  1994/08/10  00:34:18  neeri
+Sanitized for universal headers.
+
+Revision 1.1  1994/02/25  02:12:04  neeri
+Initial revision
+
+Revision 0.5  1993/05/21  00:00:00  neeri
+suffixes
+
+Revision 0.4  1993/01/31  00:00:00  neeri
+Daemon
+
+Revision 0.3  1993/01/03  00:00:00  neeri
+autoSpin
+
+Revision 0.2  1992/09/24  00:00:00  neeri
+Don't include CKID, create GUSIRsrc_P.h
+
+Revision 0.1  1992/07/13  00:00:00  neeri
+.rsrc
+
+*********************************************************************/
+
+#include "Types.r"
+#include "GUSIRsrc_P.h"
+
+include "GUSI.rsrc" not 'ckid';
+
+/* Define a resource ('GU\85I', GUSIRsrcID) to override GUSI defaults            
+       To avoid having to change the Rez file every time I introduce another
+       feature, the preprocessor variable GUSI_PREF_VERSION by default keeps
+       everything compatible with version 1.0.2. Just define GUSI_PREF_VERSION
+       to be the version you want to use.
+*/
+
+#ifndef GUSI_PREF_VERSION
+#define GUSI_PREF_VERSION '0102'
+#endif
+
+type 'GU\85I' {
+       literal longint text    =       'TEXT'; /* Type for creat'ed files                              */
+       literal longint mpw     =       'MPS '; /* Creator for creat'ed files                   */
+       byte            noAutoSpin, autoSpin;           /* Automatically spin cursor ?                  */
+#if GUSI_PREF_VERSION > '0102'
+       boolean         useChdir, dontUseChdir;         /* Use chdir() ?                                                        */
+       boolean approxStat, accurateStat;       /* statbuf.st_nlink = # of subdirectories ? */
+#if GUSI_PREF_VERSION >= '0181'
+       boolean noDelayConsole, DelayConsole;   /* Delay opening console window until needed? */
+       fill            bit[1];
+#else
+       boolean noTCPDaemon, isTCPDaemon;       /* Inetd client ?                                                       */
+       boolean noUDPDaemon, isUDPDaemon;
+#endif
+#if GUSI_PREF_VERSION >= '0150'
+#if GUSI_PREF_VERSION >= '0181'
+       boolean wantAppleEvents, noAppleEvents; /* Always solicit AppleEvents */
+#else
+       boolean noConsole, hasConsole;          /* Are we providing our own dev:console ? (Obsolete) */
+#endif
+#if GUSI_PREF_VERSION >= '0180'
+       boolean autoInitGraf, noAutoInitGraf;   /* Automatically do InitGraf ? */
+       boolean exclusiveOpen, sharedOpen;      /* Shared open() ?                                                      */
+       boolean noSigPipe, sigPipe;                     /* raise SIGPIPE on write to closed PIPE */
+#else
+       fill            bit[3];
+#endif
+#else
+       fill            bit[4];
+#endif
+       literal longint = GUSI_PREF_VERSION;
+#if GUSI_PREF_VERSION >= '0120'
+       integer = $$Countof(SuffixArray);
+       wide array SuffixArray {
+                       literal longint;                                        /* Suffix of file */
+                       literal longint;                                        /* Type for file */
+                       literal longint;                                        /* Creator for file */
+       };
+#endif
+#endif
+};
+
+type 'TMPL' {
+       wide array {
+               pstring;
+               literal longint;
+       };
+};
+
+resource 'TMPL' (GUSIRsrcID, "GU\85I") {
+       {
+               "Type of created files",                'TNAM',
+               "Creator of created files",     'TNAM',
+               "Automatically spin cursor",    'DBYT',
+#if GUSI_PREF_VERSION > '0102'
+               "Not using chdir()",                            'BBIT',
+               "Accurate stat()",                              'BBIT',
+               "TCP daemon",                                           'BBIT',
+               "UDP daemon",                                           'BBIT',
+#if GUSI_PREF_VERSION >= '0150'
+               "Own Console",                                          'BBIT',
+#else
+               "Reserved",                                                     'BBIT',
+#endif
+#if GUSI_PREF_VERSION >= '0180'
+               "Don't initialize QuickDraw",   'BBIT',
+               "Open files shared",                            'BBIT',
+               "Raise SIGPIPE",                                        'BBIT',
+#else
+               "Reserved",                                                     'BBIT',
+               "Reserved",                                                     'BBIT',
+               "Reserved",                                                     'BBIT',
+#endif
+               "Version (don't change)",               'TNAM',         
+#if GUSI_PREF_VERSION >= '0120'
+               "NumSuffices",                                          'OCNT',
+               "*****",                                                                'LSTC',
+               "Suffix",                                                       'TNAM',
+               "Type for suffix",                              'TNAM',
+               "Creator for suffix",                   'TNAM',
+               "*****",                                                                'LSTE',
+#endif
+#endif         
+       }
+};
+
+resource 'DLOG' (GUSIRsrcID, "Get Directory") {
+       {0, 0, 217, 348}, 
+       dBoxProc, 
+       invisible, 
+       noGoAway, 
+       0x0, 
+       10240, 
+       "",
+       alertPositionMainScreen
+};
+
+resource 'DITL' (GUSIRsrcID, "Get Directory") {
+       {
+               { 142, 256,  160, 336}, Button          {enabled,"Open"},
+               {1152,  59, 1232,  77}, Button          {enabled,"Hidden"},
+               { 193, 256,  211, 336}, Button          {enabled,"Cancel"},
+               {  43, 232,   63, 347}, UserItem                {disabled},
+               {  72, 256,   90, 336}, Button          {enabled,"Eject"},
+               {  97, 256,  115, 336}, Button          {enabled,"Drive"},
+               {  43,  12,  189, 230}, UserItem                {enabled},
+               {  43, 229,  189, 246}, UserItem                {enabled},
+               { 128, 252,  129, 340}, UserItem                {disabled},
+               {1044,  20, 1145, 116}, StaticText      {disabled,""},
+               { 167, 256,  185, 336}, Button          {enabled,"Directory"},
+               {   0,  30,   18, 215}, Button          {enabled,"Select Current Directory:"},
+               { 200,  20, 1145, 222}, StaticText      {disabled,"Select a Folder"}
+       }
+};
+
+
diff --git a/Mac/GUSI-mods/into-src/GUSIDispatch.cp b/Mac/GUSI-mods/into-src/GUSIDispatch.cp
new file mode 100644 (file)
index 0000000..86941cb
--- /dev/null
@@ -0,0 +1,1434 @@
+/*********************************************************************
+Project        :       GUSI                            -       Grand Unified Socket Interface
+File   :       GUSIDispatch.cp-        Dispatch calls to their correct recipient
+Author :       Matthias Neeracher
+Language:      MPW C/C++
+
+$Log$
+Revision 1.1  1998/08/18 14:52:37  jack
+Putting Python-specific GUSI modifications under CVS.
+
+Revision 1.4  1994/12/30  19:48:09  neeri
+Remove (theoretical) support for pre-System 6 systems.
+Remove built-in support for INETd.
+Fix problems in connection with ROM PowerPC library.
+Move open() to GUSIFileDispatch.cp.
+Support AF_UNSPEC domains.
+More work on spinning performance.
+
+Revision 1.3  1994/08/10  00:30:30  neeri
+Sanitized for universal headers.
+Prevent overly fast spinning.
+
+Revision 1.2  1994/05/01  23:47:34  neeri
+Extend fflush() kludge.
+Define _lastbuf for MPW 3.2 compatibility.
+
+Revision 1.1  1994/02/25  02:28:36  neeri
+Initial revision
+
+Revision 0.27  1993/11/24  00:00:00  neeri
+Flush stdio before closing
+
+Revision 0.26  1993/11/22  00:00:00  neeri
+Extend two time loser for EBADF
+
+Revision 0.25  1993/11/12  00:00:00  neeri
+Two time loser workaround for flush bug
+
+Revision 0.24  1993/06/27  00:00:00  neeri
+{pre,post}_select
+
+Revision 0.23  1993/06/27  00:00:00  neeri
+ftruncate
+
+Revision 0.22  1993/06/20  00:00:00  neeri
+Further subtleties in console handling 
+
+Revision 0.21  1993/05/21  00:00:00  neeri
+Suffixes
+
+Revision 0.20  1993/05/15  00:00:00  neeri
+Try to keep errno always set on error returns
+
+Revision 0.19  1993/05/13  00:00:00  neeri
+Limit Search for configuration resource to application
+
+Revision 0.18  1993/01/31  00:00:00  neeri
+Introducing daemons (pleased to meet you, hope you guess my name)
+
+Revision 0.17  1993/01/17  00:00:00  neeri
+Be more careful about user aborts.
+
+Revision 0.16  1993/01/03  00:00:00  neeri
+GUSIConfiguration
+
+Revision 0.15  1992/11/25  00:00:00  neeri
+Still trying to get standard descriptors for standalone programs right. sigh.
+
+Revision 0.14  1992/10/05  00:00:00  neeri
+Small fix in event dispatching
+
+Revision 0.13  1992/09/12  00:00:00  neeri
+getdtablesize()
+
+Revision 0.12  1992/08/30  00:00:00  neeri
+Move hasPPC to GUSIPPC.cp, AppleTalkIdentity
+
+Revision 0.11  1992/08/05  00:00:00  neeri
+Change the way standard I/O channels are opened
+
+Revision 0.10  1992/08/03  00:00:00  neeri
+Move Scatter/Gather to GUSIBuffer.cp
+
+Revision 0.9  1992/07/30  00:00:00  neeri
+Features with initializers
+
+Revision 0.8  1992/07/13  00:00:00  neeri
+hasProcessMgr
+
+Revision 0.7  1992/06/27  00:00:00  neeri
+choose(), hasNewSF
+
+Revision 0.6  1992/06/06  00:00:00  neeri
+Feature
+
+Revision 0.5  1992/04/19  00:00:00  neeri
+C++ Rewrite
+
+Revision 0.4  1992/04/18  00:00:00  neeri
+Changed read/write/send/recv dispatchers
+
+Revision 0.3  1992/04/17  00:00:00  neeri
+Spin routines
+
+Revision 0.2  1992/04/16  00:00:00  neeri
+User interrupt stuff
+
+Revision 0.1  1992/03/31  00:00:00  neeri
+unix domain socket calls
+
+*********************************************************************/
+
+#include "GUSIFile_P.h"
+#include "GUSIMPW_P.h"
+#include <SetJmp.h>
+#include <Signal.h>
+#include <CursorCtl.h>
+#include <Resources.h>
+#include <Events.h> 
+#include <Windows.h>
+#include <Finder.h>
+#include <Script.h>
+#include <Events.h>
+#include <Traps.h>
+#include <CommResources.h>
+#include <CTBUtilities.h>
+#include <Connections.h>
+#include <FileTransfers.h>
+#include <Terminals.h>
+#include <EPPC.h>
+#include <PLStringFuncs.h>
+#include <LowMem.h>
+#include <Processes.h>
+
+#if GENERATINGCFM
+#include <CodeFragments.h>
+#endif
+
+#pragma segment GUSI
+
+/***************************** Globals ******************************/
+
+GUSIConfiguration GUSIConfig;          // Change the order of these declarations
+SocketTable                                    Sockets;                        //      and you'll regret it (ARM Â§12.6.1)
+GUSISpinFn                                     GUSISpin        = GUSIDefaultSpin;
+GUSIExecFn                                     GUSIExec        = GUSIDefaultExec;
+GUSIFTypeFn                                    GUSIFType       = (GUSIFTypeFn)0;
+long                                           gGUSISpeed      = 1;
+static GUSIEvtHandler *        evtHandler      = nil;
+static short                           evtMask         = 0;
+static int                                     errorSock       = -1;
+static int                                     errorType       = 0;
+static int                                     errorCount      = 0;
+const int                                      errorMax                = 3;
+Boolean                                                CatchStdIO      = false;
+
+Feature        hasMakeFSSpec(
+                               gestaltFSAttr,
+                               (1<<gestaltHasFSSpecCalls),
+                               (1<<gestaltHasFSSpecCalls));
+Feature        hasAlias(
+                               gestaltAliasMgrAttr,
+                               (1<<gestaltAliasMgrPresent),
+                               (1<<gestaltAliasMgrPresent));
+Feature        hasNewSF(
+                               gestaltStandardFileAttr,
+                               (1<<gestaltStandardFile58),
+                               (1<<gestaltStandardFile58));
+Feature        hasProcessMgr(
+                               gestaltOSAttr,
+                               (1<<gestaltLaunchControl),
+                               (1<<gestaltLaunchControl));
+Feature hasCRM_P(
+                               gestaltCRMAttr,
+                               (1<<gestaltCRMPresent),
+                               (1<<gestaltCRMPresent));
+Feature hasCRM(hasCRM_P, InitCRM);
+Feature hasCTB(hasCRM, InitCTBUtilities);
+Feature hasStdNBP_P(
+                               gestaltStdNBPAttr,
+                               (1<<gestaltStdNBPPresent),
+                               (1<<gestaltStdNBPPresent));
+Feature hasStdNBP(hasCTB, hasStdNBP_P);
+Feature hasAppleEvents(
+                               gestaltAppleEventsAttr,
+                               (1<<gestaltAppleEventsPresent),
+                               (1<<gestaltAppleEventsPresent));
+Feature hasRevisedTimeMgr(
+                       gestaltTimeMgrVersion,
+                       2L);
+
+/*********************** Error propagation ************************/
+
+#ifdef GUSI_DISPATCH
+inline
+#endif
+int GUSI_error(int err)
+{
+       if (err)
+               errno = err;
+
+       return -1;
+}
+
+#ifdef GUSI_DISPATCH
+inline
+#endif
+void * GUSI_error_nil(int err)
+{
+       if (err)
+               errno = err;
+
+       return nil;
+}
+
+/*********************** GUSIConfiguration members ************************/
+
+#ifndef GUSI_DISPATCH
+
+Boolean        GUSIConfiguration::firstTime = false;
+short          GUSIConfiguration::we;
+
+void GUSIConfiguration::GUSILoadConfiguration(Handle h)
+{
+       typedef         GUSIConfigRsrc **       GUSIConfHdl;            
+       GUSIConfHdl config              =       GUSIConfHdl(h);
+       long            confSize        =       config ? GetHandleSize(Handle(config)) : 0;
+       
+       if (confSize < 4 || !(defaultType = (*config)->defaultType))
+               defaultType     =       'TEXT';
+       if (confSize < 8 || !(defaultCreator = (*config)->defaultCreator))
+               defaultCreator  =       'MPS ';
+       if (confSize < 9) 
+               autoSpin        =       1;                      // do automatic spin on read/write
+       else
+               autoSpin = (*config)->autoSpin;
+                       
+       if (confSize < 14)
+               version = '0102';
+       else
+               version = (*config)->version;
+
+       if (confSize < 10) {
+               noChdir                 =       false;  // Use chdir()
+               accurStat               =       false;  // st_nlink = # of entries + 2
+               hasConsole              =       false;
+               noAutoInitGraf  =       false;
+               sharedOpen              =       false;
+               sigPipe                 =       false;
+               noAppleEvents   =       false;
+               delayConsole            =       false;
+       } else {
+               noChdir                 =       ((*config)->flags & 0x80) != 0;
+               accurStat               =       ((*config)->flags & 0x40) != 0;
+               hasConsole              =       version >= '0150' && version <= '0180' && ((*config)->flags & 0x08) != 0;
+               delayConsole    =       version >= '0181' && ((*config)->flags & 0x20) != 0;
+               noAppleEvents   =       version >= '0181' && ((*config)->flags & 0x08) != 0;
+               noAutoInitGraf  =       version >= '0174' && ((*config)->flags & 0x04) != 0;
+               sharedOpen              =       version >= '0174' && ((*config)->flags & 0x02) != 0;
+               sigPipe                 =       version >= '0174' && ((*config)->flags & 0x01) != 0;
+       }
+       
+       if (version < '0120' || confSize < 16)
+               numSuffices = 0;
+       else
+               numSuffices = (*config)->numSuffices;
+       
+       if (!numSuffices)
+               suffices = nil;
+       else if (suffices = new GUSISuffix[numSuffices]) {
+               HLock((Handle)config);
+               memcpy(suffices, (*config)->suffices, numSuffices*sizeof(GUSISuffix));
+               for (int i=0; i<numSuffices; i++)
+                       for (int j=0; j<4; j++)
+                               if (((char *) (suffices+i))[j] == ' ')
+                                       ((char *) (suffices+i))[j] = 0;
+       }
+}
+
+GUSIConfiguration::GUSIConfiguration()
+{
+       short   oldResFile = CurResFile();
+       
+       if (!firstTime)
+               we = oldResFile;
+       else
+               UseResFile(we);
+               
+       Handle config   =       Get1Resource('GU\85I', GUSIRsrcID);
+       GUSILoadConfiguration(config);  
+       if (!firstTime) {
+               firstTime       =       true;
+               
+               if (!noChdir)
+                       chdir(":");
+       } else
+               UseResFile(oldResFile);
+       
+       ReleaseResource((Handle)config);
+}
+
+void GUSIConfiguration::SetDefaultFType(const TFileSpec & name) const
+{
+       FInfo   info;   
+
+       // 
+       // Custom hook if existing
+       //
+       if (GUSIFType && GUSIFType(name))
+               return;
+       
+       //
+       // Otherwise default behaviour
+       //
+       if (HGetFInfo(name.vRefNum, name.parID, name.name, &info))
+               return;
+
+       Ptr dot = PLstrrchr(name.name, '.');
+       
+       if (dot && (name.name[0] - (dot-Ptr(name.name))) <= 4) {
+               char searchsuffix[5];
+               
+               strncpy(searchsuffix, dot+1, name.name[0] - (dot-Ptr(name.name)));
+               
+               for (int i = 0; i<numSuffices; i++)
+                       if (!strncmp(suffices[i].suffix, searchsuffix, 4)) {
+                               info.fdType     =       suffices[i].suffType;
+                               info.fdCreator  =       suffices[i].suffCreator;
+                               
+                               goto determined;
+                       }
+       }
+
+       info.fdType     =       defaultType;
+       info.fdCreator  =       defaultCreator;
+       info.fdFlags    &= ~kHasBeenInited;
+
+determined:    
+       HSetFInfo(name.vRefNum, name.parID, name.name, &info);
+}
+
+void GUSIConfiguration::DoAutoInitGraf() const
+{
+       if (*(GrafPtr **) LMGetCurrentA5() != &qd.thePort)
+               InitGraf(&qd.thePort);
+       const_cast<GUSIConfiguration *>(this)->noAutoInitGraf   =       true;
+}
+
+#endif // GUSI_DISPATCH
+
+inline void GUSIConfiguration::DoAutoSpin() const 
+{
+       if (autoSpin)
+               SAFESPIN(0, SP_AUTO_SPIN, autoSpin);
+}
+
+Boolean GUSIConfiguration::DelayConsole() const
+{
+       return delayConsole;
+}
+
+/************************ Handle nonstandard consoles *************************/
+
+#ifndef GUSI_DISPATCH
+
+static void InitConsole()
+{
+       if (MPWDomain::stdopen) {
+               for (int i = 0; i < 3; i++) {
+                       Socket * sock =         MPWDomain::stdopen(i);
+
+                       if (sock)
+                               Sockets.Install(sock);
+               }
+       } else {
+               if (open("dev:console", O_RDONLY) < 0)
+                       open("dev:null", O_RDONLY);
+               if (open("dev:console", O_WRONLY) < 0)
+                       open("dev:null", O_WRONLY);
+               if (open("dev:console", O_WRONLY) < 0)
+                       open("dev:null", O_WRONLY); 
+       }
+}
+
+void SocketTable::InitConsole()
+{
+       if (needsConsole) {
+               needsConsole = false;
+               ::InitConsole();
+       }
+}
+
+#endif // GUSI_DISPATCH
+
+/************************ External routines *************************/
+
+int getdtablesize()
+{
+       return GUSI_MAX_FD;
+}
+
+int socket(int domain, int type, int protocol)
+{
+       SocketDomain *  dom;
+       Socket *                sock;
+       int                             fd;
+
+       Sockets.InitConsole();
+       
+       if (dom = SocketDomain::Domain(domain))
+               if (sock = dom->socket(type, protocol))
+                       if ((fd = Sockets.Install(sock)) != -1)
+                               return fd;
+                       else
+                               delete sock;
+
+       if (!errno)
+               return GUSI_error(ENOMEM);
+       else
+               return -1;
+}
+
+int socketpair(int domain, int type, int protocol, int * sv)
+{
+       SocketDomain *  dom;
+       Socket *                sock[2];
+
+       Sockets.InitConsole();
+       
+       if (dom = SocketDomain::Domain(domain))
+               if (!dom->socketpair(type, protocol, sock))
+                       if ((sv[0] = Sockets.Install(sock[0])) != -1)
+                               if ((sv[1] = Sockets.Install(sock[1])) != -1)
+                                       return 0;
+                               else {
+                                       Sockets.Remove(sv[0]);
+                                       
+                                       goto failInstall;
+                               }
+                       else {
+failInstall:
+                               delete sock[0];
+                               delete sock[1];
+                       }
+               
+       if (!errno)
+               return GUSI_error(ENOMEM);
+       else
+               return -1;
+}
+
+int pipe(int * fd)
+{
+       GUSIwithUnixSockets();
+       
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd))
+               return -1;
+       shutdown(fd[0], 1);
+       shutdown(fd[1], 0);
+       
+       return 0;
+}
+
+int choose(int domain, int type, char * prompt, void * constraint, int flags, void * name, int * namelen)
+{
+       SocketDomain *  dom;
+
+       if (dom = SocketDomain::Domain(domain))
+               return dom->choose(type, prompt, constraint, flags, name, namelen);
+
+       return -1;
+}
+
+int bind(int s, const struct sockaddr *name, int namelen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->bind((void *) name, namelen) : -1;
+}
+
+int connect(int s, const struct sockaddr *addr, int addrlen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->connect((void *) addr, addrlen) : -1;
+}
+
+int listen(int s, int qlen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->listen(qlen) : -1;
+}
+
+int accept(int s, struct sockaddr *addr, int *addrlen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       if (sock)
+               if (sock        = sock->accept(addr, addrlen))
+                       if ((s = Sockets.Install(sock)) != -1)
+                               return s;
+                       else
+                               delete sock;
+
+       return -1;
+}
+
+int close(int s)
+{
+       errorSock       =       -1;
+       
+       return Sockets.Remove(s);
+}
+
+#ifdef __MWERKS__
+int read(int s, char *buffer, int buflen)
+#else
+int read(int s, char *buffer, unsigned buflen)
+#endif
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->read(buffer, (unsigned) buflen) : -1;
+}
+
+int readv(int s, const struct iovec *iov, int count)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       if (sock)       {
+               Scatterer       scatt(iov, count);
+
+               if (scatt)
+                       return scatt.length(sock->read(scatt.buffer(), scatt.buflen()));
+               else
+                       return GUSI_error(ENOMEM);
+       } else
+               return -1;
+}
+
+int recv(int s, void *buffer, int buflen, int flags)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       int             fromlen         =       0;
+       Socket *        sock            =       Sockets[s];
+
+       return sock ? sock->recvfrom(buffer, buflen, flags, nil, &fromlen) : -1;
+}
+
+int recvfrom(int s, void *buffer, int buflen, int flags, struct sockaddr *from, int *fromlen)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->recvfrom(buffer, buflen, flags, from, fromlen) : -1;
+}
+
+int recvmsg(int s, struct msghdr *msg, int flags)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       if (sock)       {
+               Scatterer       scatt((struct iovec *)msg->msg_iov, msg->msg_iovlen);
+
+               if (scatt)
+                       return
+                               scatt.length(
+                                       sock->recvfrom(
+                                               scatt.buffer(),
+                                               scatt.buflen(),
+                                               flags,
+                                               msg->msg_name,
+                                               (int *)&msg->msg_namelen));
+               else
+                       return GUSI_error(ENOMEM);
+       } else
+               return -1;
+}
+
+#ifdef __MWERKS__
+int write(int s, const char *buffer, int buflen)
+#else
+int write(int s, const char *buffer, unsigned buflen)
+#endif
+{
+       /* fflush() in the MPW stdio library doesn't take no for an answer.
+               Our workaround is to treat a second subsequent ESHUTDOWN or EBADF as 
+               an invitation to lie by pretending the write worked.
+       */
+       
+       int     len;
+       
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       if (sock && (len = sock->write((char *) buffer, (unsigned) buflen)) != -1)
+               return len;
+               
+       switch (errno) {
+       case EINTR:
+       case EWOULDBLOCK:
+       case EINPROGRESS:
+       case EALREADY:
+               break;
+       default:
+               if (GUSIConfig.sigPipe)
+                       raise(SIGPIPE);
+               if (errorSock == s && errorType == errno) {
+                       if (++errorCount == errorMax) {
+                               errorSock = -1;
+                       
+                               return buflen;
+                       }
+               } else {
+                       errorSock = s;
+                       errorType = errno;
+                       errorCount= 1;
+               }
+       }
+       return -1;
+}
+
+static int HandleWriteErrors(int retval)
+{
+       if (retval == -1)
+               switch (errno) {
+               case EINTR:
+               case EWOULDBLOCK:
+               case EINPROGRESS:
+               case EALREADY:
+                       break;
+               default:
+                       if (GUSIConfig.sigPipe)
+                               raise(SIGPIPE);
+                       break;
+               }
+       
+       return retval;
+}
+
+int writev(int s, const struct iovec *iov, int count)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       if (sock)       {
+               Gatherer        gath(iov, count);
+
+               if (gath)
+                       return HandleWriteErrors(gath.length(sock->write(gath.buffer(), gath.buflen())));
+               else
+                       return GUSI_error(ENOMEM);
+       } else
+               return -1;
+}
+
+int send(int s, const void *buffer, int buflen, int flags)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? HandleWriteErrors(sock->sendto((void *)buffer, buflen, flags, nil, 0)) : -1;
+}
+
+int sendto(int s, const void *buffer, int buflen, int flags, const struct sockaddr *to, int tolen)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? HandleWriteErrors(sock->sendto((void *)buffer, buflen, flags, (void *) to, tolen)) : -1;
+}
+
+int sendmsg(int s, const struct msghdr *msg, int flags)
+{
+       GUSIConfig.DoAutoSpin();
+       
+       Socket *        sock    =       Sockets[s];
+
+       if (sock)       {
+               Gatherer        gath((struct iovec *) msg->msg_iov, msg->msg_iovlen);
+
+               if (gath)
+                       return
+                               HandleWriteErrors(gath.length(
+                                       sock->sendto(
+                                               gath.buffer(),
+                                               gath.buflen(),
+                                               flags,
+                                               msg->msg_name,
+                                               msg->msg_namelen)));
+               else
+                       return GUSI_error(ENOMEM);
+       } else
+               return -1;
+}
+
+int select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+       Socket  *       sock;
+       long                    count;
+       int                     s;
+       long                    starttime, waittime;
+       fd_set          rd, wd, ed;
+       Boolean         r,w,e;
+       Boolean *       canRead;
+       Boolean *       canWrite;
+       Boolean *       exception;
+
+       count = 0;
+       FD_ZERO(&rd);
+       FD_ZERO(&wd);
+       FD_ZERO(&ed);
+
+       if (timeout)
+               waittime =  timeout->tv_sec*60 + timeout->tv_usec/16666;
+       else
+               waittime =      2000000000;     // Slightly more than a year; close enough to "no timeout"
+               
+       starttime = LMGetTicks();
+
+       // Check files for kosherness
+
+       for (s = 0; s < width ; ++s)
+               if (    (readfds && FD_ISSET(s,readfds))
+                       ||      (writefds && FD_ISSET(s,writefds))
+                       ||      (exceptfds && FD_ISSET(s,exceptfds))
+               )
+                       if (!Sockets[s])
+                               return GUSI_error(EBADF);
+       
+       for (s = 0; s < width ; ++s)
+               if (sock = Sockets[s]) {
+                       r = readfds && FD_ISSET(s,readfds);
+                       w = writefds && FD_ISSET(s,writefds);
+                       e = exceptfds && FD_ISSET(s,exceptfds);
+
+                       if (r || w || e)
+                               sock->pre_select(r, w, e);
+               }
+               
+       do {
+               for (s = 0; s < width ; ++s)  {
+                       if (sock = Sockets[s]) {
+                               r = false;
+                               w = false;
+                               e = false;
+
+                               canRead = (readfds && FD_ISSET(s,readfds)) ? &r : nil;
+                               canWrite = (writefds && FD_ISSET(s,writefds)) ? &w : nil;
+                               exception = (exceptfds && FD_ISSET(s,exceptfds)) ? &e : nil;
+
+                               if (canRead || canWrite || exception)   {
+                                       count   += sock->select(canRead, canWrite, exception);
+
+                                       if (r)
+                                               FD_SET(s,&rd);
+                                       if (w)
+                                               FD_SET(s,&wd);
+                                       if (e)
+                                               FD_SET(s,&ed);
+                               }
+                       }
+               }
+               if (count)
+                       break;
+
+               SAVE_AND_CLEAR_ERRNO;
+               SAFESPIN(false, SP_SELECT, waittime);
+
+               if (errno) {
+                       count = -1;
+                       
+                       break;
+               }
+       }  while (LMGetTicks() - starttime < waittime);
+
+       for (s = 0; s < width ; ++s)
+               if (sock = Sockets[s]) {
+                       r = readfds && FD_ISSET(s,readfds);
+                       w = writefds && FD_ISSET(s,writefds);
+                       e = exceptfds && FD_ISSET(s,exceptfds);
+
+                       if (r || w || e)
+                               sock->post_select(r, w, e);
+               }
+               
+       if (count < 0)
+               return GUSI_error(EINTR);
+               
+       if (readfds)
+               *readfds = rd;
+       if (writefds)
+               *writefds = wd;
+       if (exceptfds)
+               *exceptfds = ed;
+
+       return count;
+}
+
+int getsockname(int s, struct sockaddr *name, int *namelen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->getsockname(name, namelen) : -1;
+}
+
+int getpeername(int s, struct sockaddr *name, int *namelen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->getpeername(name, namelen) : -1;
+}
+
+int shutdown(int s, int how)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->shutdown(how) : -1;
+}
+
+int fcntl(int s, unsigned int cmd, int arg)
+{
+       Socket *        sock    =       Sockets[s];
+
+       if (sock)
+               return (cmd == F_DUPFD) ? Sockets.Install(sock, arg) : sock->fcntl(cmd, arg);
+       else
+               return -1;
+}
+
+int dup(int s)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? Sockets.Install(sock) : -1;
+}
+
+int dup2(int s, int s1)
+{
+       Socket *        sock    =       Sockets[s];
+
+       if (!sock)
+               return -1;
+
+       if (Sockets[s1])
+               Sockets.Remove(s1);
+
+       return Sockets.Install(sock, s1);
+}
+
+int ioctl(int s, unsigned int request, long *argp)
+{
+       Socket *        sock    =       Sockets[s];
+
+       if (!sock)
+               return -1;
+       
+       return sock->ioctl(request, argp);
+}
+
+int getsockopt(int s, int level, int optname, void *optval, int * optlen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->getsockopt(level, optname, optval, optlen) : -1;
+}
+
+int setsockopt(int s, int level, int optname, const void *optval, int optlen)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->setsockopt(level, optname, (void *) optval, optlen) : -1;
+}
+
+int fstat(int s, struct stat * buf)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->fstat(buf) : -1;
+}
+
+long lseek(int s, long offset, int whence)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->lseek(offset, whence) : -1;
+}
+
+int ftruncate(int s, long offset)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->ftruncate(offset) : -1;
+}
+
+int isatty(int s)
+{
+       Socket *        sock    =       Sockets[s];
+
+       return sock ? sock->isatty() : -1;
+}
+
+void GUSISetHook(GUSIHookCode code, GUSIHook hook)
+{
+       switch (code) {
+       case GUSI_SpinHook:
+               GUSISpin = (GUSISpinFn) hook;
+               break;
+       case GUSI_ExecHook:
+               GUSIExec = (GUSIExecFn) hook;
+               break;
+       case GUSI_FTypeHook:
+               GUSIFType = (GUSIFTypeFn) hook;
+               break;
+       case GUSI_SpeedHook:
+               gGUSISpeed = (long) hook;
+               break;
+       }
+}
+
+GUSIHook GUSIGetHook(GUSIHookCode code)
+{
+       switch (code) {
+       case GUSI_SpinHook:
+               return (GUSIHook) GUSISpin;
+       case GUSI_ExecHook:
+               return (GUSIHook) GUSIExec;
+       case GUSI_FTypeHook:
+               return (GUSIHook) GUSIFType;
+       case GUSI_SpeedHook:
+               return (GUSIHook) gGUSISpeed;
+               break;
+       default:
+               return (GUSIHook) nil;
+       }
+}
+
+int GUSISetEvents(GUSIEvtTable table)
+{
+       short   evt;
+
+       evtHandler      =       table;
+       evtMask         =       0;
+
+       for (evt = 0; evt<16; ++evt)
+               if (evtHandler[evt])
+                       evtMask |=      1 << evt;
+
+       return 0;
+}
+
+GUSIEvtHandler * GUSIGetEvents(void)
+{
+       return evtHandler;
+}
+
+/*********************** SocketDomain members ***********************/
+
+#ifndef GUSI_DISPATCH
+
+SocketDomain *                 SocketDomain::domains[GUSI_MAX_DOMAIN];
+ProcessSerialNumber    SocketDomain::process;
+
+SocketDomain * SocketDomain::Domain(int domain)
+{
+       if (domain < 0 || domain >= GUSI_MAX_DOMAIN || !domains[domain])        {
+               GUSI_error(EINVAL);
+
+               return nil;
+       } else
+               return domains[domain];
+}
+
+void SocketDomain::Ready()
+{
+       if (hasProcessMgr)
+               WakeUpProcess(&process);
+}
+
+SocketDomain::SocketDomain(int domain)
+{
+#ifdef PREVENT_DUPLICATE_DOMAINS
+       if (domains[domain])    {
+               Str63   msg;
+
+               sprintf((char *) msg+1, "Duplicate declaration for domain %d\n", domain);
+               msg[0] = (unsigned char)strlen((char *) msg+1);
+
+               DebugStr(msg);
+       }
+#endif
+       if (domain)                                                                     // Ignore AF_UNSPEC domains
+               domains[domain] =       this;
+       
+       if (hasProcessMgr && !process.highLongOfPSN && !process.lowLongOfPSN)
+               GetCurrentProcess(&process);
+}
+
+SocketDomain::~SocketDomain()
+{
+}
+
+// Default implementations of socket() just returns an error
+
+Socket * SocketDomain::socket(int, short)
+{
+       GUSI_error(EOPNOTSUPP);
+
+       return nil;
+}
+
+// Same with socketpair
+
+int SocketDomain::socketpair(int, short, Socket **)
+{
+       return GUSI_error(EOPNOTSUPP);
+}
+
+
+int SocketDomain::choose(int, char *, void *, int, void *, int *)
+{
+       return GUSI_error(EOPNOTSUPP);
+}
+
+void SocketDomain::DontStrip()
+{
+}
+
+/*********************** SocketTable members ************************/
+
+static void FlushStdio()
+{
+       fwalk(fflush);
+}
+
+SocketTable::SocketTable()
+{
+       atexit(FlushStdio);
+       
+       needsConsole = true;
+}
+       
+int SocketTable::Install(Socket * sock, int start)
+{
+       short   fd;
+
+       if (start<0 || start >= GUSI_MAX_FD)
+               return GUSI_error(EINVAL);
+
+       for (fd=start; fd<GUSI_MAX_FD; ++fd)
+               if (!sockets[fd])       {
+                       sockets[fd] = sock;
+               
+                       ++sock->refCount;
+                       return fd;
+               }
+
+       return GUSI_error(EMFILE);
+}
+
+int SocketTable::Remove(int fd)
+{
+       Socket *        sock;
+
+       InitConsole();
+
+       if (fd<0 || fd >= GUSI_MAX_FD || !(sock = sockets[fd]))
+               return GUSI_error(EBADF);
+
+       sockets[fd]     =       nil;
+
+       if (!--sock->refCount)
+               delete sock;
+
+       return 0;
+}
+
+Socket * SocketTable::operator[](int fd)
+{
+       Socket * sock;
+
+       InitConsole();
+       
+       if (fd<0 || fd >= GUSI_MAX_FD || !(sock = sockets[fd])) {
+               GUSI_error(EBADF);
+
+               return nil;
+       } else
+               return sock;
+}
+
+#ifndef powerc
+#pragma far_code
+#endif
+
+SocketTable::~SocketTable()
+{
+       int i;
+
+       // Flush stdio files (necessary to flush buffers)
+
+       fwalk(fflush);
+
+       // If we didn't need a console so far, we certainly don't need one now!
+       // Doing this further up would be dangerous for small write only apps
+       
+       needsConsole = false;
+
+       // Now close stdio files, just to be sure
+
+       fwalk(fclose);
+
+       // Close all files
+
+       for (i = 0; i<GUSI_MAX_FD; ++i)
+               if (sockets[i])
+                       close(i);
+}
+
+#endif // GUSI_DISPATCH
+
+/********************** sleep()/alarm() ***********************/
+
+static long    GUSIAlarm = 0;
+
+int GUSICheckAlarm()
+{
+       if (GUSIAlarm && LMGetTicks() > GUSIAlarm) {
+               GUSIAlarm = 0;
+               raise(SIGALRM);
+               
+               return 1;
+       } else
+               return 0;
+}
+
+u_int   alarm(u_int seconds)
+{
+       long remaining = GUSIAlarm ? (LMGetTicks() - GUSIAlarm) / 60 : 0;
+       
+       GUSIAlarm = seconds ? LMGetTicks() + 60 * seconds : 0;
+       
+       return (remaining < 0) ? 0 : (u_int) remaining;
+}
+
+static u_int DoSleep(long ticks)
+{
+       long wakeup = LMGetTicks() + ticks;
+       
+       SAFESPIN(wakeup > LMGetTicks(), SP_SLEEP, wakeup - LMGetTicks());
+       
+       long remaining = (LMGetTicks() - wakeup) / 60;
+       
+       return (remaining < 0) ? 0 : (u_int) remaining;
+}
+
+u_int sleep(u_int seconds) 
+{
+       return DoSleep(seconds * 60);
+}
+
+void usleep(u_int useconds)
+{
+       DoSleep((useconds * 3) / 50000);
+}
+
+/********************** Default spin function ***********************/
+
+#ifndef GUSI_DISPATCH
+
+#ifndef powerc
+#pragma smart_code
+#endif
+
+/* Borrowed from tech note 263 */
+
+#define kMaskModifiers         0xFE00          // we need the modifiers without the
+                                               // command key for KeyTrans
+#define kMaskVirtualKey        0x0000FF00      // get virtual key from event message
+                                               // for KeyTrans
+#define kUpKeyMask             0x0080
+#define kShiftWord             8               // we shift the virtual key to mask it
+                                               // into the keyCode for KeyTrans
+#define kMaskASCII1            0x00FF0000      // get the key out of the ASCII1 byte
+#define kMaskASCII2            0x000000FF      // get the key out of the ASCII2 byte
+#define kPeriod                0x2E            // ascii for a period
+
+static Boolean CmdPeriod(EventRecord *theEvent)
+{
+       Boolean  fTimeToQuit;
+       short    keyCode;
+       long     virtualKey, keyInfo, lowChar, highChar, keyCId;
+       UInt32  state;
+       Handle   hKCHR;
+       Ptr             KCHRPtr;
+
+       fTimeToQuit = false;
+
+       if (((*theEvent).what == keyDown) || ((*theEvent).what == autoKey)) {
+
+               // see if the command key is down.  If it is, find out the ASCII
+               // equivalent for the accompanying key.
+
+               if ((*theEvent).modifiers & cmdKey ) {
+
+                       virtualKey = ((*theEvent).message & kMaskVirtualKey) >> kShiftWord;
+                       // And out the command key and Or in the virtualKey
+                       keyCode    = short(((*theEvent).modifiers & kMaskModifiers) | virtualKey);
+                       state      = 0;
+
+                       hKCHR = nil;  /* set this to nil before starting */
+                       KCHRPtr = (Ptr)GetScriptManagerVariable(smKCHRCache);
+
+                       if ( !KCHRPtr ) {
+                               keyCId = GetScriptVariable(short(GetScriptManagerVariable(smKeyScript)), smScriptKeys);
+
+                               hKCHR   = GetResource('KCHR',short(keyCId));
+                               KCHRPtr = *hKCHR;
+                       }
+
+                       if (KCHRPtr) {
+                               keyInfo = KeyTrans(KCHRPtr, keyCode, &state);
+                               if (hKCHR)
+                                       ReleaseResource(hKCHR);
+                       } else
+                               keyInfo = (*theEvent).message;
+
+                       lowChar =  keyInfo &  kMaskASCII2;
+                       highChar = (keyInfo & kMaskASCII1) >> 16;
+                       if (lowChar == kPeriod || highChar == kPeriod)
+                               fTimeToQuit = true;
+
+               }  // end the command key is down
+       }  // end key down event
+
+       return( fTimeToQuit );
+}
+
+Boolean GUSIInterrupt()
+{
+       EvQElPtr                eventQ;
+
+       for (eventQ = (EvQElPtr) LMGetEventQueue()->qHead; eventQ; )
+               if (CmdPeriod((EventRecord *) &eventQ->evtQWhat))
+                       return true;
+               else
+                       eventQ = (EvQElPtr)eventQ->qLink;
+       
+       return false;
+}
+
+int StandAlone = 1;
+long gGUSISpinControl = 0;
+
+int GUSIDefaultSpin(spin_msg msg, long arg)
+{
+       static Boolean                  inForeground    =       true;
+       WindowPtr                               win;
+       EventRecord                             ev;
+       long                                    sleepTime       =       6;      // 1/10 of a second by default
+       short                                   mask            =       osMask|highLevelEventMask|mDownMask|evtMask;
+
+       GUSIConfig.AutoInitGraf();
+       
+       if (inForeground) {
+               register long contrib = (msg == SP_AUTO_SPIN) ? arg : gGUSISpeed;
+               gGUSISpinControl += contrib;
+               // Tweak when a spin point has been overshot
+               RotateCursor((gGUSISpinControl & 31) < contrib ? 32 : gGUSISpinControl);
+       }
+
+       if (GUSIInterrupt())
+               goto interrupt;
+
+       if (!StandAlone && inForeground)                // For MPW tools, SpinCursor already calls WNE
+               if (!GUSIConfig.noAppleEvents)                  // but it no longer reports AppleEvents
+                       mask = highLevelEventMask|evtMask;
+               else
+                       return 0;                                                               
+               
+       switch (msg) {
+       case SP_SLEEP:
+       case SP_SELECT:
+               if (arg >= sleepTime)                           // Only sleep if patience guaranteed
+                       break;
+               // Otherwise, fall through      
+       case SP_AUTO_SPIN:
+               sleepTime = 0;
+               break;
+       default:
+               break;
+       }
+       
+       if (WaitNextEvent(mask, &ev, sleepTime, nil))
+               switch (ev.what) {
+               case mouseDown:
+                       if (!evtHandler || !evtHandler[mouseDown])
+                               if (FindWindow(ev.where, &win) == inSysWindow)
+                                       SystemClick(&ev, win);
+
+                       break;
+               case osEvt:
+                       if (ev.message & 1)
+                               inForeground    =       true;
+                       else
+                               inForeground    =       false;
+                       break;
+               case kHighLevelEvent:
+                       if (!evtHandler || !evtHandler[kHighLevelEvent])
+                               if (hasAppleEvents)                             // actually pretty likely, if we get HL Events
+                                       AEProcessAppleEvent(&ev);       // Ignore errors
+                       break;
+               default:
+                       break;
+               }
+
+       if (ev.what >= 0 && ev.what < 24 && evtHandler && evtHandler[ev.what])
+               evtHandler[ev.what](&ev);
+
+       return 0;
+
+interrupt:
+       FlushEvents(-1, 0);
+
+       return -1;
+}
+
+/************************** Feature members **************************/
+
+Feature::Feature(unsigned short trapNum, TrapType tTyp)
+{
+       good =
+               NGetTrapAddress(trapNum, tTyp) != NGetTrapAddress(_Unimplemented, ToolTrap);
+}
+
+Feature::Feature(OSType type, long value)
+{
+       long            attr;
+
+       good = (!Gestalt(type, &attr) && (attr >= value));
+}
+
+Feature::Feature(OSType type, long mask, long value)
+{
+       long            attr;
+
+       good = (!Gestalt(type, &attr) && ((attr & mask) == value));
+}
+
+Feature::Feature(const Feature & precondition, OSErrInitializer init)
+{
+       good    =       precondition && !init();
+}
+
+Feature::Feature(OSErrInitializer init)
+{
+       good    =       !init();
+}
+
+Feature::Feature(const Feature & precondition, voidInitializer init)
+{
+       if (precondition)       {
+               good = true;
+               init();
+       } else
+               good = false;
+}
+
+Feature::Feature(voidInitializer init)
+{
+       good = true;
+       init();
+}
+
+Feature::Feature(const Feature & cond1, const Feature & cond2)
+{
+       good = cond1 && cond2;
+}
+
+OSErr AppleTalkIdentity(short & net, short & node)
+{
+       static short    mynet;
+       static short    mynode;
+       static OSErr    err = 1;
+
+       if (err == 1)
+               if (!(err = MPPOpen()))
+                       err = GetNodeAddress(&mynode, &mynet);
+
+
+       net     =       mynet;
+       node    =       mynode;
+
+       return err;
+}
+
+/************************** Setup suppport **************************/
+
+/* Pray that the following function never inlines GUSISetup */
+
+void GUSIDefaultSetup()
+{
+       GUSISetup(GUSIwithAppleTalkSockets);
+       GUSISetup(GUSIwithInternetSockets);
+       GUSISetup(GUSIwithPAPSockets);
+       GUSISetup(GUSIwithPPCSockets);
+       GUSISetup(GUSIwithUnixSockets);
+       GUSISetup(GUSIwithSIOUXSockets);
+}
+
+void GUSISetup(void (*proc)())
+{
+       proc();
+}
+
+void GUSILoadConfiguration(Handle hdl)
+{
+       GUSIConfig.GUSILoadConfiguration(hdl);
+}
+
+#endif // GUSI_DISPATCH
diff --git a/Mac/GUSI-mods/into-src/GUSINetDB.cp b/Mac/GUSI-mods/into-src/GUSINetDB.cp
new file mode 100644 (file)
index 0000000..bc435b6
--- /dev/null
@@ -0,0 +1,579 @@
+/*********************************************************************
+Project        :       GUSI                            -       Grand Unified Socket Interface
+File           :       GUSINetDB.cp    -       Convert internet names to adresses
+Author :       Matthias Neeracher
+
+       This file was derived from the socket library by
+
+               Charlie Reiman  <creiman@ncsa.uiuc.edu> and
+               Tom Milligan    <milligan@madhaus.utcs.utoronto.ca>
+
+Language       :       MPW C++
+
+$Log$
+Revision 1.1  1998/08/18 14:52:38  jack
+Putting Python-specific GUSI modifications under CVS.
+
+Revision 1.3  1994/08/10  00:07:30  neeri
+Sanitized for universal headers.
+
+Revision 1.2  1994/05/01  23:43:31  neeri
+getservbyname() without /etc/services would fail.
+
+Revision 1.1  1994/02/25  02:29:36  neeri
+Initial revision
+
+Revision 0.5  1993/10/31  00:00:00  neeri
+Deferred opening of resolver
+
+Revision 0.4  1993/07/29  00:00:00  neeri
+Real getservent code (adapted from Sak Wathanasin)
+
+Revision 0.3  1993/01/19  00:00:00  neeri
+Can't set aliases to NULL.
+
+Revision 0.2  1992/11/21  00:00:00  neeri
+Remove force_active
+
+Revision 0.1  1992/09/14  00:00:00  neeri
+Maybe it works, maybe it doesn't
+
+*********************************************************************/
+
+#include "GUSIINET_P.h"
+
+#include "TFileSpec.h"
+#include "Folders.h"
+#include "PLStringFuncs.h"
+
+#ifdef __MWERKS__
+//
+// I disapprove of the way dnr.c is written
+// This disapproval gets stronger with every version
+//
+#include "dnr.c"
+#pragma require_prototypes reset
+#pragma cplusplus reset
+#endif
+
+#if GENERATING68K
+#pragma segment GUSIINET
+#endif
+
+static pascal void DNRDone(struct hostInfo *, Boolean * done)
+{
+       *done = true;
+}
+
+#if GENERATINGCFM
+RoutineDescriptor      uDNRDone = 
+               BUILD_ROUTINE_DESCRIPTOR(uppResultProcInfo, DNRDone);
+#else
+#define uDNRDone DNRDone
+#endif
+
+int h_errno;
+
+/*
+ *   Gethostbyname and gethostbyaddr each return a pointer to an
+ *   object with the following structure describing an Internet
+ *   host referenced by name or by address, respectively. This
+ *   structure contains the information obtained from the MacTCP
+ *   name server.
+ *
+ *   struct    hostent
+ *   {
+ *        char *h_name;
+ *        char **h_aliases;
+ *        int  h_addrtype;
+ *        int  h_length;
+ *        char **h_addr_list;
+ *   };
+ *   #define   h_addr  h_addr_list[0]
+ *
+ *   The members of this structure are:
+ *
+ *   h_name       Official name of the host.
+ *
+ *   h_aliases    A zero terminated array of alternate names for the host.
+ *
+ *   h_addrtype   The type of address being  returned; always AF_INET.
+ *
+ *   h_length     The length, in bytes, of the address.
+ *
+ *   h_addr_list  A zero terminated array of network addresses for the host.
+ *
+ *   Error return status from gethostbyname and gethostbyaddr  is
+ *   indicated by return of a null pointer.  The external integer
+ *   h_errno may then  be checked  to  see  whether  this  is  a
+ *   temporary  failure  or  an  invalid  or  unknown  host.  The
+ *   routine herror  can  be  used  to  print  an error  message
+ *   describing the failure.  If its argument string is non-NULL,
+ *   it is printed, followed by a colon and a space.   The  error
+ *   message is printed with a trailing newline.
+ *
+ *   h_errno can have the following values:
+ *
+ *     HOST_NOT_FOUND  No such host is known.
+ *
+ *     TRY_AGAIN       This is usually a temporary error and
+ *                                     means   that  the  local  server  did  not
+ *                                     receive a response from  an  authoritative
+ *                                     server.   A  retry at some later time may
+ *                                     succeed.
+ *
+ *     NO_RECOVERY     Some unexpected server failure was encountered.
+ *                                     This is a non-recoverable error.
+ *
+ *     NO_DATA         The requested name is valid but  does  not
+ *                                     have   an IP  address;  this  is not  a
+ *                                     temporary error. This means that the  name
+ *                                     is known  to the name server but there is
+ *                                     no address  associated  with  this  name.
+ *                                     Another type of request to the name server
+ *                                     using this domain name will result in  an
+ *                                     answer;  for example, a mail-forwarder may
+ *                                     be registered for this domain.
+ *                                     (NOT GENERATED BY THIS IMPLEMENTATION)
+ */
+
+static struct hostInfo macHost;
+
+#define MAXALIASES 0
+static char *aliasPtrs[MAXALIASES+1] = {NULL};
+static ip_addr *addrPtrs[NUM_ALT_ADDRS+1];
+
+static struct hostent  unixHost =
+{
+       macHost.cname,
+       aliasPtrs,
+       AF_INET,
+       sizeof(ip_addr),
+       (char **) addrPtrs
+};
+
+inline struct in_addr make_in_addr(ip_addr addr)
+{
+       struct in_addr  res;
+
+       res.s_addr      =       addr;
+
+       return res;
+}
+
+struct hostent * gethostbyname(char *name)
+{
+       Boolean done;
+       int i;
+
+       if (!strcmp(name, "localhost")) {
+               in_addr ipaddr;
+
+               ipaddr  =       make_in_addr(ip_addr(gethostid()));
+
+               if (ipaddr.s_addr)
+                       return gethostbyaddr((char *) &ipaddr, sizeof(in_addr), AF_INET);
+
+               h_errno = HOST_NOT_FOUND;
+                       
+               return NULL;
+       }
+       
+       if (INETSockets.Resolver()) {
+               h_errno = NO_RECOVERY;  
+               return NULL;
+       }
+       
+       for (i=0; i<NUM_ALT_ADDRS; i++)
+               macHost.addr[i] = 0;
+
+       done = false;
+
+       if (StrToAddr(name, &macHost, ResultUPP(&uDNRDone), (char *) &done) == cacheFault)
+               SPINP(!done,SP_NAME,0L);
+
+       switch (macHost.rtnCode) {
+       case noErr: break;
+
+       case nameSyntaxErr:     h_errno = HOST_NOT_FOUND;       return(NULL);
+       case cacheFault:                h_errno = NO_RECOVERY;          return(NULL);
+       case noResultProc:      h_errno = NO_RECOVERY;          return(NULL);
+       case noNameServer:      h_errno = HOST_NOT_FOUND;       return(NULL);
+       case authNameErr:               h_errno = HOST_NOT_FOUND;       return(NULL);
+       case noAnsErr:                  h_errno = TRY_AGAIN;                    return(NULL);
+       case dnrErr:                    h_errno = NO_RECOVERY;          return(NULL);
+       case outOfMemory:               h_errno = TRY_AGAIN;                    return(NULL);
+       default:                                        h_errno = NO_RECOVERY;          return(NULL);
+       }
+
+       /* was the 'name' an IP address? */
+       if (macHost.cname[0] == 0) {
+               h_errno = HOST_NOT_FOUND;
+               return(NULL);
+       }
+
+       /* for some reason there is a dot at the end of the name */
+       i = int(strlen(macHost.cname)) - 1;
+       if (macHost.cname[i] == '.')
+               macHost.cname[i] = 0;
+
+       for (i=0; i<NUM_ALT_ADDRS && macHost.addr[i]!=0; i++)
+               addrPtrs[i] =   (ip_addr *) &macHost.addr[i];
+
+       addrPtrs[i] = NULL;
+
+       return &unixHost;
+}
+
+struct hostent * gethostbyaddr(const char *addrP, int, int)
+{
+       Boolean done;
+       int             i;
+
+       if (INETSockets.Resolver()) {
+               h_errno = NO_RECOVERY;  
+               return NULL;
+       }
+
+       for (i=0; i<NUM_ALT_ADDRS; i++)
+               macHost.addr[i] = 0;
+
+       done = false;
+
+       ip_addr addr = FIX_LOOPBACK(*(ip_addr *)addrP);
+       
+       if (AddrToName(addr, &macHost, ResultUPP(&uDNRDone), (char *) &done) == cacheFault)
+               SPINP(!done,SP_ADDR,0L);
+
+       switch (macHost.rtnCode) {
+       case noErr:                     break;
+
+       case cacheFault:                h_errno = NO_RECOVERY;          return(NULL);
+       case noNameServer:      h_errno = HOST_NOT_FOUND;       return(NULL);
+       case authNameErr:               h_errno = HOST_NOT_FOUND;       return(NULL);
+       case noAnsErr:                  h_errno = TRY_AGAIN;                    return(NULL);
+       case dnrErr:                    h_errno = NO_RECOVERY;          return(NULL);
+       case outOfMemory:               h_errno = TRY_AGAIN;                    return(NULL);
+       default:                                        h_errno = NO_RECOVERY;          return(NULL);
+       }
+
+       /* for some reason there is a dot at the end of the name */
+       i = int(strlen(macHost.cname)) - 1;
+       if (macHost.cname[i] == '.')
+               macHost.cname[i] = 0;
+
+       /* For some reason, the IP address usually seems to be set to 0 */
+       if (!macHost.addr[0])
+               macHost.addr[0] = addr;
+               
+       for (i=0; i<NUM_ALT_ADDRS; i++)
+               addrPtrs[i] = (ip_addr *) &macHost.addr[i];
+
+       addrPtrs[NUM_ALT_ADDRS] = NULL;
+
+       return &unixHost;
+}
+
+char * inet_ntoa(struct in_addr inaddr)
+{
+       if (INETSockets.Resolver()) {
+               h_errno = NO_RECOVERY;  
+               return NULL;
+       }
+       
+       (void) AddrToStr(inaddr.s_addr, macHost.cname);
+
+       return macHost.cname;
+}
+
+struct in_addr inet_addr(char *address)
+{
+       if (INETSockets.Resolver()) {
+               h_errno = NO_RECOVERY;  
+               return make_in_addr(0xFFFFFFFF);
+       }
+       
+       if (StrToAddr(address,&macHost,NULL,NULL) != noErr)
+               return make_in_addr(0xFFFFFFFF);
+
+       /* was the 'address' really a name? */
+       if (macHost.cname[0] != 0)
+               return make_in_addr(0xFFFFFFFF);
+
+       return make_in_addr(macHost.addr[0]);
+}
+
+/*
+ * gethostid()
+ *
+ * Get internet address of current host
+ */
+
+long gethostid()
+{
+       static long sHostID = 0;
+       if (sHostID)
+               return sHostID;
+       
+       struct GetAddrParamBlock pbr;
+               
+       pbr.ioCRefNum   = INETSockets.Driver();
+       pbr.csCode              = ipctlGetAddr;
+
+       if (PBControlSync(ParmBlkPtr(&pbr)))
+               return 0;
+       else
+               return sHostID = (long)pbr.ourAddress;
+}
+
+/*
+ * gethostname()
+ *
+ * Try to get my host name from DNR. If it fails, just return my
+ * IP address as ASCII. This is non-standard, but it's a mac,
+ * what do you want me to do?
+ */
+
+int gethostname(char *machname, int buflen)
+{
+       static char * sHostName = nil;
+       
+       if (!sHostName) {
+               in_addr ipaddr;
+               struct  hostent *hp;
+
+               ipaddr  =       make_in_addr(ip_addr(gethostid()));
+
+               if (!ipaddr.s_addr)                                     // TCP/IP not up at all
+                       return GUSI_error(ENETDOWN);
+               
+               hp = gethostbyaddr((char *) &ipaddr, sizeof(in_addr), AF_INET);
+
+               if (!hp) {
+                       // No good name
+                       if (buflen < 16)                                                // Not enough space
+                               return GUSI_error(EINVAL);      
+                       sprintf(machname, "%d.%d.%d.%d",
+                                                       ipaddr.s_addr>>24,
+                                                       ipaddr.s_addr>>16 & 0xff,
+                                                       ipaddr.s_addr>>8 & 0xff,
+                                                       ipaddr.s_addr & 0xff);
+                       return 0;
+               } else {
+                       // We only cache satisfactory replies in sHostName
+                       sHostName = new char[strlen(hp->h_name)+1];
+                       strcpy(sHostName, hp->h_name);
+               }
+       }
+       strncpy(machname, sHostName, unsigned(buflen));
+       machname[buflen-1] = 0;  /* extra safeguard */
+
+       return 0;
+}
+
+
+/*
+ *     getservbybname()
+ *
+ */
+
+static char * servlist[] =
+{
+       "echo                     7/udp",
+       "discard          9/udp",
+       "time                    37/udp",
+       "domain          53/udp",
+       "sunrpc         111/udp",
+       "tftp            69/udp",
+       "biff                   512/udp",
+       "who            513/udp",
+       "talk                   517/udp",
+       "ftp-data        20/tcp",
+       "ftp             21/tcp",
+       "telnet          23/tcp",
+       "smtp            25/tcp",
+       "time            37/tcp",
+       "whois                   43/tcp",
+       "domain                  53/tcp",
+       "hostnames  101/tcp",
+       "nntp                   119/tcp",
+       "finger          79/tcp",
+       "ntp            123/tcp",
+       "uucp                   540/tcp",
+       NULL
+};
+
+static char                            servline[128];
+static struct servent  serv;
+static FILE *                          servfil;
+static int                                     servptr;
+static char *                          servalias[8];
+static int                                     servstay = 0;
+
+void setservent(int stayopen)
+{
+       if (servfil && servfil != (FILE *) -1) {
+               rewind(servfil);
+       }
+       servptr = 0;
+       servstay = servstay || stayopen;
+}
+
+void endservent()
+{
+       if (servfil && servfil != (FILE *) -1) {
+               fclose(servfil);
+               servfil = NULL;
+       }
+       
+       servstay = 0;
+}
+
+struct servent *  getservent()
+{
+       char *  p;
+       int             aliascount;
+       
+       if (!servfil) {
+               TFileSpec serv;
+               
+               if (!FindFolder(
+                               kOnSystemDisk, 
+                               kPreferencesFolderType, 
+                               kDontCreateFolder, 
+                               &serv.vRefNum,
+                               &serv.parID)
+               ) {
+                       PLstrcpy(serv.name, (StringPtr) "\p/etc/services");
+               
+                       if (servfil = fopen(serv.FullPath(), "r"))
+                               goto retry;
+               }       
+               servfil         = (FILE *) -1;
+               servptr = 0;
+       }
+       
+retry:
+       if (servfil == (FILE *) -1)
+               if (!servlist[servptr])
+                       return (struct servent *) NULL;
+               else
+                       strcpy(servline, servlist[servptr++]);
+       else if (!(fgets(servline, 128, servfil)))
+               return (struct servent *) NULL;
+               
+       if (p = strpbrk(servline, "#\n\r"))
+               *p = 0;
+       if (!servline[0])
+               goto retry;
+       
+       if (!(serv.s_name = strtok(servline, " \t")))
+               goto retry;
+               
+       if (!(p = strtok(NULL, " \t")))
+               goto retry;
+       
+       if (!(serv.s_proto = strpbrk(p, "/,")))
+               goto retry;
+               
+       *serv.s_proto++         = 0;
+       serv.s_port             = htons(atoi(p));
+       serv.s_aliases  = servalias;
+       
+       for (aliascount = 0; aliascount < 7; ) 
+               if (!(servalias[aliascount++] = strtok(NULL, " \t")))
+                       break;
+       
+       servalias[aliascount] = NULL;
+       
+       return &serv;
+}
+
+struct servent * getservbyname(const char * name, const char * proto)
+{
+       struct servent *        ent;
+       char **                                 al;
+       setservent(0);
+       
+       while (ent = getservent()) {
+               if (!strcmp(name, ent->s_name))
+                       goto haveName;
+               
+               for (al = ent->s_aliases; *al; ++al)
+                       if (!strcmp(name, *al))
+                               goto haveName;
+               
+               continue;
+haveName:
+               if (!proto || !strcmp(proto, ent->s_proto))
+                       break;
+       }
+       
+       if (!servstay)
+               endservent();
+       
+       return ent;
+}
+
+struct servent * getservbyport(int port, const char * proto)
+{
+       struct servent * ent;
+       
+       setservent(0);
+       
+       while (ent = getservent())
+               if (port == ent->s_port && (!proto || !strcmp(proto, ent->s_proto)))
+                       break;
+       
+       if (!servstay)
+               endservent();
+       
+       return ent;
+}
+
+static char    tcp[] = "tcp";
+static char    udp[] = "udp";
+#define        MAX_PROTOENT                    10
+static         struct protoent         protoents[MAX_PROTOENT];
+static         int                                             protoent_count=0;
+
+struct protoent * getprotobyname(const char * name)
+{
+       struct protoent *pe;
+
+       pe = &protoents[protoent_count];
+       if (strcmp(name, "udp") == 0) {
+               pe->p_name = udp;
+               pe->p_proto = IPPROTO_UDP;
+       } else if (strcmp (name, "tcp") == 0)  {
+               pe->p_name = tcp;
+               pe->p_proto = IPPROTO_TCP;
+       } else {
+               errno = EPROTONOSUPPORT;
+               return NULL;
+       }
+       pe->p_aliases = aliasPtrs;
+       protoent_count = (protoent_count +1) % MAX_PROTOENT;
+       return pe;
+}
+
+struct protoent * getprotobynumber(int proto)
+{
+       struct protoent *pe;
+
+       pe = &protoents[protoent_count];
+       if (proto == IPPROTO_UDP) {
+               pe->p_name = udp;
+               pe->p_proto = IPPROTO_UDP;
+       } else if (proto == IPPROTO_TCP)  {
+               pe->p_name = tcp;
+               pe->p_proto = IPPROTO_TCP;
+       } else {
+               errno = EPROTONOSUPPORT;
+               return NULL;
+       }
+       pe->p_aliases = aliasPtrs;
+       protoent_count = (protoent_count +1) % MAX_PROTOENT;
+       return pe;
+}
+
diff --git a/Mac/GUSI-mods/into-src/GUSISIOUX.cp b/Mac/GUSI-mods/into-src/GUSISIOUX.cp
new file mode 100644 (file)
index 0000000..24b98b0
--- /dev/null
@@ -0,0 +1,246 @@
+/*********************************************************************
+Project        :       GUSI                            -       Grand unified socket interface
+File           :       GUSISIOUX.cp    -       Interface to Metrowerks SIOUX library
+Author :       Matthias Neeracher
+Language       :       MPW C/C++
+
+$Log$
+Revision 1.1  1998/08/18 14:52:38  jack
+Putting Python-specific GUSI modifications under CVS.
+
+*********************************************************************/
+
+#include <GUSIFile_P.h>
+#include <ioctl.h>
+#include <console.h>
+
+#include <Events.h>
+#include <LowMem.h>
+
+/************************ SIOUXSocket members ************************/
+
+/* This declaration lies about the return type */
+extern "C" void SIOUXHandleOneEvent(EventRecord *userevent);
+
+GUSIEvtHandler GUSISIOUXEvents[]       =       {
+       SIOUXHandleOneEvent,            // nullEvent
+       
+       SIOUXHandleOneEvent,            // mouseDown
+       SIOUXHandleOneEvent,            // mouseUp
+       nil,                                                    // keyDown
+       nil,
+       
+       nil,                                                    // autoKey
+       SIOUXHandleOneEvent,            // updateEvt
+       SIOUXHandleOneEvent,            // diskEvt
+       SIOUXHandleOneEvent,            // activateEvt
+       
+       nil,
+       nil,
+       nil,
+       nil,
+       
+       nil,
+       nil,
+       SIOUXHandleOneEvent,            // osEvt
+       nil,
+       
+       nil,
+       nil,
+       nil,
+       nil,
+       
+       nil,
+       nil,
+       nil,
+};
+
+/************************ Declaration of SIOUXSocket ************************/
+
+class SIOUXSocket : public Socket      {               
+       friend class SIOUXSocketDomain; 
+       
+                                       SIOUXSocket();
+                                       
+       virtual                 ~SIOUXSocket();
+protected:
+       int                     initialized;
+       void                    DoInitialize(void);
+public:
+       virtual int     read(void * buffer, int buflen);
+       virtual int write(void * buffer, int buflen);
+       virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception);
+       virtual int     ioctl(unsigned int request, void *argp);
+       virtual int     isatty();
+};     
+
+class SIOUXSocketDomain : public FileSocketDomain {
+       SIOUXSocket *   singleton;
+public:
+       SIOUXSocketDomain()     :       FileSocketDomain(AF_UNSPEC, true, false), singleton(nil)        {       }
+       
+       virtual Boolean Yours(const GUSIFileRef & ref, Request request);
+       virtual Socket * open(const GUSIFileRef & ref, int oflag);
+};
+
+#if GENERATING68K
+#pragma segment SIOUX
+#endif
+
+/************************ SIOUXSocket members ************************/
+
+void SIOUXSocket::DoInitialize()
+{
+       if ( initialized ) return;
+       initialized++;
+       InstallConsole(0);
+       GUSISetEvents(GUSISIOUXEvents);
+}
+
+SIOUXSocket::SIOUXSocket()
+{
+       initialized = 0;
+       if ( !GUSIConfig.DelayConsole() )
+               DoInitialize();
+}
+
+SIOUXSocket::~SIOUXSocket()
+{
+       RemoveConsole();
+}
+
+int SIOUXSocket::ioctl(unsigned int request, void *)
+{
+       if ( !initialized) DoInitialize();
+       switch (request)        {
+       case FIOINTERACTIVE:
+               return 0;
+       default:
+               return GUSI_error(EOPNOTSUPP);
+       }
+}
+
+int SIOUXSocket::read(void * buffer, int buflen)
+{
+       if ( !initialized) DoInitialize();
+       fflush(stdout);
+       
+       return ReadCharsFromConsole((char *) buffer, buflen);
+}
+
+int SIOUXSocket::write(void * buffer, int buflen)
+{
+       if ( !initialized) DoInitialize();
+       return WriteCharsToConsole((char *) buffer, buflen);
+}
+
+static Boolean input_pending()
+{
+       QHdrPtr eventQueue = LMGetEventQueue();
+       EvQElPtr element = (EvQElPtr)eventQueue->qHead;
+       
+       // now, count the number of pending keyDown events.
+       while (element != nil) {
+               if (element->evtQWhat == keyDown || element->evtQWhat == autoKey)
+                       return true;
+               element = (EvQElPtr)element->qLink;
+       }
+       
+       return false;
+}
+
+int SIOUXSocket::select(Boolean * canRead, Boolean * canWrite, Boolean * exception)
+{
+       int             goodies         =       0;
+               
+       if ( !initialized) DoInitialize();
+       fflush(stdout);
+       
+       if (canRead) 
+               if (*canRead = input_pending())
+                       ++goodies;
+       
+       if (canWrite) {
+               *canWrite = true;
+               ++goodies;
+       }
+       
+       if (exception)
+               *exception = false;
+       
+       return goodies;
+}
+
+int SIOUXSocket::isatty()
+{
+       return 1;
+}
+
+/********************* SIOUXSocketDomain members **********************/
+
+#ifdef MSLGUSI
+#ifndef SFIOGUSI
+       extern void GUSISetupMSLSIOUX();
+#endif
+#endif
+
+extern "C" void GUSIwithSIOUXSockets()
+{
+       static SIOUXSocketDomain        SIOUXSockets;
+       SIOUXSockets.DontStrip();
+#ifdef MSLGUSI
+#ifndef SFIOGUSI
+       GUSISetupMSLSIOUX();
+#endif
+#endif
+}
+
+Boolean SIOUXSocketDomain::Yours(const GUSIFileRef & ref, FileSocketDomain::Request request)
+{
+       if (ref.spec || (request != willOpen && request != willStat))
+               return false;
+       
+       switch (ref.name[4] | 0x20) {
+       case 's':
+               if ((ref.name[5] | 0x20) != 't' || (ref.name[6] | 0x20) != 'd')
+                       return false;
+               switch (ref.name[7] | 0x20) {
+               case 'i':
+                       if ((ref.name[8] | 0x20) != 'n' || ref.name[9])
+                               return false;
+                       return true;
+               case 'o':
+                       if ((ref.name[8] | 0x20) != 'u' || (ref.name[9] | 0x20) != 't' || ref.name[10])
+                               return false;
+                       return true;
+               case 'e':
+                       if ((ref.name[8] | 0x20) != 'r' || (ref.name[9] | 0x20) != 'r' || ref.name[10])
+                               return false;
+                       return true;
+               default:
+                       return false;
+               }
+       case 'c':
+               if (    (ref.name[5] | 0x20) != 'o' || (ref.name[6] | 0x20) != 'n'
+                       || (ref.name[7] | 0x20) != 's' || (ref.name[8] | 0x20) != 'o'
+                       || (ref.name[9] | 0x20) != 'l' || (ref.name[10] | 0x20) != 'e')
+                       return false;
+               switch (ref.name[11]) {
+               case 0:
+                       return true;
+               default:
+                       return false;
+               }
+       default:
+               return false;
+       }
+}
+
+Socket * SIOUXSocketDomain::open(const GUSIFileRef &, int)
+{
+       if (!singleton)
+               singleton = new SIOUXSocket();
+       ++*singleton;
+       
+       return singleton;
+}