Back to index

lightning-sunbird  0.9+nobinonly
os2sock.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Netscape Portable Runtime (NSPR).
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 /* OS/2 Sockets module
00040  *
00041  */
00042 
00043 /*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2    */
00044 /*There is standard BSD (which is kind of slow) and a new flavor of select() that takes      */
00045 /*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */
00046 /*a millisecond count for timeout. In the interest of performance I have choosen the OS/2    */
00047 /*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info.          */ 
00048 
00049 #include "primpl.h"
00050 
00051 #ifdef XP_OS2_EMX
00052  #include <sys/time.h> /* For timeval. */
00053 #endif
00054 
00055 #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
00056 #define READ_FD   1
00057 #define WRITE_FD  2
00058 
00059 #ifdef XP_OS2_VACPP
00060 #define _OS2_WRITEV writev
00061 #define _OS2_IOCTL ioctl
00062 #else
00063 #define _OS2_WRITEV so_writev
00064 #define _OS2_IOCTL so_ioctl
00065 #endif
00066 
00067 /* --- SOCKET IO --------------------------------------------------------- */
00068 
00069 
00070 PRInt32
00071 _PR_MD_SOCKET(int domain, int type, int flags)
00072 {
00073     PRInt32 osfd, err;
00074 
00075     osfd = socket(domain, type, flags);
00076 
00077     if (osfd == -1) 
00078     {
00079         err = sock_errno();
00080         _PR_MD_MAP_SOCKET_ERROR(err);
00081     }
00082 
00083     return(osfd);
00084 }
00085 
00086 /*
00087 ** _MD_CloseSocket() -- Close a socket
00088 **
00089 */
00090 PRInt32
00091 _MD_CloseSocket(PRInt32 osfd)
00092 {
00093     PRInt32 rv, err;
00094 
00095     rv = soclose(osfd);
00096     if (rv == -1) {
00097         err = sock_errno();
00098         _PR_MD_MAP_CLOSE_ERROR(err);
00099     }
00100     return rv;
00101 }
00102 
00103 PRInt32
00104 _MD_SocketAvailable(PRFileDesc *fd)
00105 {
00106     PRInt32 result;
00107 
00108     if (_OS2_IOCTL(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) {
00109         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno());
00110         return -1;
00111     }
00112     return result;
00113 }
00114 
00115 static PRInt32
00116 socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
00117 {
00118     PRInt32 rv = -1;
00119     PRThread *me = _PR_MD_CURRENT_THREAD();
00120     PRIntervalTime epoch, now, elapsed, remaining;
00121     PRBool wait_for_remaining;
00122     PRInt32 syserror;
00123 #ifdef BSD_SELECT
00124     struct timeval tv;
00125     fd_set rd_wr;
00126 #else
00127     int socks[1];
00128     long lTimeout;
00129 #endif
00130 
00131     switch (timeout) {
00132         case PR_INTERVAL_NO_WAIT:
00133             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
00134             break;
00135         case PR_INTERVAL_NO_TIMEOUT:
00136             /*
00137              * This is a special case of the 'default' case below.
00138              * Please see the comments there.
00139              */
00140 #ifdef BSD_SELECT
00141             tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
00142             tv.tv_usec = 0;
00143             FD_ZERO(&rd_wr);
00144             do {
00145                 FD_SET(osfd, &rd_wr);
00146                 if (fd_type == READ_FD)
00147                     rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
00148                 else
00149                     rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
00150 #else
00151             lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; 
00152             do {
00153                 socks[0] = osfd;
00154                 if (fd_type == READ_FD)
00155                     rv = os2_select(socks, 1, 0, 0, lTimeout);
00156                 else
00157                     rv = os2_select(socks, 0, 1, 0, lTimeout);
00158 #endif                    
00159                 if (rv == -1 && (syserror = sock_errno()) != EINTR) {
00160                     _PR_MD_MAP_SELECT_ERROR(syserror);
00161                     break;
00162                 }
00163                 if (_PR_PENDING_INTERRUPT(me)) {
00164                     me->flags &= ~_PR_INTERRUPT;
00165                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
00166                     rv = -1;
00167                     break;
00168                 }
00169             } while (rv == 0 || (rv == -1 && syserror == EINTR));
00170             break;
00171         default:
00172             now = epoch = PR_IntervalNow();
00173             remaining = timeout;
00174 #ifdef BSD_SELECT
00175             FD_ZERO(&rd_wr);
00176 #endif
00177             do {
00178                 /*
00179                  * We block in select for at most
00180                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
00181                  * so that there is an upper limit on the delay
00182                  * before the interrupt bit is checked.
00183                  */
00184 #ifdef BSD_SELECT
00185                 wait_for_remaining = PR_TRUE;
00186                 tv.tv_sec = PR_IntervalToSeconds(remaining);
00187                 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
00188                     wait_for_remaining = PR_FALSE;
00189                     tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
00190                     tv.tv_usec = 0;
00191                 } else {
00192                     tv.tv_usec = PR_IntervalToMicroseconds(
00193                         remaining -
00194                         PR_SecondsToInterval(tv.tv_sec));
00195                 }
00196                 FD_SET(osfd, &rd_wr);
00197                 if (fd_type == READ_FD)
00198                     rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
00199                 else
00200                     rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
00201 #else
00202                 wait_for_remaining = PR_TRUE;
00203                 lTimeout = PR_IntervalToMilliseconds(remaining);
00204                 if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
00205                     wait_for_remaining = PR_FALSE;
00206                     lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
00207                 }
00208                 socks[0] = osfd;
00209                 if (fd_type == READ_FD)
00210                     rv = os2_select(socks, 1, 0, 0, lTimeout);
00211                 else
00212                     rv = os2_select(socks, 0, 1, 0, lTimeout);
00213 #endif
00214                 /*
00215                  * we don't consider EINTR a real error
00216                  */
00217                 if (rv == -1 && (syserror = sock_errno()) != EINTR) {
00218                     _PR_MD_MAP_SELECT_ERROR(syserror);
00219                     break;
00220                 }
00221                 if (_PR_PENDING_INTERRUPT(me)) {
00222                     me->flags &= ~_PR_INTERRUPT;
00223                     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
00224                     rv = -1;
00225                     break;
00226                 }
00227                 /*
00228                  * We loop again if select timed out or got interrupted
00229                  * by a signal, and the timeout deadline has not passed yet.
00230                  */
00231                 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
00232                     /*
00233                      * If select timed out, we know how much time
00234                      * we spent in blocking, so we can avoid a
00235                      * PR_IntervalNow() call.
00236                      */
00237                     if (rv == 0) {
00238                         if (wait_for_remaining) {
00239                             now += remaining;
00240                         } else {
00241 #ifdef BSD_SELECT
00242                             now += PR_SecondsToInterval(tv.tv_sec)
00243                                 + PR_MicrosecondsToInterval(tv.tv_usec);
00244 #else
00245                             now += PR_MillisecondsToInterval(lTimeout);
00246 #endif
00247                         }
00248                     } else {
00249                         now = PR_IntervalNow();
00250                     }
00251                     elapsed = (PRIntervalTime) (now - epoch);
00252                     if (elapsed >= timeout) {
00253                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
00254                         rv = -1;
00255                         break;
00256                     } else {
00257                         remaining = timeout - elapsed;
00258                     }
00259                 }
00260             } while (rv == 0 || (rv == -1 && syserror == EINTR));
00261             break;
00262         }
00263     return(rv);
00264 }
00265 
00266 PRInt32
00267 _MD_Accept(PRFileDesc *fd, PRNetAddr *addr,
00268            PRUint32 *addrlen, PRIntervalTime timeout)
00269 {
00270     PRInt32 osfd = fd->secret->md.osfd;
00271     PRInt32 rv, err;
00272     PRThread *me = _PR_MD_CURRENT_THREAD();
00273 
00274     while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1)
00275     {
00276         err = sock_errno();
00277         if ((err == EWOULDBLOCK) || (err == ECONNABORTED))
00278         {
00279             if (fd->secret->nonblocking) {
00280                 break;
00281             }
00282                 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
00283                     goto done;
00284         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
00285             continue;
00286         } else {
00287             break;
00288         }
00289     }
00290     if (rv < 0) {
00291         _PR_MD_MAP_ACCEPT_ERROR(err);
00292     }
00293 done:
00294     return(rv);
00295 }
00296 
00297 PRInt32
00298 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, 
00299                PRIntervalTime timeout)
00300 {
00301     PRInt32 rv, err;
00302     PRThread *me = _PR_MD_CURRENT_THREAD();
00303     PRInt32 osfd = fd->secret->md.osfd;
00304     PRNetAddr addrCopy = *addr; /* Work around a bug in OS/2 where connect
00305                                  * modifies the sockaddr structure.
00306                                  * See Bugzilla bug 100776. */
00307 
00308      /*
00309       * We initiate the connection setup by making a nonblocking connect()
00310       * call.  If the connect() call fails, there are two cases we handle
00311       * specially:
00312       * 1. The connect() call was interrupted by a signal.  In this case
00313       *    we simply retry connect().
00314       * 2. The NSPR socket is nonblocking and connect() fails with
00315       *    EINPROGRESS.  We first wait until the socket becomes writable.
00316       *    Then we try to find out whether the connection setup succeeded
00317       *    or failed.
00318       */
00319 
00320 retry:
00321     if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1)
00322     {
00323         err = sock_errno();
00324 
00325         if (err == EINTR) {
00326             if (_PR_PENDING_INTERRUPT(me)) {
00327                 me->flags &= ~_PR_INTERRUPT;
00328                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
00329                 return -1;
00330             }
00331             goto retry;
00332         }
00333 
00334         if (!fd->secret->nonblocking && (err == EINPROGRESS))
00335         {
00336             /*
00337              * socket_io_wait() may return -1 or 1.
00338              */
00339 
00340             rv = socket_io_wait(osfd, WRITE_FD, timeout);
00341             if (rv == -1) {
00342                 return -1;
00343             }
00344 
00345             PR_ASSERT(rv == 1);
00346             if (_PR_PENDING_INTERRUPT(me)) {
00347                 me->flags &= ~_PR_INTERRUPT;
00348                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
00349                 return -1;
00350             }
00351             err = _MD_os2_get_nonblocking_connect_error(osfd);
00352             if (err != 0) {
00353                 _PR_MD_MAP_CONNECT_ERROR(err);
00354                 return -1;
00355             }
00356             return 0;
00357         }
00358         
00359         _PR_MD_MAP_CONNECT_ERROR(err);
00360     }
00361 
00362     return rv;
00363 }  /* _MD_connect */
00364 
00365 PRInt32
00366 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
00367 {
00368     PRInt32 rv, err;
00369     rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
00370     if (rv < 0) {
00371         err = sock_errno();
00372         _PR_MD_MAP_BIND_ERROR(err);
00373     }
00374     return(rv);
00375 }
00376 
00377 
00378 PRInt32
00379 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
00380 {
00381     PRInt32 rv, err;
00382     rv = listen(fd->secret->md.osfd, backlog);
00383     if (rv < 0)  {
00384         err = sock_errno();
00385         _PR_MD_MAP_DEFAULT_ERROR(err);
00386     }
00387     return(rv);
00388 }
00389 
00390 
00391 PRInt32
00392 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 
00393             PRIntervalTime timeout)
00394 {
00395     PRInt32 osfd = fd->secret->md.osfd;
00396     PRInt32 rv, err;
00397     PRThread *me = _PR_MD_CURRENT_THREAD();
00398 
00399     while ((rv = recv(osfd,buf,amount,flags)) == -1)
00400     {
00401         err = sock_errno();
00402         if ((err == EWOULDBLOCK)) {
00403             if (fd->secret->nonblocking) {
00404                 break;
00405             }
00406             if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
00407                 goto done;
00408         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
00409             continue;
00410         } else {
00411             break;
00412         }
00413     }
00414     if (rv < 0) {
00415         _PR_MD_MAP_RECV_ERROR(err);
00416     }
00417 done:
00418     return(rv);
00419 }
00420 
00421 PRInt32
00422 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
00423             PRIntervalTime timeout)
00424 {
00425     PRInt32 osfd = fd->secret->md.osfd;
00426     PRInt32 rv, err;
00427     PRThread *me = _PR_MD_CURRENT_THREAD();
00428 
00429     while ((rv = send(osfd,buf,amount,flags)) == -1)
00430     {
00431         err = sock_errno();
00432         if ((err == EWOULDBLOCK)) {
00433             if (fd->secret->nonblocking) {
00434                 break;
00435             }
00436             if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
00437                 goto done;
00438         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
00439             continue;
00440         } else {
00441             break;
00442         }
00443     }
00444 
00445      /*
00446       * optimization; if bytes sent is less than "amount" call
00447       * select before returning. This is because it is likely that
00448       * the next send() call will return EWOULDBLOCK.
00449       */
00450     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
00451         && (timeout != PR_INTERVAL_NO_WAIT))
00452     {
00453         if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
00454             rv = -1;
00455             goto done;
00456         }
00457     }
00458     if (rv < 0) {
00459         _PR_MD_MAP_SEND_ERROR(err);
00460     }
00461 done:
00462     return(rv);
00463 }
00464 
00465 PRInt32
00466 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
00467               const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
00468 {
00469     PRInt32 osfd = fd->secret->md.osfd;
00470     PRInt32 rv, err;
00471     PRThread *me = _PR_MD_CURRENT_THREAD();
00472     while ((rv = sendto(osfd, buf, amount, flags,
00473            (struct sockaddr *) addr, addrlen)) == -1)
00474     {
00475         err = sock_errno();
00476         if ((err == EWOULDBLOCK))
00477         {
00478             if (fd->secret->nonblocking) {
00479                 break;
00480             }
00481             if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
00482                 goto done;
00483         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
00484             continue;
00485         } else {
00486             break;
00487         }
00488     }
00489     if (rv < 0) {
00490         _PR_MD_MAP_SENDTO_ERROR(err);
00491     }
00492 done:
00493     return(rv);
00494 }
00495 
00496 PRInt32
00497 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
00498                 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
00499 {
00500     PRInt32 osfd = fd->secret->md.osfd;
00501     PRInt32 rv, err;
00502     PRThread *me = _PR_MD_CURRENT_THREAD();
00503 
00504     while( (*addrlen = PR_NETADDR_SIZE(addr)),
00505            ((rv = recvfrom(osfd, buf, amount, flags,
00506              (struct sockaddr *) addr, (int *)addrlen)) == -1))
00507     {
00508         err = sock_errno();
00509         if ((err == EWOULDBLOCK)) {
00510             if (fd->secret->nonblocking) {
00511                 break;
00512             }
00513             if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
00514                 goto done;
00515         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
00516             continue;
00517         } else {
00518             break;
00519         }
00520     }
00521     if (rv < 0) {
00522         _PR_MD_MAP_RECVFROM_ERROR(err);
00523     }
00524 done:
00525     return(rv);
00526 }
00527 
00528 PRInt32
00529 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
00530               PRIntervalTime timeout)
00531 {
00532     PRInt32 rv, err;
00533     PRThread *me = _PR_MD_CURRENT_THREAD();
00534     PRInt32 index, amount = 0;
00535     PRInt32 osfd = fd->secret->md.osfd;
00536 
00537      /*
00538       * Calculate the total number of bytes to be sent; needed for
00539       * optimization later.
00540       * We could avoid this if this number was passed in; but it is
00541       * probably not a big deal because iov_size is usually small (less than
00542       * 3)
00543       */
00544     if (!fd->secret->nonblocking) {
00545         for (index=0; index<iov_size; index++) {
00546             amount += iov[index].iov_len;
00547         }
00548     }
00549 
00550     while ((rv = _OS2_WRITEV(osfd, (const struct iovec*)iov, iov_size)) == -1) {
00551         err = sock_errno();
00552         if ((err == EWOULDBLOCK))    {
00553             if (fd->secret->nonblocking) {
00554                 break;
00555             }
00556             if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
00557                 goto done;
00558         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
00559             continue;
00560         } else {
00561             break;
00562         }
00563     }
00564 
00565      /*
00566       * optimization; if bytes sent is less than "amount" call
00567       * select before returning. This is because it is likely that
00568       * the next writev() call will return EWOULDBLOCK.
00569       */
00570     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
00571           && (timeout != PR_INTERVAL_NO_WAIT)) {
00572         if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
00573             rv = -1;
00574             goto done;
00575         }
00576     }
00577     if (rv < 0) {
00578         _PR_MD_MAP_WRITEV_ERROR(err);
00579     }
00580 done:
00581     return(rv);
00582 }
00583 
00584 PRInt32
00585 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
00586 {
00587     PRInt32 rv;
00588 
00589     rv = shutdown(fd->secret->md.osfd, how);
00590     if (rv < 0)
00591         _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno());
00592     return rv;
00593 }
00594 
00595 #ifndef XP_OS2_VACPP
00596 PRInt32
00597 _PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd)
00598 {
00599     PRInt32 rv, err;
00600 
00601     rv = socketpair(af, type, flags, osfd);
00602     if (rv < 0) {
00603         err = _MD_ERRNO();
00604         _PR_MD_MAP_SOCKETPAIR_ERROR(err);
00605     }
00606     return rv;
00607 }
00608 #endif
00609 
00610 PRStatus
00611 _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
00612 {
00613     PRInt32 rv, err;
00614 
00615     rv = getsockname(fd->secret->md.osfd,
00616                      (struct sockaddr *) addr, (int *)addrlen);
00617     if (rv < 0) {
00618         err = sock_errno();
00619         _PR_MD_MAP_GETSOCKNAME_ERROR(err);
00620     }
00621     return rv==0?PR_SUCCESS:PR_FAILURE;
00622 }
00623 
00624 PRStatus
00625 _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
00626 {
00627     PRInt32 rv, err;
00628 
00629     rv = getpeername(fd->secret->md.osfd,
00630                      (struct sockaddr *) addr, (int *)addrlen);
00631     if (rv < 0) {
00632         err = sock_errno();
00633         _PR_MD_MAP_GETPEERNAME_ERROR(err);
00634     }
00635     return rv==0?PR_SUCCESS:PR_FAILURE;
00636 }
00637 
00638 PRStatus
00639 _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
00640                   char* optval, PRInt32* optlen)
00641 {
00642     PRInt32 rv, err;
00643 
00644     rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen);
00645     if (rv < 0) {
00646         err = sock_errno();
00647         _PR_MD_MAP_GETSOCKOPT_ERROR(err);
00648     }
00649     return rv==0?PR_SUCCESS:PR_FAILURE;
00650 }
00651 
00652 PRStatus
00653 _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
00654                   const char* optval, PRInt32 optlen)
00655 {
00656     PRInt32 rv, err;
00657 
00658     rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
00659     if (rv < 0) {
00660         err = sock_errno();
00661         _PR_MD_MAP_SETSOCKOPT_ERROR(err);
00662     }
00663     return rv==0?PR_SUCCESS:PR_FAILURE;
00664 }
00665 
00666 void
00667 _MD_MakeNonblock(PRFileDesc *fd)
00668 {
00669     PRInt32 osfd = fd->secret->md.osfd;
00670     PRInt32 err;
00671     PRUint32  one = 1;
00672     
00673     if (osfd <= 2) {
00674         /* Don't mess around with stdin, stdout or stderr */
00675         return;
00676     }
00677 
00678     err = _OS2_IOCTL( osfd, FIONBIO, (char *) &one, sizeof(one));
00679     if ( err != 0 )
00680     {
00681         err = sock_errno();
00682         _PR_MD_MAP_SOCKET_ERROR(err);
00683     }
00684 }