]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/xtrans/Xtransos2.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / xtrans / Xtransos2.c
1 /* $XFree86: xc/lib/xtrans/Xtransos2.c,v 3.5 1997/01/28 10:53:32 dawes Exp $ */
2
3 /*
4  * (c) Copyright 1996 by Sebastien Marineau and Holger Veit
5  *                      <marineau@genie.uottawa.ca>
6  *                      <Holger.Veit@gmd.de>
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a 
9  * copy of this software and associated documentation files (the "Software"), 
10  * to deal in the Software without restriction, including without limitation 
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
12  * and/or sell copies of the Software, and to permit persons to whom the 
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
21  * HOLGER VEIT  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
23  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
24  * SOFTWARE.
25  * 
26  * Except as contained in this notice, the name of Sebastien Marineau or Holger Veit shall not be
27  * used in advertising or otherwise to promote the sale, use or other dealings
28  * in this Software without prior written authorization from Holger Veit or Sebastien Marineau.
29  *
30  */
31
32 /* Implementation of the OS/2 local pipe transport layer */
33
34 #define INCL_DOSNMPIPES
35 #define INCL_DOSPROCESS
36 #define INCL_DOSERRORS
37 #define INCL_DOSFILEMGR
38 #undef BYTE
39 #undef BOOL
40 #include <os2.h>
41
42 #ifdef XSERV_t
43 extern HEV hPipeSem;
44 BOOL init_server_pipes();
45 #endif
46
47 /*************************************************************************
48  * Independent Layer
49  *************************************************************************/
50 #ifdef TRANS_CLIENT
51
52 static XtransConnInfo
53 TRANS(Os2OpenClient)(thistrans, protocol, host, port)
54 Xtransport *thistrans;
55 char *protocol;
56 char *host;
57 char *port;
58 {
59         APIRET rc;
60         HFILE hfd,hServer;
61         ULONG action,byteWritten,State;
62         char pipename[256],clientname[256];
63         char server_string[256];
64         struct sockaddr *addr_name;
65         unsigned char pipe_len;
66         XtransConnInfo ciptr;
67         static int unique_id=0;
68         int i,namelen,try;
69
70         PRMSG(2,"Os2OpenClient(%s,%s,%s)\n",protocol,host,port);
71
72         /* test, whether the host is really local, i.e. either
73          * "os2" or "local"
74          */
75         if (strcmp(protocol,"os2") && strcmp(protocol,"local")) {
76                 PRMSG (1,
77                         "Os2OpenClient: Cannot connect to non-local host %s\n",
78                         host, 0, 0);
79                 return NULL;
80         }
81
82    /* make the pipename */
83
84     if (port && *port ) {
85         if( *port == '/' ) { /* A full pathname */
86                 (void) sprintf(pipename, "\\PIPE\\X\\%s,", port);
87             } else {
88                 (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port);
89             }
90     } else {
91         (void) sprintf(pipename, "\\PIPE\\X\\xfree86"); }
92
93     PRMSG(5, "Os2OpenClient: Creating pipe %s\n",pipename, 0,0 );
94
95         /* make a connection entry */   
96         if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) {
97                 PRMSG(1,"Os2OpenClient: calloc(1,%d) failed\n",
98                         sizeof(struct _XtransConnInfo),0,0 );
99                 return NULL;
100         }
101
102         /* open the pipe. Try ten times before giving up at 500ms intervals*/
103     try = 0;
104     do {
105         rc = DosOpen(pipename,&hServer, &action, 0,
106                 FILE_NORMAL, FILE_OPEN,
107                 OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE,
108                 (PEAOP2)NULL);
109         if(rc == 0) break;
110         if (try >=10) {
111                 PRMSG(1,"Os2OpenClient: Open server pipe %s failed, rc=%d\n",
112                         pipename,rc,0 );
113                 PRMSG(1,"\tProbable causes: either the XServer is not running, or has not started properly,\n",
114                         0,0,0 );
115                 PRMSG(1,"\tor the DISPLAY variable is set incorrectly.\n",
116                         0,0,0 );
117                 xfree(ciptr);
118                 return NULL;
119             }
120        try ++;
121        DosSleep(500);
122        } while (rc != 0);
123
124 /* OK, now we are talking to the server. Generate a unique pipe name and pass it to
125  * the server. Make the pipe and wait for server to connect */
126
127    sprintf(clientname,"\\PIPE\\X\\%d.%d",getpid(),unique_id++);
128  
129    rc = DosCreateNPipe (clientname, &hfd,
130                        NP_NOINHERIT | NP_ACCESS_DUPLEX,
131                        1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE,
132                        16384, 16384, 0);
133    if (rc != 0){
134         PRMSG(1, "Os2OpenClient: Unable to create pipe %s\n", pipename,0,0 );
135         DosClose(hfd);
136         pipe_len=0;
137         DosWrite(hServer,&pipe_len,1,&byteWritten);
138         DosClose(hServer);
139         xfree(ciptr);
140         return(NULL);
141     }
142
143  /* Connect to the pipe. */
144
145   rc = DosConnectNPipe (hfd);
146   if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
147     {
148         PRMSG(1, "Os2OpenClient: Unable to connect to pipe %s\n", pipename,0,0 );
149         DosClose (hfd);
150         DosClose(hServer);
151         xfree(ciptr);
152         return (NULL);
153     }
154
155 /* Now write name to server on hServer */
156         server_string[0]=(char) strlen(clientname)+1;
157         strcpy(&server_string[1],clientname);
158         rc = DosWrite(hServer,server_string,(ULONG)server_string[0]+1,&byteWritten);
159         if(rc != 0){  /* Could not write to server pipe? */
160            PRMSG(1, "Os2OpenClient: Error writing to server pipe, handle=%d, rc=%d, w=%d\n",
161                 hServer,rc,byteWritten );
162            DosClose(hServer);
163            DosClose(hfd);
164            xfree(ciptr);
165            return(NULL);
166            }
167
168       PRMSG (5, "Os2OpenCLient: Wrote pipename %s to server; len %d written %d \n",
169         &server_string[1],server_string[0]+1,byteWritten);
170
171
172 /* The server will respond by opening the pipe. Wait for that for 30 secs */
173
174         i=0;
175         DosSleep(50);  /* Give it time to catch up but minimize race condition*/
176         rc = DosConnectNPipe(hfd);
177         while((rc == ERROR_PIPE_NOT_CONNECTED)&&(i++<60)) {
178                 DosSleep(500);
179                 rc = DosConnectNPipe(hfd);
180                 }
181
182         if(rc != 0){  /* Server has not responded! */
183            PRMSG(1, "Os2OpenClient: Timeout on wait for server response, handle=%d, rc=%d\n",hServer,rc,0 );
184            PRMSG(1, "\tProbable cause: the XServer has exited or crashed while the connection was being established\n",0,0,0 );
185            PRMSG(1, "\tor the XServer is too busy to respond.\n",0,0,0 );
186            DosClose(hServer);
187            DosClose(hfd);
188            xfree(ciptr);
189            return(NULL);
190            }
191
192 /* OK, the server has connected! Fill-in the info and return */
193
194         DosClose(hServer);
195
196 /* Last check: make sure client is connected! */
197
198         rc = DosQueryNPHState(hfd,&State);
199         if(rc != 0){  /* Client is not connected! */
200            PRMSG(1, "Os2OpenClient: Client pipe does not appear connected. rc=%d, h=%d\n",rc,hfd,0 );
201            PRMSG(1, "\tProbable cause: the XServer has just exited.\n",0,0,0 );
202            DosClose(hfd);
203            xfree(ciptr);
204            return(NULL);
205            }
206
207         namelen=sizeof(struct sockaddr);
208         if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
209           {
210                 PRMSG (1, "Os2OpenClient: Can't allocate space for the addr\n",
211                 0, 0, 0);
212                 DosClose(hfd);
213                 xfree(ciptr);
214                 return(NULL);
215            }
216         ciptr->addrlen = namelen;
217         ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX;
218         strcpy(((struct sockaddr *)ciptr->addr)->sa_data, "local");
219
220         if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
221           {
222                 PRMSG (1, "Os2OpenCLient: Can't allocate space for the addr\n",
223                 0, 0, 0);
224                 DosClose(hfd);
225                 xfree(ciptr->addr);
226                 xfree(ciptr);
227                 return(NULL);
228            }
229        ciptr->peeraddrlen = namelen;
230        ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX;
231        strcpy (((struct sockaddr *)ciptr->peeraddr)->sa_data,"local");
232
233        PRMSG (5, "Os2OpenCLient: Filled in struct: len %d %d name %s\n",
234                 ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data);
235
236
237         ciptr->index=hfd;
238         ciptr->family=AF_UNIX;
239         if((ciptr->fd=_imphandle(hfd))<0){
240            PRMSG(1, "Os2OpenClient: Could not import the pipe handle into EMX\n",0,0,0 );
241            PRMSG(1, "\tProbable cause: EMX has run out of free file handles.\n",0,0,0 );
242            DosClose(hfd);
243            xfree(ciptr->addr);
244            xfree(ciptr->peeraddr);
245            xfree(ciptr);
246            return(NULL);
247            }
248     PRMSG(5, "Os2OpenClient: pipe handle %d EMX handle %d\n",ciptr->index,ciptr->fd,0 );
249         fcntl(ciptr->fd,F_SETFL,O_NDELAY);
250         fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC);
251         return ciptr;
252 }
253 #endif /* TRANS_CLIENT */
254
255 #ifdef TRANS_SERVER
256 static XtransConnInfo
257 TRANS(Os2OpenServer)(thistrans, protocol, host, port)
258 Xtransport *thistrans;
259 char *protocol;
260 char *host;
261 char *port;
262 {
263    APIRET rc;
264    HFILE hfd;
265    ULONG action;
266    char pipename[256];
267    struct sockaddr *addr_name;
268    XtransConnInfo ciptr;
269    int namelen;
270
271 #ifdef XSERV_t
272     if (! init_server_pipes()) return(NULL);
273 #endif
274
275     PRMSG(2,"Os2OpenServer(%s,%s,%s)\n",protocol,host,port);
276
277    if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
278     {
279         PRMSG(1,"Os2OpenServer: xcalloc(1,%d) failed\n",
280               sizeof(struct _XtransConnInfo),0,0 );
281         return NULL;
282     }
283
284
285     if (port && *port ) {
286         if( *port == '/' ) { /* A full pathname */
287                 (void) sprintf(pipename, "\\PIPE\\X\\%s", port);
288             } else {
289                 (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port);
290             }
291     } else {
292         (void) sprintf(pipename, "\\PIPE\\X\\xfree86");
293     }
294
295     PRMSG(5, "Os2OpenServer: Creating pipe %s\n",pipename, 0,0 );
296
297    rc = DosCreateNPipe (pipename, &hfd,
298                        NP_NOINHERIT | NP_ACCESS_INBOUND,
299                        1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE,
300                        0, 8192, 0);
301    if (rc != 0){
302         PRMSG(1, "Os2OpenServer: Unable to create pipe %s, rc=%d\n", pipename,rc,0 );
303         PRMSG(1, "\tProbable cause: there is already another XServer running on display :%s\n",port,0,0 );
304         DosClose(hfd);
305         xfree(ciptr);
306         return(NULL);
307     }
308
309  /* Connect to the pipe. */
310
311   rc = DosConnectNPipe (hfd);
312   if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
313     {
314         PRMSG(1, "Os2OpenServer: Unable to connect to pipe %s\n", pipename,0,0 );
315         DosClose (hfd);
316         xfree(ciptr);
317         return (NULL);
318     }
319
320 /* Pipe is now connected and waiting for client connect */
321
322 /*** Put in info ***/
323
324         namelen=sizeof(struct sockaddr);
325         if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
326           {
327                 PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n",
328                 0, 0, 0);
329                 DosClose(hfd);
330                 xfree(ciptr);
331                 return(NULL);
332            }
333         ciptr->addrlen = namelen;
334         ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX;
335         strcpy (((struct sockaddr *)ciptr->addr)->sa_data, "local");
336
337         if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
338           {
339                 PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n",
340                 0, 0, 0);
341                 DosClose(hfd);
342                 xfree(ciptr->addr);
343                 xfree(ciptr);
344                 return(NULL);
345            }
346
347        ciptr->peeraddrlen = namelen;
348        ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX;
349        strcpy(((struct sockaddr *)ciptr->peeraddr)->sa_data,"local");
350      
351       PRMSG (5, "Os2OpenServer: Filled in struct: len %d %d name %s\n",
352                 ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data);
353
354     ciptr->index=hfd; /* Save this for later use in this unused member of struct */
355     ciptr->flags=1;     /* Listener */
356     ciptr->family=AF_UNIX;
357
358     if((ciptr->fd=_imphandle(hfd))<0){
359        DosClose(hfd);
360        xfree(ciptr->addr);
361        xfree(ciptr->peeraddr);
362        xfree(ciptr);
363        return(NULL);
364        }
365     PRMSG(5, "Os2OpenServer: Pipe handle %d EMX handle %d",ciptr->index,ciptr->fd,0 );
366
367 #ifdef XSERV_t
368 /* Attach the pipe sem to the pipe. Use handle index as key */
369     rc = DosSetNPipeSem(ciptr->fd, (HSEM)hPipeSem, ciptr->fd);
370     if (rc){
371         PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n",
372                  hPipeSem,ciptr->fd,rc);
373         DosClose(ciptr->fd);
374         xfree(ciptr->addr);
375         xfree(ciptr->peeraddr);
376         xfree(ciptr);
377          return(NULL);
378         }
379 #endif
380
381     fcntl(ciptr->fd,F_SETFL,O_NDELAY);
382     fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC);
383     return(ciptr);
384 }
385 #endif /* TRANS_SERVER */
386
387 #ifdef TRANS_CLIENT
388 static XtransConnInfo
389 TRANS(Os2OpenCLTSClient)(thistrans, protocol, host, port)
390 Xtransport *thistrans;
391 char *protocol;
392 char *host;
393 char *port;
394 {
395         PRMSG(2,"Os2OpenCLTSClient(%s,%s,%s)\n",protocol,host,port);
396         return TRANS(Os2OpenClient)(thistrans, protocol, host, port);
397 }
398 #endif /* TRANS_CLIENT */
399
400 #ifdef TRANS_CLIENT
401 static XtransConnInfo
402 TRANS(Os2OpenCOTSClient)(thistrans, protocol, host, port)
403 Xtransport *thistrans;
404 char *protocol;
405 char *host;
406 char *port;
407 {
408         PRMSG(2,"Os2OpenCOTSClient(%s,%s,%s)\n",protocol,host,port);
409         return TRANS(Os2OpenClient)(thistrans, protocol, host, port);
410 }
411 #endif /* TRANS_CLIENT */
412
413
414 #ifdef TRANS_SERVER
415 static XtransConnInfo
416 TRANS(Os2OpenCLTSServer)(thistrans, protocol, host, port)
417 Xtransport *thistrans;
418 char *protocol;
419 char *host;
420 char *port;
421 {
422         PRMSG(2,"Os2OpenCLTSServer(%s,%s,%s)\n",protocol,host,port);
423         return TRANS(Os2OpenServer)(thistrans, protocol, host, port);
424 }
425 #endif /* TRANS_SERVER */
426
427
428 #ifdef TRANS_SERVER
429 static XtransConnInfo
430 TRANS(Os2OpenCOTSServer)(thistrans, protocol, host, port)
431 Xtransport *thistrans;
432 char *protocol;
433 char *host;
434 char *port;
435 {
436         PRMSG(2,"Os2OpenCOTSServer(%s,%s,%s)\n",protocol,host,port);
437         return TRANS(Os2OpenServer)(thistrans, protocol, host, port);
438 }
439 #endif /* TRANS_SERVER */
440
441
442 #ifdef TRANS_REOPEN
443 static XtransConnInfo
444 TRANS(Os2ReopenCOTSServer)(thistrans, fd, port)
445 Xtransport *thistrans;
446 int        fd;
447 char       *port;
448 {
449
450     XtransConnInfo ciptr;
451     char addr_name[256];
452     int namelen;
453     
454     PRMSG(2,"Os2ReopenCOTSServer(%d,%s)\n", fd, port, 0);
455     
456     if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
457     {
458         PRMSG(1,"Os2ReopenCOTSServer: xcalloc(1,%d) failed\n",
459               sizeof(struct _XtransConnInfo),0,0 );
460         return NULL;
461     }
462     
463         strcpy(addr_name,"local");
464         namelen=sizeof(addr_name);
465         if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
466           {
467                 PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n",
468                 0, 0, 0);
469                 xfree(ciptr);
470                 return(NULL);
471            }
472
473         ciptr->addrlen = namelen;
474         memcpy (ciptr->addr, addr_name, ciptr->addrlen);
475         if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
476           {
477                 PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n",
478                 0, 0, 0);
479                 xfree(ciptr);
480                 return(NULL);
481            }
482
483        ciptr->peeraddrlen = namelen;
484        memcpy (ciptr->peeraddr,addr_name, ciptr->addrlen);
485
486     ciptr->fd = fd;
487     ciptr->family=AF_UNIX;
488     ciptr->flags=1;
489     PRMSG(1,"Os2ReopenCOTSServer: Filled-in info for handle %d on port %s.\n", fd, port, 0);
490
491     return(ciptr);
492 }
493
494 static XtransConnInfo
495 TRANS(Os2ReopenCLTSServer)(thistrans, fd, port)
496 Xtransport *thistrans;
497 int        fd;
498 char       *port;
499 {
500     PRMSG(2,"Os2ReopenCLTSServer(%d,%s)\n", fd, port, 0);
501     return TRANS(Os2ReopenCOTSServer)(thistrans, fd, port);
502 }
503 #endif
504
505 static
506 TRANS(Os2SetOption)(ciptr, option, arg)
507 XtransConnInfo ciptr;
508 int option;
509 int arg;
510 {
511     PRMSG(2,"Os2SetOption(%d,%d,%d)\n",ciptr->fd,option,arg);
512     return -1;
513 }
514
515 #ifdef TRANS_SERVER
516
517 static
518 TRANS(Os2CreateListener)(ciptr, port)
519 XtransConnInfo ciptr;
520 char *port;
521 {
522         PRMSG(2,"Os2CreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port);
523         return 0;
524 }
525
526 static XtransConnInfo
527 TRANS(Os2Accept)(ciptr, status)
528 XtransConnInfo ciptr;
529 int            *status;
530 {
531     XtransConnInfo      newciptr;
532     HFILE hClient;
533     unsigned char length;
534     ULONG action;
535     char clientname[256];
536     struct sockaddr *addr_name;
537     int in,namelen;
538     APIRET rc;
539
540
541     PRMSG(2,"Os2Accept(%x->%d)\n", ciptr, ciptr->fd,0);
542     if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL )
543     {
544         PRMSG(1,"Os2Accept: xcalloc(1,%d) failed\n",
545               sizeof(struct _XtransConnInfo),0,0 );
546         *status = TRANS_ACCEPT_BAD_MALLOC;
547         return NULL;
548     }
549
550 /* Read in length of client pipe name. If fails, then reset server pipe */
551     if((in=read(ciptr->fd,&length,1))<=0){
552         PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n",
553               in,errno,0 );
554         *status = TRANS_ACCEPT_MISC_ERROR;
555         xfree(newciptr);
556         rc = DosDisConnectNPipe(ciptr->fd);
557         rc = DosConnectNPipe (ciptr->fd);
558         if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
559         {
560                 PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
561                 }
562         return NULL;
563         }
564         PRMSG(5, "Os2Accept: Bytes to read for name: %d\n",length,0,0 );
565
566
567 /* Check length for valid length ?? */
568
569 /* Now read in length bytes from pipe for client pipe name */
570     if((in=read(ciptr->fd,clientname,length))<=0){
571         PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n",
572               in,errno,0 );
573         *status = TRANS_ACCEPT_MISC_ERROR;
574         xfree(newciptr);
575         rc = DosDisConnectNPipe(ciptr->fd);
576         rc = DosConnectNPipe (ciptr->fd);
577         if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
578         {
579                 PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
580                 }
581         return NULL;
582         }
583     clientname[length]='\0';
584     PRMSG(5, "Os2Accept: Server name %s length %d\n",clientname,length,0 );
585
586
587 /* Now we have the client pipe name. Open it with DosOpen  */
588
589      rc = DosOpen(clientname,&hClient, &action, 0,
590            FILE_NORMAL, FILE_OPEN,
591            OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
592            (PEAOP2)NULL);
593
594      PRMSG(5, "Os2Accept: Open pipe %s, handle = %d, rc=%d\n",clientname,hClient,rc );
595
596        if (rc) {
597             PRMSG(1,"Os2Accept: Open pipe %s to client failed, rc=%d\n",
598             clientname,rc,0 );
599             PRMSG(1, "\tProbable cause: the client has exited or timed-out.\n",0,0,0 );
600             xfree(newciptr);
601             rc = DosDisConnectNPipe(ciptr->fd);
602             rc = DosConnectNPipe (ciptr->fd);
603             if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
604                {
605                    PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
606                    }
607             return NULL;
608             }
609
610         rc = DosSetNPHState (hClient, NP_NOWAIT | NP_READMODE_BYTE);
611         if (rc != 0)
612         {
613             PRMSG(1,"Os2Accept: Could not set pipe %s to non-blocking mode, rc=%d\n",
614             hClient,rc,0 );
615             xfree(newciptr);
616             rc = DosDisConnectNPipe(ciptr->fd);
617             rc = DosConnectNPipe (ciptr->fd);
618             if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
619                {
620                    PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
621                    }
622             return NULL;
623             }
624
625 /* OK, we seem to be well connected to client. Now disconnect server pipe and put again in listen */
626
627          rc = DosDisConnectNPipe(ciptr->fd);
628          rc = DosConnectNPipe (ciptr->fd);
629         PRMSG(5, "Os2Accept: Reconnecting server pipe %d, rc = %d\n",ciptr->fd,rc,0 );
630
631          if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
632          {
633               PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
634               }  /* Consider this non-fatal for present connection */
635  
636 /* And finally fill-in info in newciptr */
637
638         namelen=sizeof(struct sockaddr);
639         if ((newciptr->addr = (char *) xalloc (namelen)) == NULL)
640           {
641                 PRMSG (1, "Os2Accept: Can't allocate space for the addr\n",
642                 0, 0, 0);
643                 DosClose(hClient);
644                 xfree(newciptr);
645                 return(NULL);
646            }
647
648         newciptr->addrlen = namelen;
649         ((struct sockaddr *)newciptr->addr)->sa_family = AF_UNIX;
650         strcpy (((struct sockaddr *)newciptr->addr)->sa_data, "local");
651
652         if ((newciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
653           {
654                 PRMSG (1, "Os2Accept: Can't allocate space for the addr\n",
655                 0, 0, 0);
656                 DosClose(hClient);
657                 xfree(ciptr->addr);
658                 xfree(newciptr);
659                 return(NULL);
660            }
661
662        newciptr->peeraddrlen = namelen;
663        ((struct sockaddr *)newciptr->peeraddr)->sa_family = AF_UNIX;
664        strcpy (((struct sockaddr *)newciptr->peeraddr)->sa_data, "local");
665
666       PRMSG (5, "Os2Accept: Filled in struct: len %d %d name %s\n",
667                 newciptr->addrlen,newciptr->peeraddrlen,newciptr->peeraddr);
668
669
670         newciptr->index=hClient;
671         newciptr->family=AF_UNIX;
672         if((newciptr->fd=_imphandle(hClient))<0){
673            PRMSG(1,"Os2Accept: Could not import pipe %d into EMX, errno=%d\n",
674            hClient,errno,0 );
675            PRMSG(1, "\tProbable cause: EMX has run out of file handles.\n",0,0,0 );
676            DosClose(hClient);
677            xfree(newciptr->addr);
678            xfree(newciptr->peeraddr);
679            xfree(newciptr);
680            return(NULL);
681            }
682     PRMSG(5, "Os2Accept: Pipe handle %d EMX handle %d",newciptr->index,newciptr->fd,0 );
683
684 #ifdef XSERV_t
685 /* Attach the pipe sem to the pipe. Use handle index as key */
686     rc = DosSetNPipeSem(newciptr->fd, (HSEM)hPipeSem, newciptr->fd);
687     if (rc){
688         PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n",
689                  hPipeSem,newciptr->fd,rc);
690         DosClose(newciptr->fd);
691         xfree(newciptr->addr);
692         xfree(newciptr->peeraddr);
693         xfree(newciptr);
694          return(NULL);
695         }
696 #endif
697
698     fcntl(ciptr->fd,F_SETFL,O_NDELAY);
699     fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC);
700     *status=0;
701     return newciptr;
702 }
703
704 #endif /* TRANS_SERVER */
705
706 #ifdef TRANS_CLIENT
707
708 static
709 TRANS(Os2Connect)(ciptr, host, port)
710 XtransConnInfo ciptr;
711 char *host;
712 char *port;
713 {
714     PRMSG(2,"Os2Connect(%x->%d,%s)\n", ciptr, ciptr->fd, port);
715     return 0;
716 }
717
718 #endif /* TRANS_CLIENT */
719
720 static int
721 TRANS(Os2BytesReadable)(ciptr, pend )
722 XtransConnInfo ciptr;
723 BytesReadable_t *pend;
724 {
725    ULONG rc, state, nread;
726   AVAILDATA avail;
727   char buffer;
728
729   PRMSG(2,"Os2BytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend);
730
731   rc = DosPeekNPipe (ciptr->fd, &buffer, 0, &nread, &avail, &state);
732   if (rc != 0)
733     {
734       errno = EPIPE;
735       *pend = 0;
736       return -1;
737     }
738   if (state == NP_STATE_CLOSING)
739      {
740         errno = EPIPE;
741         *pend = 0;
742         return -1;
743       }
744   errno = 0;
745   *pend = avail.cbpipe;
746   return 0;
747 }
748
749 static int
750 TRANS(Os2Read)(ciptr, buf, size)
751 XtransConnInfo ciptr;
752 char *buf;
753 int size;
754 {
755     int ret;
756     APIRET rc;
757     ULONG ulRead;
758     PRMSG(2,"Os2Read(%d,%x,%d)\n", ciptr->fd, buf, size );
759     errno = 0;
760     rc = DosRead(ciptr->fd, buf, size, &ulRead);
761     if (rc == 0){
762         ret = ulRead;
763         }
764     else if ((rc == 232) || (rc == 231)){
765         errno = EAGAIN;
766         ret = -1;
767         }
768     else if (rc == 6){
769         errno = EBADF;
770         ret = -1;
771         }
772      else if ((rc == 109) || (rc == 230) || (rc == 233)){
773         errno = EPIPE;
774        ret = -1;
775         }
776     else {
777            PRMSG(2,"Os2Read: Unknown return code from DosRead, fd %d rc=%d\n", ciptr->fd,rc,0 );
778            errno = EINVAL;
779            ret = -1;
780            }
781     return (ret);
782 }
783
784 static int
785 TRANS(Os2Write)(ciptr, buf, size)
786 XtransConnInfo ciptr;
787 char *buf;
788 int size;
789 {
790     int ret;
791     APIRET rc;
792     ULONG nWritten;
793     PRMSG(2,"Os2Write(%d,%x,%d)\n", ciptr->fd, buf, size );
794     rc = DosWrite(ciptr->fd, buf, size, &nWritten);
795     if (rc == 0){
796          ret = nWritten;
797          if(nWritten == 0) { 
798                  errno=EAGAIN;
799                  ret = -1;
800                  }
801          }
802     else if ((rc == 39) || (rc == 112)){
803         errno = EAGAIN;
804         ret = -1;
805         }
806     else if ((rc == 109) || (rc == 230) || (rc == 233)){
807         errno = EPIPE;
808         ret = -1;
809         }
810     else if (rc == 6){
811          errno=EBADF;
812          ret = -1;
813          }
814     else {
815         PRMSG(2,"(Os2Write)Unknown return code from DosWrite, fd %d rc=%d\n", ciptr->fd,rc,0 );
816         errno = EINVAL;
817         ret = -1;
818         }
819     return (ret);
820 }
821
822 static int
823 TRANS(Os2Readv)(ciptr, buf, size)
824 XtransConnInfo  ciptr;
825 struct iovec    *buf;
826 int             size;
827 {
828     int ret;
829     PRMSG(2,"Os2Readv(%d,%x,%d)\n", ciptr->fd, buf, size );
830     ret = READV(ciptr,buf,size);
831     if ((ret <0) && (errno == EINVAL)) errno = EPIPE;
832     return (ret);
833 }
834
835 static int
836 TRANS(Os2Writev)(ciptr, buf, size)
837 XtransConnInfo  ciptr;
838 struct iovec    *buf;
839 int             size;
840 {
841     int ret;
842     PRMSG(2,"Os2Writev(%d,%x,%d)\n", ciptr->fd, buf, size );
843     ret = WRITEV(ciptr,buf,size);
844     if ((ret <0) && (errno == EINVAL)) errno = EPIPE;
845     if ((ret <0) && (errno == ENOSPC)) errno = EAGAIN;
846     return (ret);
847 }
848
849 static int
850 TRANS(Os2Disconnect)(ciptr)
851 XtransConnInfo ciptr;
852 {
853     PRMSG(2,"Os2Disconnect(%x->%d)\n", ciptr, ciptr->fd, 0);
854     return 0;
855 }
856
857 static int
858 TRANS(Os2Close)(ciptr)
859 XtransConnInfo ciptr;
860 {
861     int ret;
862     PRMSG(2,"Os2Close(%x->%d)\n", ciptr, ciptr->fd ,0);
863     ret=close(ciptr->fd);
864     return ret;
865 }
866
867 static int
868 TRANS(Os2CloseForCloning)(ciptr)
869 XtransConnInfo ciptr;
870 {
871     int ret;
872
873     PRMSG(2,"Os2CloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0);
874     ret=close(ciptr->fd);
875     return ret;
876 }
877
878
879 Xtransport      TRANS(OS2LocalFuncs) = {
880         /* Local Interface */
881         "local",
882         TRANS_LOCAL,
883 #ifdef TRANS_CLIENT
884         TRANS(Os2OpenCOTSClient),
885 #endif /* TRANS_CLIENT */
886 #ifdef TRANS_SERVER
887         TRANS(Os2OpenCOTSServer),
888 #endif /* TRANS_SERVER */
889 #ifdef TRANS_CLIENT
890         TRANS(Os2OpenCLTSClient),
891 #endif /* TRANS_CLIENT */
892 #ifdef TRANS_SERVER
893         TRANS(Os2OpenCLTSServer),
894 #endif /* TRANS_SERVER */
895 #ifdef TRANS_REOPEN
896         TRANS(Os2ReopenCOTSServer),
897         TRANS(Os2ReopenCLTSServer),
898 #endif
899         TRANS(Os2SetOption),
900 #ifdef TRANS_SERVER
901         TRANS(Os2CreateListener),
902         NULL,                  /* ResetListener */
903         TRANS(Os2Accept),
904 #endif /* TRANS_SERVER */
905 #ifdef TRANS_CLIENT
906         TRANS(Os2Connect),
907 #endif /* TRANS_CLIENT */
908         TRANS(Os2BytesReadable),
909         TRANS(Os2Read),
910         TRANS(Os2Write),
911         TRANS(Os2Readv),
912         TRANS(Os2Writev),
913         TRANS(Os2Disconnect),
914         TRANS(Os2Close),
915         TRANS(Os2CloseForCloning),
916 };
917
918 #ifdef XSERV_t
919 /* This function is used in the server to initialize the semaphore used with pipes */
920
921 BOOL init_server_pipes()
922 {
923    static BOOL first_time=TRUE;
924    ULONG rc;
925
926    if(first_time){
927         rc = DosCreateEventSem(NULL, &hPipeSem,DC_SEM_SHARED,FALSE);
928         if (rc){
929            PRMSG(1,"Os2OpenListener (init_server_pipes): Could not create pipe semaphore, rc=%d\n",
930                 rc,0,0);
931            return(FALSE);
932            }
933      first_time=FALSE;
934      }
935 return(TRUE);
936 }
937 #endif  /* XSERV_t */