11ab64890Smrg/*
21ab64890Smrg * (c) Copyright 1996 by Sebastien Marineau and Holger Veit
31ab64890Smrg *			<marineau@genie.uottawa.ca>
41ab64890Smrg *                      <Holger.Veit@gmd.de>
51ab64890Smrg *
661b2299dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
761b2299dSmrg * copy of this software and associated documentation files (the "Software"),
861b2299dSmrg * to deal in the Software without restriction, including without limitation
961b2299dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1061b2299dSmrg * and/or sell copies of the Software, and to permit persons to whom the
111ab64890Smrg * Software is furnished to do so, subject to the following conditions:
121ab64890Smrg *
131ab64890Smrg * The above copyright notice and this permission notice shall be included in
141ab64890Smrg * all copies or substantial portions of the Software.
1561b2299dSmrg *
161ab64890Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171ab64890Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1861b2299dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1961b2299dSmrg * HOLGER VEIT  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2061b2299dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2161b2299dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
221ab64890Smrg * SOFTWARE.
2361b2299dSmrg *
2461b2299dSmrg * Except as contained in this notice, the name of Sebastien Marineau or Holger Veit
2561b2299dSmrg * shall not be used in advertising or otherwise to promote the sale, use or other
261ab64890Smrg * dealings in this Software without prior written authorization from Holger Veit or
271ab64890Smrg * Sebastien Marineau.
281ab64890Smrg *
291ab64890Smrg */
301ab64890Smrg
311ab64890Smrg
321ab64890Smrg/* A few OS/2 functions needed in the X11 lib. Mainly, the file path redirection
331ab64890Smrg * functions and the "optimized" select() for the clients */
341ab64890Smrg
351ab64890Smrg#define I_NEED_OS2_H
361ab64890Smrg#ifdef HAVE_CONFIG_H
371ab64890Smrg#include <config.h>
381ab64890Smrg#endif
391ab64890Smrg#include <X11/Xpoll.h>
401ab64890Smrg#include <stdio.h>
411ab64890Smrg#include <sys/errno.h>
421ab64890Smrg#define INCL_DOSSEMAPHORES
431ab64890Smrg#define INCL_DOSNPIPES
441ab64890Smrg#define INCL_DOSMISC
451ab64890Smrg#define INCL_DOSMODULEMGR
461ab64890Smrg#undef BOOL
471ab64890Smrg#undef BYTE
481ab64890Smrg#include <os2.h>
491ab64890Smrg#include <sys/select.h>
501ab64890Smrg#include <sys/time.h>
511ab64890Smrg
521ab64890Smrgchar *__XOS2RedirRoot(char *fname)
531ab64890Smrg{
541ab64890Smrg    /* This adds a further redirection by allowing the ProjectRoot
551ab64890Smrg     * to be prepended by the content of the envvar X11ROOT.
561ab64890Smrg     * This is for the purpose to move the whole X11 stuff to a different
571ab64890Smrg     * disk drive.
581ab64890Smrg     * The feature was added despite various environment variables
591ab64890Smrg     * because not all file opens respect them.
601ab64890Smrg     */
611ab64890Smrg    static char redirname[300]; /* enough for long filenames */
621ab64890Smrg    char *root;
631ab64890Smrg
641ab64890Smrg    /* if name does not start with /, assume it is not root-based */
651ab64890Smrg    if (fname==0 || !(fname[0]=='/' || fname[0]=='\\'))
661ab64890Smrg	return fname;
671ab64890Smrg
681ab64890Smrg    root = (char*)getenv("X11ROOT");
6961b2299dSmrg    if (root==0 ||
701ab64890Smrg	(fname[1]==':' && isalpha(fname[0])) ||
711ab64890Smrg        (strlen(fname)+strlen(root)+2) > 300)
721ab64890Smrg	return fname;
731ab64890Smrg    sprintf(redirname,"%s%s",root,fname);
741ab64890Smrg    return redirname;
751ab64890Smrg}
761ab64890Smrg
771ab64890Smrgchar *__XOS2RedirRoot1(char *format, char *arg1, char *arg2, char *arg3)
781ab64890Smrg{
791ab64890Smrg    /* this first constructs a name from a format and up to three
801ab64890Smrg     * components, then adds a path
811ab64890Smrg     */
821ab64890Smrg    char buf[300];
831ab64890Smrg    sprintf(buf,format,arg1,arg2,arg3);
841ab64890Smrg    return __XOS2RedirRoot(buf);
851ab64890Smrg}
861ab64890Smrg
871ab64890Smrg/* This below implements select() for the calls in this file. It has been */
881ab64890Smrg/* somewhat optimized for improved performance, but assumes a few */
891ab64890Smrg/* things so it cannot be used as a general select. If both pipes and     */
901ab64890Smrg/* sockets are present, this may call the emx select                          */
911ab64890Smrg
921ab64890Smrg
931ab64890SmrgHEV hPipeSem;
941ab64890SmrgHMODULE hmod_so32dll;
951ab64890Smrgstatic int (*os2_tcp_select)(int*,int,int,int,long);
961ab64890SmrgULONG os2_get_sys_millis();
971ab64890Smrgextern int _files[];
981ab64890Smrg
991ab64890Smrg#define MAX_TCP 256
1001ab64890Smrg/* These lifted from sys/emx.h. Change if that changes there! */
1011ab64890Smrg#define F_SOCKET 0x10000000
1021ab64890Smrg#define F_PIPE 0x20000000
1031ab64890Smrg
1041ab64890Smrgstruct select_data
1051ab64890Smrg{
1061ab64890Smrg   fd_set read_copy;
1071ab64890Smrg   fd_set write_copy;
1081ab64890Smrg   BOOL have_read;
1091ab64890Smrg   BOOL have_write;
1101ab64890Smrg   int tcp_select_mask[MAX_TCP];
1111ab64890Smrg   int tcp_emx_handles[MAX_TCP];
1121ab64890Smrg   int tcp_select_copy[MAX_TCP];
1131ab64890Smrg   int socket_nread;
1141ab64890Smrg   int socket_nwrite;
1151ab64890Smrg   int socket_ntotal;
1161ab64890Smrg   int pipe_ntotal;
1171ab64890Smrg   int pipe_have_write;
1181ab64890Smrg   int max_fds;
1191ab64890Smrg};
1201ab64890Smrg
1211ab64890Smrgint os2ClientSelect(int nfds, fd_set *readfds, fd_set *writefds,
1221ab64890Smrg        fd_set *exceptfds, struct timeval *timeout)
1231ab64890Smrg{
1241ab64890Smrgstatic BOOL FirstTime=TRUE;
1251ab64890Smrgstatic haveTCPIP=TRUE;
1261ab64890SmrgULONG timeout_ms;
1271ab64890SmrgULONG postCount, start_millis,now_millis;
1281ab64890Smrgchar faildata[16];
1291ab64890Smrgstruct select_data sd;
1301ab64890SmrgBOOL any_ready;
1311ab64890Smrgint np,ns, i,ready_handles,n;
1321ab64890SmrgAPIRET rc;
1331ab64890Smrg
13461b2299dSmrgsd.have_read=FALSE; sd.have_write=FALSE;
1351ab64890Smrgsd.socket_nread=0; sd.socket_nwrite=0; sd.socket_ntotal=0;
1361ab64890Smrgsd.max_fds=31; ready_handles=0; any_ready=FALSE;
1371ab64890Smrgsd.pipe_ntotal=0; sd.pipe_have_write=FALSE;
1381ab64890Smrg
1391ab64890Smrgif(FirstTime){
1401ab64890Smrg   /* First load the so32dll.dll module and get a pointer to the SELECT fn */
1411ab64890Smrg
1421ab64890Smrg   if((rc=DosLoadModule(faildata,sizeof(faildata),"SO32DLL",&hmod_so32dll))!=0){
1431ab64890Smrg        fprintf(stderr, "Could not load module so32dll.dll, rc = %d. Error note %s\n",rc,faildata);
1441ab64890Smrg        haveTCPIP=FALSE;
1451ab64890Smrg        }
1461ab64890Smrg   if((rc = DosQueryProcAddr(hmod_so32dll, 0, "SELECT", (PPFN)&os2_tcp_select))!=0){
1471ab64890Smrg        fprintf(stderr, "Could not query address of SELECT, rc = %d.\n",rc);
1481ab64890Smrg        haveTCPIP=FALSE;
1491ab64890Smrg        }
1501ab64890Smrg   /* Call these a first time to set the semaphore */
1511ab64890Smrg    rc = DosCreateEventSem(NULL, &hPipeSem, DC_SEM_SHARED, FALSE);
15261b2299dSmrg    if(rc) {
1531ab64890Smrg             fprintf(stderr, "Could not create event semaphore, rc=%d\n",rc);
1541ab64890Smrg             return(-1);
1551ab64890Smrg             }
1561ab64890Smrg    rc = DosResetEventSem(hPipeSem, &postCount);
1571ab64890Smrg    FirstTime = FALSE;
1581ab64890Smrg}
1591ab64890Smrg
1601ab64890Smrg/* Set up the time delay structs */
1611ab64890Smrg
1621ab64890Smrg    if(timeout!=NULL) {
1631ab64890Smrg	timeout_ms=timeout->tv_sec*1000+timeout->tv_usec/1000;
1641ab64890Smrg	}
1651ab64890Smrg    else { timeout_ms=1000000; }  /* This should be large enough... */
1661ab64890Smrg    if(timeout_ms>0) start_millis=os2_get_sys_millis();
1671ab64890Smrg
1681ab64890Smrg/* Copy the masks */
1691ab64890Smrg    {FD_ZERO(&sd.read_copy);}
1701ab64890Smrg    {FD_ZERO(&sd.write_copy);}
1711ab64890Smrg    if(readfds!=NULL){ XFD_COPYSET(readfds,&sd.read_copy); sd.have_read=TRUE;}
1721ab64890Smrg    if(writefds!=NULL) {XFD_COPYSET(writefds,&sd.write_copy);sd.have_write=TRUE;}
1731ab64890Smrg
1741ab64890Smrg/* And zero the original masks */
1751ab64890Smrg    if(sd.have_read){ FD_ZERO(readfds);}
1761ab64890Smrg    if(sd.have_write) {FD_ZERO(writefds);}
1771ab64890Smrg    if(exceptfds != NULL) {FD_ZERO(exceptfds);}
1781ab64890Smrg
1791ab64890Smrg/* Now we parse the fd_sets passed to select and separate pipe/sockets */
1801ab64890Smrg        n = os2_parse_select(&sd,nfds);
1811ab64890Smrg        if(n == -1) {
1821ab64890Smrg           errno = EBADF;
1831ab64890Smrg           return (-1);
1841ab64890Smrg           }
1851ab64890Smrg
1861ab64890Smrg/* Now we have three cases: either we have sockets, pipes, or both */
1871ab64890Smrg/* We handle all three cases differently to optimize things */
1881ab64890Smrg
1891ab64890Smrg/* Case 1: only pipes! */
1901ab64890Smrg        if((sd.pipe_ntotal >0) && (!sd.socket_ntotal)){
1911ab64890Smrg            np = os2_check_pipes(&sd,readfds,writefds);
1921ab64890Smrg            if(np > 0){
1931ab64890Smrg               return (np);
1941ab64890Smrg               }
1951ab64890Smrg            else if (np == -1) { return(-1); }
1961ab64890Smrg            while(!any_ready){
1971ab64890Smrg                 rc = DosWaitEventSem(hPipeSem, timeout_ms);
1981ab64890Smrg                 if(rc == 640)  {
1991ab64890Smrg                     return(0);
2001ab64890Smrg                     }
2011ab64890Smrg                 if((rc != 0) && (rc != 95)) {errno= EBADF; return(-1);}
2021ab64890Smrg                 np = os2_check_pipes(&sd,readfds,writefds);
2031ab64890Smrg                 if (np > 0){
2041ab64890Smrg                    return(np);
2051ab64890Smrg                    }
2061ab64890Smrg                 else if (np < 0){ return(-1); }
2071ab64890Smrg                 }
2081ab64890Smrg          }
2091ab64890Smrg
2101ab64890Smrg/* Case 2: only sockets. Just let the os/2 tcp select do the work */
2111ab64890Smrg        if((sd.socket_ntotal > 0) && (!sd.pipe_ntotal)){
2121ab64890Smrg                ns = os2_check_sockets(&sd, readfds, writefds, timeout_ms);
2131ab64890Smrg                return (ns);
2141ab64890Smrg                }
2151ab64890Smrg
2161ab64890Smrg/* Case 3: combination of both */
2171ab64890Smrg        if((sd.socket_ntotal > 0) && (sd.pipe_ntotal)){
2181ab64890Smrg           np = os2_check_pipes(&sd,readfds,writefds);
2191ab64890Smrg              if(np > 0){
2201ab64890Smrg                 any_ready=TRUE;
2211ab64890Smrg                 ready_handles += np;
2221ab64890Smrg                 }
2231ab64890Smrg              else if (np == -1) { return(-1); }
2241ab64890Smrg
2251ab64890Smrg           ns = os2_check_sockets(&sd,readfds,writefds, 0);
2261ab64890Smrg           if(ns>0){
2271ab64890Smrg               ready_handles+=ns;
2281ab64890Smrg               any_ready = TRUE;
2291ab64890Smrg               }
2301ab64890Smrg           else if (ns == -1) {return(-1);}
2311ab64890Smrg
2321ab64890Smrg           while (!any_ready && timeout_ms){
2331ab64890Smrg
2341ab64890Smrg                rc = DosWaitEventSem(hPipeSem, 10L);
2351ab64890Smrg                if(rc == 0){
2361ab64890Smrg                        np = os2_check_pipes(&sd,readfds,writefds);
2371ab64890Smrg                        if(np > 0){
2381ab64890Smrg                        ready_handles+=np;
2391ab64890Smrg                        any_ready = TRUE;
2401ab64890Smrg                        }
24161b2299dSmrg                        else if (np == -1) {
2421ab64890Smrg                                return(-1); }
2431ab64890Smrg                      }
2441ab64890Smrg
2451ab64890Smrg                 ns = os2_check_sockets(&sd,readfds,writefds,exceptfds, 0);
2461ab64890Smrg                 if(ns>0){
2471ab64890Smrg                      ready_handles+=ns;
2481ab64890Smrg                      any_ready = TRUE;
2491ab64890Smrg                     }
2501ab64890Smrg                 else if (ns == -1) {return(-1);}
2511ab64890Smrg
25261b2299dSmrg                  if (i%8 == 0) {
2531ab64890Smrg                    now_millis = os2_get_sys_millis();
2541ab64890Smrg                    if((now_millis-start_millis) > timeout_ms) timeout_ms = 0;
2551ab64890Smrg                    }
2561ab64890Smrg                   i++;
2571ab64890Smrg                  }
2581ab64890Smrg        }
2591ab64890Smrg
2601ab64890Smrgreturn(ready_handles);
2611ab64890Smrg}
2621ab64890Smrg
2631ab64890Smrg
2641ab64890SmrgULONG os2_get_sys_millis()
2651ab64890Smrg{
2661ab64890Smrg   APIRET rc;
2671ab64890Smrg   ULONG milli;
2681ab64890Smrg
2691ab64890Smrg   rc = DosQuerySysInfo(14, 14, &milli, sizeof(milli));
2701ab64890Smrg   if(rc) {
2711ab64890Smrg        fprintf(stderr,"Bad return code querying the millisecond counter! rc=%d\n",rc);
2721ab64890Smrg        return(0);
2731ab64890Smrg        }
2741ab64890Smrg   return(milli);
2751ab64890Smrg}
2761ab64890Smrg
2771ab64890Smrgint os2_parse_select(sd,nfds)
2781ab64890Smrgstruct select_data *sd;
2791ab64890Smrgint nfds;
2801ab64890Smrg{
2811ab64890Smrg   int i;
2821ab64890Smrg   APIRET rc;
2831ab64890Smrg/* First we determine up to which descriptor we need to check.              */
2849c019ec5Smaya/* No need to check up to 256 if we don't have to (and usually we don't...)*/
2851ab64890Smrg/* Note: stuff here is hardcoded for fd_sets which are int[8] as in EMX!!!    */
2861ab64890Smrg
2871ab64890Smrg  if(nfds > sd->max_fds){
2881ab64890Smrg     for(i=0;i<((FD_SETSIZE+31)/32);i++){
2891ab64890Smrg        if(sd->read_copy.fds_bits[i] ||
2901ab64890Smrg            sd->write_copy.fds_bits[i])
2911ab64890Smrg                        sd->max_fds=(i*32) +32;
2921ab64890Smrg        }
2931ab64890Smrg     }
2941ab64890Smrg   else { sd->max_fds = nfds; }
2951ab64890Smrg/* Check if result is greater than specified in select() call */
2961ab64890Smrg  if(sd->max_fds > nfds) sd->max_fds = nfds;
2971ab64890Smrg
2981ab64890Smrg  if (sd->have_read)
2991ab64890Smrg    {
3001ab64890Smrg      for (i = 0; i < sd->max_fds; ++i) {
3011ab64890Smrg        if (FD_ISSET (i, &sd->read_copy)){
3021ab64890Smrg         if(_files[i] & F_SOCKET)
3031ab64890Smrg           {
3041ab64890Smrg            sd->tcp_select_mask[sd->socket_ntotal]=_getsockhandle(i);
3051ab64890Smrg            sd->tcp_emx_handles[sd->socket_ntotal]=i;
3061ab64890Smrg            sd->socket_ntotal++; sd->socket_nread++;
3071ab64890Smrg           }
3081ab64890Smrg         else if (_files[i] & F_PIPE)
3091ab64890Smrg          {
3101ab64890Smrg            sd -> pipe_ntotal++;
3111ab64890Smrg            rc = DosSetNPipeSem((HPIPE)i, (HSEM) hPipeSem, i);
3121ab64890Smrg            if(rc) { fprintf(stderr,"Error SETNPIPE rc = %d\n",rc); return -1;}
3131ab64890Smrg          }
3141ab64890Smrg        }
3151ab64890Smrg      }
3161ab64890Smrg    }
3171ab64890Smrg
3181ab64890Smrg  if (sd->have_write)
3191ab64890Smrg    {
3201ab64890Smrg      for (i = 0; i < sd->max_fds; ++i) {
3211ab64890Smrg        if (FD_ISSET (i, &sd->write_copy)){
3221ab64890Smrg         if(_files[i] & F_SOCKET)
3231ab64890Smrg         {
3241ab64890Smrg            sd->tcp_select_mask[sd->socket_ntotal]=_getsockhandle(i);
3251ab64890Smrg            sd->tcp_emx_handles[sd->socket_ntotal]=i;
3261ab64890Smrg            sd->socket_ntotal++; sd->socket_nwrite++;
3271ab64890Smrg         }
3281ab64890Smrg         else if (_files[i] & F_PIPE)
3291ab64890Smrg          {
3301ab64890Smrg            sd -> pipe_ntotal++;
3311ab64890Smrg            rc = DosSetNPipeSem((HPIPE)i, (HSEM) hPipeSem, i);
3321ab64890Smrg            if(rc) { fprintf(stderr,"Error SETNPIPE rc = %d\n",rc); return -1;}
3331ab64890Smrg            sd -> pipe_have_write=TRUE;
3341ab64890Smrg          }
3351ab64890Smrg        }
3361ab64890Smrg      }
3371ab64890Smrg    }
3381ab64890Smrg
3391ab64890Smrg
3401ab64890Smrgreturn(sd->socket_ntotal);
3411ab64890Smrg}
3421ab64890Smrg
3431ab64890Smrg
3441ab64890Smrgint os2_check_sockets(sd,readfds,writefds)
3451ab64890Smrgstruct select_data *sd;
3461ab64890Smrgfd_set *readfds,*writefds;
3471ab64890Smrg{
3481ab64890Smrg   int e,i;
3491ab64890Smrg   int j,n;
3501ab64890Smrg        memcpy(sd->tcp_select_copy,sd->tcp_select_mask,
3511ab64890Smrg                sd->socket_ntotal*sizeof(int));
35261b2299dSmrg
3531ab64890Smrg        e = os2_tcp_select(sd->tcp_select_copy,sd->socket_nread,
3541ab64890Smrg                sd->socket_nwrite, 0, 0);
3551ab64890Smrg
3561ab64890Smrg        if(e == 0) return(e);
3571ab64890Smrg/* We have something ready? */
3581ab64890Smrg        if(e>0){
3591ab64890Smrg            j = 0; n = 0;
3601ab64890Smrg            for (i = 0; i < sd->socket_nread; ++i, ++j)
3611ab64890Smrg                 if (sd->tcp_select_copy[j] != -1)
3621ab64890Smrg                    {
3631ab64890Smrg                    FD_SET (sd->tcp_emx_handles[j], readfds);
3641ab64890Smrg                    n ++;
3651ab64890Smrg                    }
3661ab64890Smrg             for (i = 0; i < sd->socket_nwrite; ++i, ++j)
3671ab64890Smrg                  if (sd->tcp_select_copy[j] != -1)
3681ab64890Smrg                     {
3691ab64890Smrg                     FD_SET (sd->tcp_emx_handles[j], writefds);
3701ab64890Smrg                     n ++;
3711ab64890Smrg                     }
3721ab64890Smrg               errno = 0;
37361b2299dSmrg
3741ab64890Smrg               return n;
3751ab64890Smrg              }
3761ab64890Smrg        if(e<0){
3771ab64890Smrg           /*Error -- TODO */
3781ab64890Smrg           fprintf(stderr,"Error in server select! e=%d\n",e);
3791ab64890Smrg           errno = EBADF;
3801ab64890Smrg           return (-1);
3811ab64890Smrg           }
3821ab64890Smrg }
3831ab64890Smrg
3841ab64890Smrg/* Check to see if anything is ready on pipes */
3851ab64890Smrg
3861ab64890Smrgint os2_check_pipes(sd,readfds,writefds)
3871ab64890Smrgstruct select_data *sd;
3881ab64890Smrgfd_set *readfds,*writefds;
3891ab64890Smrg{
3901ab64890Smrgint i,e;
3911ab64890SmrgULONG ulPostCount;
3921ab64890SmrgPIPESEMSTATE pipeSemState[128];
3931ab64890SmrgAPIRET rc;
3941ab64890Smrg        e = 0;
3951ab64890Smrg        rc = DosResetEventSem(hPipeSem,&ulPostCount);
39661b2299dSmrg        rc = DosQueryNPipeSemState((HSEM) hPipeSem, (PPIPESEMSTATE)&pipeSemState,
3971ab64890Smrg                sizeof(pipeSemState));
3981ab64890Smrg        if(rc) fprintf(stderr,"SELECT: rc from QueryNPipeSem: %d\n",rc);
3991ab64890Smrg        i=0;
4001ab64890Smrg        while (pipeSemState[i].fStatus != 0) {
4011ab64890Smrg           /*fprintf(stderr,"SELECT: sem entry, stat=%d, flag=%d, key=%d,avail=%d\n",
4021ab64890Smrg                pipeSemState[i].fStatus,pipeSemState[i].fFlag,pipeSemState[i].usKey,
4031ab64890Smrg                pipeSemState[i].usAvail); */
4041ab64890Smrg           if((pipeSemState[i].fStatus == 1) &&
4051ab64890Smrg                    (FD_ISSET(pipeSemState[i].usKey,&sd->read_copy))){
4061ab64890Smrg                FD_SET(pipeSemState[i].usKey,readfds);
4071ab64890Smrg                e++;
4081ab64890Smrg                }
4091ab64890Smrg           else if((pipeSemState[i].fStatus == 2)  &&
4101ab64890Smrg                    (FD_ISSET(pipeSemState[i].usKey,&sd->write_copy))){
4111ab64890Smrg                FD_SET(pipeSemState[i].usKey,writefds);
4121ab64890Smrg                e++;
4131ab64890Smrg                }
4141ab64890Smrg            else if( (pipeSemState[i].fStatus == 3) &&
4151ab64890Smrg                ( (FD_ISSET(pipeSemState[i].usKey,&sd->read_copy)) ||
4161ab64890Smrg                  (FD_ISSET(pipeSemState[i].usKey,&sd->write_copy)) )){
4171ab64890Smrg                errno = EBADF;
4181ab64890Smrg                return (-1);
4191ab64890Smrg                }
4201ab64890Smrg            i++;
4211ab64890Smrg            } /* endwhile */
4221ab64890Smrg        /*fprintf(stderr,"Done listing pipe sem entries, total %d entries, total ready entries %d\n",i,e);*/
4231ab64890Smrgerrno = 0;
4241ab64890Smrgreturn(e);
4251ab64890Smrg}
4261ab64890Smrg
4271ab64890Smrg
4281ab64890Smrg
429