diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-25 19:28:21 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-25 19:28:21 +0000 |
commit | 3b0d3a905e39624abe9ddd1ce20542097601e4c2 (patch) | |
tree | f5b0ccd0e7ace27a01c8b425d25f3d11f5ea891d | |
parent | 3bd236a07c0ebaabb7337dd5d56bc57a028a9c0e (diff) |
Initial revisionXORG-STABLE
-rw-r--r-- | Xtransos2.c | 887 |
1 files changed, 887 insertions, 0 deletions
diff --git a/Xtransos2.c b/Xtransos2.c new file mode 100644 index 0000000..f61617e --- /dev/null +++ b/Xtransos2.c @@ -0,0 +1,887 @@ +/* $XFree86: xc/lib/xtrans/Xtransos2.c,v 3.10 2003/08/26 15:38:39 tsi Exp $ */ + +/* + * (c) Copyright 1996 by Sebastien Marineau and Holger Veit + * <marineau@genie.uottawa.ca> + * <Holger.Veit@gmd.de> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * HOLGER VEIT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Sebastien Marineau or Holger Veit shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Holger Veit or Sebastien Marineau. + * + */ + +/* Implementation of the OS/2 local pipe transport layer */ + +#define INCL_DOSNMPIPES +#define INCL_DOSPROCESS +#define INCL_DOSERRORS +#define INCL_DOSFILEMGR +#undef BYTE +#undef BOOL +#include <os2.h> + +#ifdef XSERV_t +extern HEV hPipeSem; +BOOL init_server_pipes(); +#endif + +/************************************************************************* + * Independent Layer + *************************************************************************/ +#ifdef TRANS_CLIENT + +static XtransConnInfo +TRANS(Os2OpenClient)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + APIRET rc; + HFILE hfd,hServer; + ULONG action,byteWritten,State; + char pipename[256],clientname[256]; + char server_string[256]; + struct sockaddr *addr_name; + unsigned char pipe_len; + XtransConnInfo ciptr; + static int unique_id=0; + int i,namelen,try; + + PRMSG(2,"Os2OpenClient(%s,%s,%s)\n",protocol,host,port); + + /* test, whether the host is really local, i.e. either + * "os2" or "local" + */ + if (strcmp(protocol,"os2") && strcmp(protocol,"local")) { + PRMSG (1, + "Os2OpenClient: Cannot connect to non-local host %s\n", + host, 0, 0); + return NULL; + } + + /* make the pipename */ + + if (port && *port ) { + if( *port == '/' ) { /* A full pathname */ + (void) sprintf(pipename, "\\PIPE\\X\\%s,", port); + } else { + (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port); + } + } else { + (void) sprintf(pipename, "\\PIPE\\X\\xfree86"); } + + PRMSG(5, "Os2OpenClient: Creating pipe %s\n",pipename, 0,0 ); + + /* make a connection entry */ + if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) { + PRMSG(1,"Os2OpenClient: calloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + /* open the pipe. Try ten times before giving up at 500ms intervals*/ + try = 0; + do { + rc = DosOpen(pipename,&hServer, &action, 0, + FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE, + (PEAOP2)NULL); + if(rc == 0) break; + if (try >=10) { + PRMSG(1,"Os2OpenClient: Open server pipe %s failed, rc=%d\n", + pipename,rc,0 ); + PRMSG(1,"\tProbable causes: either the XServer is not running, or has not started properly,\n", + 0,0,0 ); + PRMSG(1,"\tor the DISPLAY variable is set incorrectly.\n", + 0,0,0 ); + xfree(ciptr); + return NULL; + } + try ++; + DosSleep(500); + } while (rc != 0); + +/* OK, now we are talking to the server. Generate a unique pipe name and pass it to + * the server. Make the pipe and wait for server to connect */ + + sprintf(clientname,"\\PIPE\\X\\%d.%d",getpid(),unique_id++); + + rc = DosCreateNPipe (clientname, &hfd, + NP_NOINHERIT | NP_ACCESS_DUPLEX, + 1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE, + 16384, 16384, 0); + if (rc != 0){ + PRMSG(1, "Os2OpenClient: Unable to create pipe %s\n", pipename,0,0 ); + DosClose(hfd); + pipe_len=0; + DosWrite(hServer,&pipe_len,1,&byteWritten); + DosClose(hServer); + xfree(ciptr); + return(NULL); + } + + /* Connect to the pipe. */ + + rc = DosConnectNPipe (hfd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2OpenClient: Unable to connect to pipe %s\n", pipename,0,0 ); + DosClose (hfd); + DosClose(hServer); + xfree(ciptr); + return (NULL); + } + +/* Now write name to server on hServer */ + server_string[0]=(char) strlen(clientname)+1; + strcpy(&server_string[1],clientname); + rc = DosWrite(hServer,server_string,(ULONG)server_string[0]+1,&byteWritten); + if(rc != 0){ /* Could not write to server pipe? */ + PRMSG(1, "Os2OpenClient: Error writing to server pipe, handle=%d, rc=%d, w=%d\n", + hServer,rc,byteWritten ); + DosClose(hServer); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + + PRMSG (5, "Os2OpenCLient: Wrote pipename %s to server; len %d written %d \n", + &server_string[1],server_string[0]+1,byteWritten); + + +/* The server will respond by opening the pipe. Wait for that for 30 secs */ + + i=0; + DosSleep(50); /* Give it time to catch up but minimize race condition*/ + rc = DosConnectNPipe(hfd); + while((rc == ERROR_PIPE_NOT_CONNECTED)&&(i++<60)) { + DosSleep(500); + rc = DosConnectNPipe(hfd); + } + + if(rc != 0){ /* Server has not responded! */ + PRMSG(1, "Os2OpenClient: Timeout on wait for server response, handle=%d, rc=%d\n",hServer,rc,0 ); + PRMSG(1, "\tProbable cause: the XServer has exited or crashed while the connection was being established\n",0,0,0 ); + PRMSG(1, "\tor the XServer is too busy to respond.\n",0,0,0 ); + DosClose(hServer); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + +/* OK, the server has connected! Fill-in the info and return */ + + DosClose(hServer); + +/* Last check: make sure client is connected! */ + + rc = DosQueryNPHState(hfd,&State); + if(rc != 0){ /* Client is not connected! */ + PRMSG(1, "Os2OpenClient: Client pipe does not appear connected. rc=%d, h=%d\n",rc,hfd,0 ); + PRMSG(1, "\tProbable cause: the XServer has just exited.\n",0,0,0 ); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + + namelen=sizeof(struct sockaddr); + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenClient: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + ciptr->addrlen = namelen; + ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX; + strcpy(((struct sockaddr *)ciptr->addr)->sa_data, "local"); + + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenCLient: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr); + return(NULL); + } + ciptr->peeraddrlen = namelen; + ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)ciptr->peeraddr)->sa_data,"local"); + + PRMSG (5, "Os2OpenCLient: Filled in struct: len %d %d name %s\n", + ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data); + + + ciptr->index=hfd; + ciptr->family=AF_UNIX; + if((ciptr->fd=_imphandle(hfd))<0){ + PRMSG(1, "Os2OpenClient: Could not import the pipe handle into EMX\n",0,0,0 ); + PRMSG(1, "\tProbable cause: EMX has run out of free file handles.\n",0,0,0 ); + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr->peeraddr); + xfree(ciptr); + return(NULL); + } + PRMSG(5, "Os2OpenClient: pipe handle %d EMX handle %d\n",ciptr->index,ciptr->fd,0 ); + fcntl(ciptr->fd,F_SETFL,O_NDELAY); + fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC); + return ciptr; +} +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER +static XtransConnInfo +TRANS(Os2OpenServer)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + APIRET rc; + HFILE hfd; + ULONG action; + char pipename[256]; + struct sockaddr *addr_name; + XtransConnInfo ciptr; + int namelen; + +#ifdef XSERV_t + if (! init_server_pipes()) return(NULL); +#endif + + PRMSG(2,"Os2OpenServer(%s,%s,%s)\n",protocol,host,port); + + if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"Os2OpenServer: xcalloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + + if (port && *port ) { + if( *port == '/' ) { /* A full pathname */ + (void) sprintf(pipename, "\\PIPE\\X\\%s", port); + } else { + (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port); + } + } else { + (void) sprintf(pipename, "\\PIPE\\X\\xfree86"); + } + + PRMSG(5, "Os2OpenServer: Creating pipe %s\n",pipename, 0,0 ); + + rc = DosCreateNPipe (pipename, &hfd, + NP_NOINHERIT | NP_ACCESS_INBOUND, + 1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE, + 0, 8192, 0); + if (rc != 0){ + PRMSG(1, "Os2OpenServer: Unable to create pipe %s, rc=%d\n", pipename,rc,0 ); + PRMSG(1, "\tProbable cause: there is already another XServer running on display :%s\n",port,0,0 ); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + + /* Connect to the pipe. */ + + rc = DosConnectNPipe (hfd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2OpenServer: Unable to connect to pipe %s\n", pipename,0,0 ); + DosClose (hfd); + xfree(ciptr); + return (NULL); + } + +/* Pipe is now connected and waiting for client connect */ + +/*** Put in info ***/ + + namelen=sizeof(struct sockaddr); + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + ciptr->addrlen = namelen; + ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)ciptr->addr)->sa_data, "local"); + + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr); + return(NULL); + } + + ciptr->peeraddrlen = namelen; + ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX; + strcpy(((struct sockaddr *)ciptr->peeraddr)->sa_data,"local"); + + PRMSG (5, "Os2OpenServer: Filled in struct: len %d %d name %s\n", + ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data); + + ciptr->index=hfd; /* Save this for later use in this unused member of struct */ + ciptr->flags=1; /* Listener */ + ciptr->family=AF_UNIX; + + if((ciptr->fd=_imphandle(hfd))<0){ + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr->peeraddr); + xfree(ciptr); + return(NULL); + } + PRMSG(5, "Os2OpenServer: Pipe handle %d EMX handle %d",ciptr->index,ciptr->fd,0 ); + +#ifdef XSERV_t +/* Attach the pipe sem to the pipe. Use handle index as key */ + rc = DosSetNPipeSem(ciptr->fd, (HSEM)hPipeSem, ciptr->fd); + if (rc){ + PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n", + hPipeSem,ciptr->fd,rc); + DosClose(ciptr->fd); + xfree(ciptr->addr); + xfree(ciptr->peeraddr); + xfree(ciptr); + return(NULL); + } +#endif + + fcntl(ciptr->fd,F_SETFL,O_NDELAY); + fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC); + return(ciptr); +} +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT +static XtransConnInfo +TRANS(Os2OpenCLTSClient)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCLTSClient(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenClient)(thistrans, protocol, host, port); +} +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_CLIENT +static XtransConnInfo +TRANS(Os2OpenCOTSClient)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCOTSClient(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenClient)(thistrans, protocol, host, port); +} +#endif /* TRANS_CLIENT */ + + +#ifdef TRANS_SERVER +static XtransConnInfo +TRANS(Os2OpenCLTSServer)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCLTSServer(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenServer)(thistrans, protocol, host, port); +} +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_SERVER +static XtransConnInfo +TRANS(Os2OpenCOTSServer)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCOTSServer(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenServer)(thistrans, protocol, host, port); +} +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN +static XtransConnInfo +TRANS(Os2ReopenCOTSServer)(Xtransport *thistrans, int fd, char *port) +{ + + XtransConnInfo ciptr; + char addr_name[256]; + int namelen; + + PRMSG(2,"Os2ReopenCOTSServer(%d,%s)\n", fd, port, 0); + + if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"Os2ReopenCOTSServer: xcalloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + strcpy(addr_name,"local"); + namelen=sizeof(addr_name); + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n", + 0, 0, 0); + xfree(ciptr); + return(NULL); + } + + ciptr->addrlen = namelen; + memcpy (ciptr->addr, addr_name, ciptr->addrlen); + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n", + 0, 0, 0); + xfree(ciptr); + return(NULL); + } + + ciptr->peeraddrlen = namelen; + memcpy (ciptr->peeraddr,addr_name, ciptr->addrlen); + + ciptr->fd = fd; + ciptr->family=AF_UNIX; + ciptr->flags=1; + PRMSG(1,"Os2ReopenCOTSServer: Filled-in info for handle %d on port %s.\n", fd, port, 0); + + return(ciptr); +} + +static XtransConnInfo +TRANS(Os2ReopenCLTSServer)(Xtransport *thistrans, int fd, char *port) +{ + PRMSG(2,"Os2ReopenCLTSServer(%d,%s)\n", fd, port, 0); + return TRANS(Os2ReopenCOTSServer)(thistrans, fd, port); +} +#endif + +static +TRANS(Os2SetOption)(XtransConnInfo ciptr, int option, int arg) +{ + PRMSG(2,"Os2SetOption(%d,%d,%d)\n",ciptr->fd,option,arg); + return -1; +} + +#ifdef TRANS_SERVER + +static +TRANS(Os2CreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags) +{ + PRMSG(2,"Os2CreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port); + return 0; +} + +static XtransConnInfo +TRANS(Os2Accept)(XtransConnInfo ciptr, int *status) +{ + XtransConnInfo newciptr; + HFILE hClient; + unsigned char length; + ULONG action; + char clientname[256]; + struct sockaddr *addr_name; + int in,namelen; + APIRET rc; + + + PRMSG(2,"Os2Accept(%x->%d)\n", ciptr, ciptr->fd,0); + if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL ) + { + PRMSG(1,"Os2Accept: xcalloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + +/* Read in length of client pipe name. If fails, then reset server pipe */ + if((in=read(ciptr->fd,&length,1))<=0){ + PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n", + in,errno,0 ); + *status = TRANS_ACCEPT_MISC_ERROR; + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + PRMSG(5, "Os2Accept: Bytes to read for name: %d\n",length,0,0 ); + + +/* Check length for valid length ?? */ + +/* Now read in length bytes from pipe for client pipe name */ + if((in=read(ciptr->fd,clientname,length))<=0){ + PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n", + in,errno,0 ); + *status = TRANS_ACCEPT_MISC_ERROR; + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + clientname[length]='\0'; + PRMSG(5, "Os2Accept: Server name %s length %d\n",clientname,length,0 ); + + +/* Now we have the client pipe name. Open it with DosOpen */ + + rc = DosOpen(clientname,&hClient, &action, 0, + FILE_NORMAL, FILE_OPEN, + OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, + (PEAOP2)NULL); + + PRMSG(5, "Os2Accept: Open pipe %s, handle = %d, rc=%d\n",clientname,hClient,rc ); + + if (rc) { + PRMSG(1,"Os2Accept: Open pipe %s to client failed, rc=%d\n", + clientname,rc,0 ); + PRMSG(1, "\tProbable cause: the client has exited or timed-out.\n",0,0,0 ); + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + + rc = DosSetNPHState (hClient, NP_NOWAIT | NP_READMODE_BYTE); + if (rc != 0) + { + PRMSG(1,"Os2Accept: Could not set pipe %s to non-blocking mode, rc=%d\n", + hClient,rc,0 ); + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + +/* OK, we seem to be well connected to client. Now disconnect server pipe and put again in listen */ + + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + PRMSG(5, "Os2Accept: Reconnecting server pipe %d, rc = %d\n",ciptr->fd,rc,0 ); + + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } /* Consider this non-fatal for present connection */ + +/* And finally fill-in info in newciptr */ + + namelen=sizeof(struct sockaddr); + if ((newciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2Accept: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hClient); + xfree(newciptr); + return(NULL); + } + + newciptr->addrlen = namelen; + ((struct sockaddr *)newciptr->addr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)newciptr->addr)->sa_data, "local"); + + if ((newciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2Accept: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hClient); + xfree(ciptr->addr); + xfree(newciptr); + return(NULL); + } + + newciptr->peeraddrlen = namelen; + ((struct sockaddr *)newciptr->peeraddr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)newciptr->peeraddr)->sa_data, "local"); + + PRMSG (5, "Os2Accept: Filled in struct: len %d %d name %s\n", + newciptr->addrlen,newciptr->peeraddrlen,newciptr->peeraddr); + + + newciptr->index=hClient; + newciptr->family=AF_UNIX; + if((newciptr->fd=_imphandle(hClient))<0){ + PRMSG(1,"Os2Accept: Could not import pipe %d into EMX, errno=%d\n", + hClient,errno,0 ); + PRMSG(1, "\tProbable cause: EMX has run out of file handles.\n",0,0,0 ); + DosClose(hClient); + xfree(newciptr->addr); + xfree(newciptr->peeraddr); + xfree(newciptr); + return(NULL); + } + PRMSG(5, "Os2Accept: Pipe handle %d EMX handle %d",newciptr->index,newciptr->fd,0 ); + +#ifdef XSERV_t +/* Attach the pipe sem to the pipe. Use handle index as key */ + rc = DosSetNPipeSem(newciptr->fd, (HSEM)hPipeSem, newciptr->fd); + if (rc){ + PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n", + hPipeSem,newciptr->fd,rc); + DosClose(newciptr->fd); + xfree(newciptr->addr); + xfree(newciptr->peeraddr); + xfree(newciptr); + return(NULL); + } +#endif + + fcntl(ciptr->fd,F_SETFL,O_NDELAY); + fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC); + *status=0; + return newciptr; +} + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + +static +TRANS(Os2Connect)(XtransConnInfo ciptr, char *host, char *port) +{ + PRMSG(2,"Os2Connect(%x->%d,%s)\n", ciptr, ciptr->fd, port); + return 0; +} + +#endif /* TRANS_CLIENT */ + +static int +TRANS(Os2BytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend ) +{ + ULONG rc, state, nread; + AVAILDATA avail; + char buffer; + + PRMSG(2,"Os2BytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend); + + rc = DosPeekNPipe (ciptr->fd, &buffer, 0, &nread, &avail, &state); + if (rc != 0) + { + errno = EPIPE; + *pend = 0; + return -1; + } + if (state == NP_STATE_CLOSING) + { + errno = EPIPE; + *pend = 0; + return -1; + } + errno = 0; + *pend = avail.cbpipe; + return 0; +} + +static int +TRANS(Os2Read)(XtransConnInfo ciptr, char *buf, int size) +{ + int ret; + APIRET rc; + ULONG ulRead; + PRMSG(2,"Os2Read(%d,%x,%d)\n", ciptr->fd, buf, size ); + errno = 0; + rc = DosRead(ciptr->fd, buf, size, &ulRead); + if (rc == 0){ + ret = ulRead; + } + else if ((rc == 232) || (rc == 231)){ + errno = EAGAIN; + ret = -1; + } + else if (rc == 6){ + errno = EBADF; + ret = -1; + } + else if ((rc == 109) || (rc == 230) || (rc == 233)){ + errno = EPIPE; + ret = -1; + } + else { + PRMSG(2,"Os2Read: Unknown return code from DosRead, fd %d rc=%d\n", ciptr->fd,rc,0 ); + errno = EINVAL; + ret = -1; + } + return (ret); +} + +static int +TRANS(Os2Write)(XtransConnInfo ciptr, char *buf, int size) +{ + int ret; + APIRET rc; + ULONG nWritten; + PRMSG(2,"Os2Write(%d,%x,%d)\n", ciptr->fd, buf, size ); + rc = DosWrite(ciptr->fd, buf, size, &nWritten); + if (rc == 0){ + ret = nWritten; + if(nWritten == 0) { + errno=EAGAIN; + ret = -1; + } + } + else if ((rc == 39) || (rc == 112)){ + errno = EAGAIN; + ret = -1; + } + else if ((rc == 109) || (rc == 230) || (rc == 233)){ + errno = EPIPE; + ret = -1; + } + else if (rc == 6){ + errno=EBADF; + ret = -1; + } + else { + PRMSG(2,"(Os2Write)Unknown return code from DosWrite, fd %d rc=%d\n", ciptr->fd,rc,0 ); + errno = EINVAL; + ret = -1; + } + return (ret); +} + +static int +TRANS(Os2Readv)(XtransConnInfo ciptr, struct iovec *buf, int size) +{ + int ret; + PRMSG(2,"Os2Readv(%d,%x,%d)\n", ciptr->fd, buf, size ); + ret = READV(ciptr,buf,size); + if ((ret <0) && (errno == EINVAL)) errno = EPIPE; + return (ret); +} + +static int +TRANS(Os2Writev)(XtransConnInfo ciptr, struct iovec *buf, int size) +{ + int ret; + PRMSG(2,"Os2Writev(%d,%x,%d)\n", ciptr->fd, buf, size ); + ret = WRITEV(ciptr,buf,size); + if ((ret <0) && (errno == EINVAL)) errno = EPIPE; + if ((ret <0) && (errno == ENOSPC)) errno = EAGAIN; + return (ret); +} + +static int +TRANS(Os2Disconnect)(XtransConnInfo ciptr) +{ + PRMSG(2,"Os2Disconnect(%x->%d)\n", ciptr, ciptr->fd, 0); + return 0; +} + +static int +TRANS(Os2Close)(XtransConnInfo ciptr) +{ + int ret; + PRMSG(2,"Os2Close(%x->%d)\n", ciptr, ciptr->fd ,0); + ret=close(ciptr->fd); + return ret; +} + +static int +TRANS(Os2CloseForCloning)(XtransConnInfo ciptr) +{ + int ret; + + PRMSG(2,"Os2CloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0); + ret=close(ciptr->fd); + return ret; +} + + +Xtransport TRANS(OS2LocalFuncs) = { + /* Local Interface */ + "local", + TRANS_LOCAL, +#ifdef TRANS_CLIENT + TRANS(Os2OpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + NULL, + TRANS(Os2OpenCOTSServer), +#endif /* TRANS_SERVER */ +#ifdef TRANS_CLIENT + TRANS(Os2OpenCLTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + TRANS(Os2OpenCLTSServer), +#endif /* TRANS_SERVER */ +#ifdef TRANS_REOPEN + TRANS(Os2ReopenCOTSServer), + TRANS(Os2ReopenCLTSServer), +#endif + TRANS(Os2SetOption), +#ifdef TRANS_SERVER + TRANS(Os2CreateListener), + NULL, /* ResetListener */ + TRANS(Os2Accept), +#endif /* TRANS_SERVER */ +#ifdef TRANS_CLIENT + TRANS(Os2Connect), +#endif /* TRANS_CLIENT */ + TRANS(Os2BytesReadable), + TRANS(Os2Read), + TRANS(Os2Write), + TRANS(Os2Readv), + TRANS(Os2Writev), + TRANS(Os2Disconnect), + TRANS(Os2Close), + TRANS(Os2CloseForCloning), +}; + +#ifdef XSERV_t +/* This function is used in the server to initialize the semaphore used with pipes */ + +BOOL init_server_pipes() +{ + static BOOL first_time=TRUE; + ULONG rc; + + if(first_time){ + rc = DosCreateEventSem(NULL, &hPipeSem,DC_SEM_SHARED,FALSE); + if (rc){ + PRMSG(1,"Os2OpenListener (init_server_pipes): Could not create pipe semaphore, rc=%d\n", + rc,0,0); + return(FALSE); + } + first_time=FALSE; + } +return(TRUE); +} +#endif /* XSERV_t */ |