summaryrefslogtreecommitdiffstats
path: root/Mac
diff options
context:
space:
mode:
authorJack Jansen <jack.jansen@cwi.nl>1998-08-18 14:52:38 (GMT)
committerJack Jansen <jack.jansen@cwi.nl>1998-08-18 14:52:38 (GMT)
commit1d6a6ea1a819a645a3a8841205b10cf33eb04493 (patch)
tree464997cdd49781964e5928be1a5d99311b24c3ec /Mac
parentb0195ec9c136300bcd65d89bfdf287a98af6c7de (diff)
downloadcpython-1d6a6ea1a819a645a3a8841205b10cf33eb04493.zip
cpython-1d6a6ea1a819a645a3a8841205b10cf33eb04493.tar.gz
cpython-1d6a6ea1a819a645a3a8841205b10cf33eb04493.tar.bz2
Putting Python-specific GUSI modifications under CVS.
Diffstat (limited to 'Mac')
-rw-r--r--Mac/GUSI-mods/into-include/GUSI.h366
-rw-r--r--Mac/GUSI-mods/into-include/GUSI_P.h471
-rw-r--r--Mac/GUSI-mods/into-src/GUSI.r168
-rw-r--r--Mac/GUSI-mods/into-src/GUSIDispatch.cp1434
-rw-r--r--Mac/GUSI-mods/into-src/GUSINetDB.cp579
-rw-r--r--Mac/GUSI-mods/into-src/GUSISIOUX.cp246
6 files changed, 3264 insertions, 0 deletions
diff --git a/Mac/GUSI-mods/into-include/GUSI.h b/Mac/GUSI-mods/into-include/GUSI.h
new file mode 100644
index 0000000..07ce429
--- /dev/null
+++ b/Mac/GUSI-mods/into-include/GUSI.h
@@ -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
index 0000000..1bc5523
--- /dev/null
+++ b/Mac/GUSI-mods/into-include/GUSI_P.h
@@ -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
index 0000000..6da7fd6
--- /dev/null
+++ b/Mac/GUSI-mods/into-src/GUSI.r
@@ -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…I', 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…I' {
+ 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…I") {
+ {
+ "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
index 0000000..86941cb
--- /dev/null
+++ b/Mac/GUSI-mods/into-src/GUSIDispatch.cp
@@ -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…I', 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
index 0000000..bc435b6
--- /dev/null
+++ b/Mac/GUSI-mods/into-src/GUSINetDB.cp
@@ -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
index 0000000..24b98b0
--- /dev/null
+++ b/Mac/GUSI-mods/into-src/GUSISIOUX.cp
@@ -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;
+}