fd_kern.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:51k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* ==== fd_kern.c ============================================================
  2.  * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *  This product includes software developed by Chris Provenzano.
  16.  * 4. The name of Chris Provenzano may not be used to endorse or promote 
  17.  *   products derived from this software without specific prior written
  18.  *   permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
  21.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY 
  24.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  26.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  28.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  30.  * SUCH DAMAGE.
  31.  *
  32.  * Description : Deals with the valid kernel fds.
  33.  *
  34.  *  1.00 93/09/27 proven
  35.  *      -Started coding this file.
  36.  *
  37.  * 1.01 93/11/13 proven
  38.  * -The functions readv() and writev() added.
  39.  */
  40. #ifndef lint
  41. static const char rcsid[] = "$Id$";
  42. #endif
  43. #include "config.h"
  44. #include <pthread.h>
  45. #include <unistd.h>
  46. #include <sys/compat.h>
  47. #include <sys/types.h>
  48. #include <sys/socket.h>
  49. #include <sys/stat.h>
  50. #include <sys/time.h>
  51. #include <sys/uio.h>
  52. #include <stdarg.h>
  53. #include <signal.h>
  54. #include <fcntl.h>
  55. #include <errno.h>
  56. #include <pthread/posix.h>
  57. #include <string.h>
  58. #if defined (HAVE_SYSCALL_SENDTO) && !defined (HAVE_SYSCALL_SEND)
  59. pthread_ssize_t machdep_sys_send (int fd, const void *msg, size_t len,
  60.  int flags)
  61. {
  62.   return machdep_sys_sendto (fd, msg, len, flags,
  63.      (const struct sockaddr *) 0, 0);
  64. }
  65. #endif
  66. #if defined (HAVE_SYSCALL_RECVFROM) && !defined (HAVE_SYSCALL_RECV)
  67. pthread_ssize_t machdep_sys_recv (int fd, void *buf, size_t len, int flags)
  68. {
  69.   return machdep_sys_recvfrom (fd, buf, len, flags,
  70.        (struct sockaddr *) 0, (int *) 0);
  71. }
  72. #endif
  73. /* ==========================================================================
  74.  * Check if there is any signal with must be handled.  Added by Monty
  75.  * This could be somewhat system dependent but it should work.
  76.  */
  77. static int fd_check_if_pending_signal(struct pthread *pthread)
  78. {
  79.   int i;
  80.   unsigned long *pending,*mask;
  81.   if (!pthread->sigcount)
  82.     return 0;
  83.   pending= (unsigned long*) &pthread->sigpending;
  84.   mask=    (unsigned long*) &pthread->sigmask;
  85.   for (i=0 ; i < sizeof(pthread->sigpending)/sizeof(unsigned long); i++)
  86.   {
  87.     if (*pending && (*mask ^ (unsigned) ~0L))
  88.       return 1;
  89.     pending++;
  90.     mask++;
  91.   }
  92.   return 0;
  93. }
  94. /* ==========================================================================
  95.  * Variables used by both fd_kern_poll and fd_kern_wait
  96.  */
  97. struct pthread_queue fd_wait_read = PTHREAD_QUEUE_INITIALIZER;
  98. struct pthread_queue fd_wait_write = PTHREAD_QUEUE_INITIALIZER;
  99. struct pthread_queue fd_wait_select = PTHREAD_QUEUE_INITIALIZER;
  100. static struct timeval __fd_kern_poll_timeout = { 0, 0 }; /* Moved by monty */
  101. extern struct timeval __fd_kern_wait_timeout;
  102. extern volatile sig_atomic_t sig_to_process;
  103. /*
  104.  * ==========================================================================
  105.  * Do a select if there is someting to wait for.
  106.  * This is to a combination of the old fd_kern_poll() and fd_kern_wait()
  107.  * Return 1 if nothing to do.
  108.  */
  109. static int fd_kern_select(struct timeval *timeout)
  110. {
  111.   fd_set fd_set_read, fd_set_write, fd_set_except;
  112.   struct pthread *pthread, *deq;
  113.   int count, i;
  114.   if (!fd_wait_read.q_next && !fd_wait_write.q_next && !fd_wait_select.q_next)
  115.     return 1; /* Nothing to do */
  116.   FD_ZERO(&fd_set_read);
  117.   FD_ZERO(&fd_set_write);
  118.   FD_ZERO(&fd_set_except);
  119.   for (pthread = fd_wait_read.q_next; pthread; pthread = pthread->next)
  120.     FD_SET(pthread->data.fd.fd, &fd_set_read);
  121.   for (pthread = fd_wait_write.q_next; pthread; pthread = pthread->next)
  122.     FD_SET(pthread->data.fd.fd, &fd_set_write);
  123.   for (pthread = fd_wait_select.q_next; pthread; pthread = pthread->next)
  124.   {
  125.     for (i = 0; i < pthread->data.select_data->nfds; i++) {
  126.       if (FD_ISSET(i, &pthread->data.select_data->exceptfds))
  127. FD_SET(i, &fd_set_except);
  128.       if (FD_ISSET(i, &pthread->data.select_data->writefds))
  129. FD_SET(i, &fd_set_write);
  130.       if (FD_ISSET(i, &pthread->data.select_data->readfds))
  131. FD_SET(i, &fd_set_read);
  132.     }
  133.   }
  134.   /* Turn off interrupts for real while we set the timer.  */
  135.   if (timeout == &__fd_kern_wait_timeout)
  136.   { /* from fd_kern_wait() */
  137.     sigset_t sig_to_block, oset;
  138.     sigfillset(&sig_to_block);
  139.     machdep_sys_sigprocmask(SIG_BLOCK, &sig_to_block, &oset);
  140.     machdep_unset_thread_timer(NULL); 
  141.     __fd_kern_wait_timeout.tv_usec = 0;
  142.     __fd_kern_wait_timeout.tv_sec = (sig_to_process) ? 0 : 3600;
  143.     machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
  144.   }
  145.     /*
  146.      * There is a small but finite chance that an interrupt will
  147.      * occure between the unblock and the select. Because of this
  148.      * sig_handler_real() sets the value of __fd_kern_wait_timeout
  149.      * to zero causing the select to do a poll instead of a wait.
  150.      */
  151.   while ((count = machdep_sys_select(dtablesize, &fd_set_read,
  152.      &fd_set_write, &fd_set_except,
  153.      timeout)) < OK)
  154.   {
  155.     if (count == -EINTR)
  156.       return 0;
  157.     PANIC();
  158.   }
  159.   for (pthread = fd_wait_read.q_next; pthread; ) {
  160.     if (count && FD_ISSET(pthread->data.fd.fd, &fd_set_read) ||
  161. fd_check_if_pending_signal(pthread))
  162.     {
  163.       if (FD_ISSET(pthread->data.fd.fd, &fd_set_read))
  164. count--;
  165.       deq = pthread;
  166.       pthread = pthread->next;
  167.       pthread_queue_remove(&fd_wait_read, deq);
  168.       if (SET_PF_DONE_EVENT(deq) == OK) {
  169. pthread_prio_queue_enq(pthread_current_prio_queue, deq);
  170. deq->state = PS_RUNNING;
  171.       }
  172.       continue;
  173.     } 
  174.     pthread = pthread->next;
  175.   }
  176.   for (pthread = fd_wait_write.q_next; pthread; ) {
  177.     if (count && FD_ISSET(pthread->data.fd.fd, &fd_set_write) ||
  178. fd_check_if_pending_signal(pthread))
  179.     {
  180.       if (FD_ISSET(pthread->data.fd.fd, &fd_set_read))
  181. count--;
  182.       deq = pthread;
  183.       pthread = pthread->next;
  184.       pthread_queue_remove(&fd_wait_write, deq);
  185.       if (SET_PF_DONE_EVENT(deq) == OK) {
  186. pthread_prio_queue_enq(pthread_current_prio_queue, deq);
  187. deq->state = PS_RUNNING;
  188.       }
  189.       continue;
  190.     } 
  191.     pthread = pthread->next;
  192.   }
  193.   for (pthread = fd_wait_select.q_next; pthread; )
  194.   {
  195.     int found_one=0; /* Loop fixed by monty */
  196.     if (count)
  197.     {
  198.       fd_set tmp_readfds, tmp_writefds, tmp_exceptfds;
  199.       memcpy(&tmp_readfds, &pthread->data.select_data->readfds,
  200.      sizeof(fd_set));
  201.       memcpy(&tmp_writefds, &pthread->data.select_data->writefds,
  202.      sizeof(fd_set));
  203.       memcpy(&tmp_exceptfds, &pthread->data.select_data->exceptfds,
  204.      sizeof(fd_set));
  205.       for (i = 0; i < pthread->data.select_data->nfds; i++) {
  206. if (FD_ISSET(i, &tmp_exceptfds))
  207. {
  208.   if (! FD_ISSET(i, &fd_set_except))
  209.     FD_CLR(i, &tmp_exceptfds);
  210.   else
  211.     found_one=1;
  212. }
  213. if (FD_ISSET(i, &tmp_writefds))
  214. {
  215.   if (! FD_ISSET(i, &fd_set_write))
  216.     FD_CLR(i, &tmp_writefds);
  217.   else 
  218.     found_one=1;
  219. }
  220. if (FD_ISSET(i, &tmp_readfds))
  221. {
  222.   if (! FD_ISSET(i, &fd_set_read))
  223.     FD_CLR(i, &tmp_readfds);
  224.   else
  225.     found_one=1;
  226. }
  227.       }
  228.       if (found_one)
  229.       {
  230. memcpy(&pthread->data.select_data->readfds, &tmp_readfds,
  231.        sizeof(fd_set));
  232. memcpy(&pthread->data.select_data->writefds, &tmp_writefds,
  233.        sizeof(fd_set));
  234. memcpy(&pthread->data.select_data->exceptfds, &tmp_exceptfds,
  235.        sizeof(fd_set));
  236.       }
  237.     }
  238.     if (found_one || fd_check_if_pending_signal(pthread))
  239.     {
  240.       deq = pthread;
  241.       pthread = pthread->next;
  242.       pthread_queue_remove(&fd_wait_select, deq);
  243.       if (SET_PF_DONE_EVENT(deq) == OK) {
  244. pthread_prio_queue_enq(pthread_current_prio_queue, deq);
  245. deq->state = PS_RUNNING;
  246.       }
  247.     } else {
  248.       pthread = pthread->next;
  249.     }
  250.   }
  251.   return 0;
  252. }
  253. /* ==========================================================================
  254.  * fd_kern_poll()
  255.  *
  256.  * Called only from context_switch(). The kernel must be locked.
  257.  *
  258.  * This function uses a linked list of waiting pthreads, NOT a queue.
  259.  */ 
  260. void fd_kern_poll()
  261. {
  262.   fd_kern_select(&__fd_kern_poll_timeout);
  263. }
  264. /* ==========================================================================
  265.  * fd_kern_wait()
  266.  *
  267.  * Called when there is no active thread to run.
  268.  */
  269. void fd_kern_wait()
  270. {
  271.   if (fd_kern_select(&__fd_kern_wait_timeout))
  272.     /* No threads, waiting on I/O, do a sigsuspend */
  273.     sig_handler_pause();
  274. }
  275. /* ==========================================================================
  276.  * Special Note: All operations return the errno as a negative of the errno
  277.  * listed in errno.h
  278.  * ======================================================================= */
  279. /* ==========================================================================
  280.  * read()
  281.  */
  282. pthread_ssize_t __fd_kern_read(union fd_data fd_data, int flags, void *buf,
  283.   size_t nbytes, struct timespec * timeout)
  284. {
  285.   int fd = fd_data.i;
  286.   int ret;
  287.   pthread_run->sighandled=0; /* Added by monty */
  288.   while ((ret = machdep_sys_read(fd, buf, nbytes)) < OK) { 
  289.     if (!(flags & __FD_NONBLOCK) &&
  290. ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  291.       pthread_sched_prevent();
  292.       /* queue pthread for a FDR_WAIT */
  293.       SET_PF_WAIT_EVENT(pthread_run);
  294.       pthread_run->data.fd.fd = fd;
  295.       pthread_queue_enq(&fd_wait_read, pthread_run);
  296.       if (timeout) {
  297. /* get current time */
  298. struct timespec current_time;
  299. machdep_gettimeofday(&current_time);
  300. sleep_schedule(&current_time, timeout);
  301. SET_PF_AT_CANCEL_POINT(pthread_run);
  302. pthread_resched_resume(PS_FDR_WAIT);
  303. CLEAR_PF_AT_CANCEL_POINT(pthread_run);
  304. /* We're awake */
  305. pthread_sched_prevent();
  306. if (sleep_cancel(pthread_run) == NOTOK) {
  307.   CLEAR_PF_DONE_EVENT(pthread_run);
  308.   pthread_sched_resume();
  309.   SET_ERRNO(ETIMEDOUT);
  310.   ret= NOTOK;
  311.   break;
  312. }
  313. pthread_sched_resume();
  314.       } else {
  315. SET_PF_AT_CANCEL_POINT(pthread_run);
  316. pthread_resched_resume(PS_FDR_WAIT);
  317. CLEAR_PF_AT_CANCEL_POINT(pthread_run);
  318.       }
  319.       CLEAR_PF_DONE_EVENT(pthread_run);
  320.       if (pthread_run->sighandled) /* Added by monty */
  321.       { /* We where aborted */
  322. SET_ERRNO(EINTR);
  323. ret= NOTOK;
  324. break;
  325.       }
  326.     } else {
  327.       SET_ERRNO(-ret); 
  328.       ret = NOTOK; 
  329.       break;
  330.     }
  331.   }
  332.   return(ret);
  333. }
  334. /* ==========================================================================
  335.  * readv()
  336.  */
  337. int __fd_kern_readv(union fd_data fd_data, int flags, const struct iovec *iov,
  338.     int iovcnt, struct timespec * timeout)
  339. {
  340.   int fd = fd_data.i;
  341.   int ret;
  342.   pthread_run->sighandled=0; /* Added by monty */
  343.   while ((ret = machdep_sys_readv(fd, iov, iovcnt)) < OK) { 
  344.     if (!(flags & __FD_NONBLOCK) &&
  345. ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  346.       pthread_sched_prevent();
  347.       /* queue pthread for a FDR_WAIT */
  348.       pthread_run->data.fd.fd = fd;
  349.       SET_PF_WAIT_EVENT(pthread_run);
  350.       pthread_queue_enq(&fd_wait_read, pthread_run);
  351.       if (timeout) {
  352. /* get current time */
  353. struct timespec current_time;
  354. machdep_gettimeofday(&current_time);
  355. sleep_schedule(&current_time, timeout);
  356. SET_PF_AT_CANCEL_POINT(pthread_run);
  357. pthread_resched_resume(PS_FDW_WAIT);
  358. CLEAR_PF_AT_CANCEL_POINT(pthread_run);
  359. /* We're awake */
  360. pthread_sched_prevent();
  361. if (sleep_cancel(pthread_run) == NOTOK) {
  362.   CLEAR_PF_DONE_EVENT(pthread_run);
  363.   pthread_sched_resume();
  364.   SET_ERRNO(ETIMEDOUT);
  365.   ret = NOTOK;
  366.   break;
  367. }
  368. pthread_sched_resume();
  369.       } else {
  370. SET_PF_AT_CANCEL_POINT(pthread_run);
  371. pthread_resched_resume(PS_FDW_WAIT);
  372. CLEAR_PF_AT_CANCEL_POINT(pthread_run);
  373.       }
  374.       CLEAR_PF_DONE_EVENT(pthread_run);
  375.       if (pthread_run->sighandled) /* Added by monty */
  376.       { /* We where aborted */
  377. SET_ERRNO(EINTR);
  378. ret= NOTOK;
  379. break;
  380.       }
  381.     } else {
  382.       SET_ERRNO(-ret);
  383.       ret = NOTOK;
  384.       break;
  385.     }
  386.   }
  387.   return(ret);
  388. }
  389. /* ==========================================================================
  390.  * write()
  391.  */
  392. pthread_ssize_t __fd_kern_write(union fd_data fd_data, int flags,
  393.  const void *buf, size_t nbytes, struct timespec * timeout)
  394. {
  395.   int fd = fd_data.i;
  396.   int ret;
  397.   pthread_run->sighandled=0; /* Added by monty */
  398.   while ((ret = machdep_sys_write(fd, buf, nbytes)) < OK) { 
  399.     if (!(flags & __FD_NONBLOCK) &&
  400. ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  401.       pthread_sched_prevent();
  402.       /* queue pthread for a FDW_WAIT */
  403.       pthread_run->data.fd.fd = fd;
  404.       SET_PF_WAIT_EVENT(pthread_run);
  405.       pthread_queue_enq(&fd_wait_write, pthread_run);
  406.       if (timeout) {
  407. /* get current time */
  408. struct timespec current_time;
  409. machdep_gettimeofday(&current_time);
  410. sleep_schedule(&current_time, timeout);
  411. pthread_resched_resume(PS_FDW_WAIT);
  412. /* We're awake */
  413. pthread_sched_prevent();
  414. if (sleep_cancel(pthread_run) == NOTOK) {
  415.   CLEAR_PF_DONE_EVENT(pthread_run);
  416.   pthread_sched_resume();
  417.   SET_ERRNO(ETIMEDOUT);
  418.   ret = NOTOK;
  419.   break;
  420. }
  421. pthread_sched_resume();
  422.       } else {
  423. pthread_resched_resume(PS_FDW_WAIT);
  424.       }
  425.       CLEAR_PF_DONE_EVENT(pthread_run);
  426.       if (pthread_run->sighandled) /* Added by monty */
  427.       { /* We where aborted */
  428. SET_ERRNO(EINTR);
  429. ret= NOTOK;
  430. break;
  431.       }
  432.     } else {
  433.       SET_ERRNO(-ret);
  434.       ret = NOTOK;
  435.       break;
  436.     }
  437.   }
  438.   return(ret);
  439. }
  440. /* ==========================================================================
  441.  * writev()
  442.  */
  443. int __fd_kern_writev(union fd_data fd_data, int flags, const struct iovec *iov,
  444.   int iovcnt, struct timespec * timeout)
  445. {
  446. int fd = fd_data.i;
  447. int ret;
  448.     pthread_run->sighandled=0; /* Added by monty */
  449.     while ((ret = machdep_sys_writev(fd, iov, iovcnt)) < OK) { 
  450. if (!(flags & __FD_NONBLOCK) &&
  451.           ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  452. pthread_sched_prevent();
  453. /* queue pthread for a FDW_WAIT */
  454. pthread_run->data.fd.fd = fd;
  455. SET_PF_WAIT_EVENT(pthread_run);
  456. pthread_queue_enq(&fd_wait_write, pthread_run);
  457. if (timeout) {
  458. /* get current time */
  459. struct timespec current_time;
  460. machdep_gettimeofday(&current_time);
  461. sleep_schedule(&current_time, timeout);
  462. pthread_resched_resume(PS_FDW_WAIT);
  463. /* We're awake */
  464. pthread_sched_prevent();
  465. if (sleep_cancel(pthread_run) == NOTOK) {
  466. CLEAR_PF_DONE_EVENT(pthread_run);
  467. pthread_sched_resume();
  468. SET_ERRNO(ETIMEDOUT);
  469. ret = NOTOK;
  470. break;
  471. }
  472. pthread_sched_resume();
  473. } else {
  474. pthread_resched_resume(PS_FDW_WAIT);
  475. }
  476. CLEAR_PF_DONE_EVENT(pthread_run);
  477. if (pthread_run->sighandled) /* Added by monty */
  478. { /* We where aborted */
  479.   SET_ERRNO(EINTR);
  480.   ret= NOTOK;
  481.   break;
  482. }
  483.         } else {
  484.             break;
  485.         }
  486.     }
  487.     return(ret);
  488. }
  489. /* ==========================================================================
  490.  * For blocking version we really should set an interrupt
  491.  * fcntl()
  492.  */
  493. int __fd_kern_fcntl(union fd_data fd_data, int flags, int cmd, int arg)
  494. {
  495. int fd = fd_data.i;
  496. return(machdep_sys_fcntl(fd, cmd, arg));
  497. }
  498. /* ==========================================================================
  499.  * close()
  500.  */
  501. int __fd_kern_close(union fd_data fd_data, int flags)
  502. {
  503. int fd = fd_data.i;
  504. return(machdep_sys_close(fd));
  505. }
  506. /* ==========================================================================
  507.  * lseek()
  508.  * Assume that error number is in the range 0- 255 to get bigger
  509.  * range of seek. ; Monty
  510.  */
  511. off_t __fd_kern_lseek(union fd_data fd_data, int f, off_t offset, int whence)
  512. {
  513. int fd = fd_data.i;
  514. extern off_t machdep_sys_lseek(int, off_t, int);
  515. off_t ret=machdep_sys_lseek(fd, offset, whence);
  516. if ((long) ret < 0L && (long) ret >=  -255L)
  517. {
  518.   SET_ERRNO(ret);
  519.   ret= NOTOK;
  520. }
  521. return ret;
  522. }
  523. /*
  524.  * File descriptor operations
  525.  */
  526. extern machdep_sys_close();
  527. /* Normal file operations */
  528. static struct fd_ops __fd_kern_ops = {
  529. __fd_kern_write, __fd_kern_read, __fd_kern_close, __fd_kern_fcntl,
  530. __fd_kern_writev, __fd_kern_readv, __fd_kern_lseek, 1
  531. };
  532. /* NFS file opperations */
  533. /* FIFO file opperations */
  534. /* Device operations */
  535. /* ==========================================================================
  536.  * open()
  537.  *
  538.  * Because open could potentially block opening a file from a remote
  539.  * system, we want to make sure the call will timeout. We then try and open
  540.  * the file, and stat the file to determine what operations we should
  541.  * associate with the fd.
  542.  *
  543.  * This is not done yet
  544.  *
  545.  * A regular file on the local system needs no special treatment.
  546.  */
  547. int open(const char *path, int flags, ...)
  548. {
  549. int fd, mode, fd_kern;
  550. struct stat stat_buf;
  551. va_list ap;
  552. /* If pthread scheduling == FIFO set a virtual timer */
  553. if (flags & O_CREAT) {
  554. va_start(ap, flags);
  555. mode = va_arg(ap, int);
  556. va_end(ap);
  557. } else {
  558. mode = 0;
  559. }
  560. if (!((fd = fd_allocate()) < OK)) {
  561. fd_table[fd]->flags = flags;
  562. flags |= __FD_NONBLOCK;
  563. if (!((fd_kern = machdep_sys_open(path, flags, mode)) < OK)) {
  564. /* fstat the file to determine what type it is */
  565. if (machdep_sys_fstat(fd_kern, &stat_buf)) {
  566. PANIC();
  567. }
  568. if (S_ISREG(stat_buf.st_mode)) {
  569. fd_table[fd]->ops = &(__fd_kern_ops);
  570. fd_table[fd]->type = FD_HALF_DUPLEX;
  571. } else {
  572. fd_table[fd]->ops = &(__fd_kern_ops);
  573. fd_table[fd]->type = FD_FULL_DUPLEX;
  574. }
  575. fd_table[fd]->fd.i = fd_kern; 
  576. return(fd);
  577. }
  578. fd_table[fd]->count = 0;
  579. SET_ERRNO(-fd_kern);
  580. }
  581. return(NOTOK);
  582. }
  583. /* ==========================================================================
  584.  * create()
  585.  */
  586. int create(const char *path, mode_t mode)
  587. {
  588. return creat (path, mode);
  589. }
  590. /* ==========================================================================
  591.  * creat()
  592.  */
  593. #undef creat
  594. int creat(const char *path, mode_t mode)
  595. {
  596. return open (path, O_CREAT | O_TRUNC | O_WRONLY, mode);
  597. }
  598. /* ==========================================================================
  599.  * fchown()
  600.  */
  601. int fchown(int fd, uid_t owner, gid_t group)
  602. {
  603. int ret;
  604. if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
  605. if ((ret = machdep_sys_fchown(fd_table[fd]->fd.i, owner, group)) < OK) {
  606. SET_ERRNO(-ret);
  607. ret = NOTOK;
  608. }
  609. fd_unlock(fd, FD_WRITE);
  610. }
  611. return(ret);
  612. }
  613. /* ==========================================================================
  614.  * fchmod()
  615.  */
  616. int fchmod(int fd, mode_t mode)
  617. {
  618. int ret;
  619. if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
  620. if ((ret = machdep_sys_fchmod(fd_table[fd]->fd.i, mode)) < OK) {
  621. SET_ERRNO(-ret);
  622. ret = NOTOK;
  623. }
  624. fd_unlock(fd, FD_WRITE);
  625. }
  626. return(ret);
  627. }
  628. /* ==========================================================================
  629.  * ftruncate()
  630.  */
  631. int ftruncate(int fd, off_t length)
  632. {
  633. int ret;
  634. if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
  635. if ((ret = machdep_sys_ftruncate(fd_table[fd]->fd.i, length)) < OK) {
  636. SET_ERRNO(-ret);
  637. ret = NOTOK;
  638. }
  639. fd_unlock(fd, FD_WRITE);
  640. }
  641. return(ret);
  642. }
  643. #if defined (HAVE_SYSCALL_FLOCK)
  644. /* ==========================================================================
  645.  * flock()
  646.  *
  647.  *  Added (mevans)
  648.  */
  649. int flock(int fd, int operation)
  650. {
  651.   int ret;
  652.   if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  653.     if ((ret = machdep_sys_flock(fd_table[fd]->fd.i,
  654.  operation)) < OK) {
  655.       SET_ERRNO(-ret);
  656.       ret = NOTOK;
  657.     }
  658.     fd_unlock(fd, FD_RDWR);
  659.   }
  660.   return(ret);
  661. }
  662. #endif
  663. /* ==========================================================================
  664.  * pipe()
  665.  */
  666. int pipe(int fds[2])
  667. {
  668. int kfds[2];
  669. int ret;
  670. if ((fds[0] = fd_allocate()) >= OK) {
  671. if ((fds[1] = fd_allocate()) >= OK) {
  672. if ((ret = machdep_sys_pipe(kfds)) >= OK) {
  673. fd_table[fds[0]]->flags = machdep_sys_fcntl(kfds[0], F_GETFL, NULL);
  674. machdep_sys_fcntl(kfds[0], F_SETFL, fd_table[fds[0]]->flags | __FD_NONBLOCK);
  675. fd_table[fds[1]]->flags = machdep_sys_fcntl(kfds[1], F_GETFL, NULL);
  676. machdep_sys_fcntl(kfds[1], F_SETFL, fd_table[fds[1]]->flags | __FD_NONBLOCK);
  677. fd_table[fds[0]]->ops = &(__fd_kern_ops);
  678. fd_table[fds[1]]->ops = &(__fd_kern_ops);
  679. /* Not really full duplex but ... */
  680. fd_table[fds[0]]->type = FD_FULL_DUPLEX;
  681. fd_table[fds[1]]->type = FD_FULL_DUPLEX;
  682. fd_table[fds[0]]->fd.i = kfds[0];
  683. fd_table[fds[1]]->fd.i = kfds[1];
  684. return(OK);
  685. } else {
  686. SET_ERRNO(-ret);
  687. }
  688. fd_table[fds[1]]->count = 0;
  689. }
  690. fd_table[fds[0]]->count = 0;
  691. }
  692. return(NOTOK);
  693. }
  694. /* ==========================================================================
  695.  * fd_kern_reset()
  696.  * Change the fcntl blocking flag back to NONBLOCKING. This should only
  697.  * be called after a fork.
  698.  */
  699. void fd_kern_reset(int fd)
  700. {
  701. switch (fd_table[fd]->type) {
  702. case FD_TEST_HALF_DUPLEX:
  703. machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL,
  704.           fd_table[fd]->flags | __FD_NONBLOCK);
  705. fd_table[fd]->type = FD_HALF_DUPLEX;
  706. break;
  707. case FD_TEST_FULL_DUPLEX:
  708. machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL,
  709.   fd_table[fd]->flags | __FD_NONBLOCK);
  710. fd_table[fd]->type = FD_FULL_DUPLEX;
  711. break;
  712. default:
  713. break;
  714. }
  715. }
  716. /* ==========================================================================
  717.  * fd_kern_init()
  718.  *
  719.  * Assume the entry is locked before routine is invoked
  720.  *
  721.  * This may change. The problem is setting the fd to nonblocking changes
  722.  * the parents fd too, which may not be the desired result.
  723.  *
  724.  * New added feature: If the fd in question is a tty then we open it again
  725.  * and close the original, this way we don't have to worry about the
  726.  * fd being NONBLOCKING to the outside world.
  727.  */
  728. void fd_kern_init(int fd)
  729. {
  730. if ((fd_table[fd]->flags = machdep_sys_fcntl(fd, F_GETFL, NULL)) >= OK) {
  731. if (isatty_basic(fd)) {
  732. int new_fd;
  733. if ((new_fd = machdep_sys_open(__ttyname_basic(fd), O_RDWR)) >= OK){
  734. if (machdep_sys_dup2(new_fd, fd) == OK) {
  735. /* Should print a warning */
  736. /* Should also set the flags to that of opened outside of
  737. process */
  738. }
  739. machdep_sys_close(new_fd);
  740. }
  741. }
  742. /* We do these things regaurdless of the above results */
  743. machdep_sys_fcntl(fd, F_SETFL, fd_table[fd]->flags | __FD_NONBLOCK);
  744. fd_table[fd]->ops  = &(__fd_kern_ops);
  745. fd_table[fd]->type  = FD_HALF_DUPLEX;
  746. fd_table[fd]->fd.i  = fd;
  747. fd_table[fd]->count = 1;
  748. }
  749. }
  750. /* ==========================================================================
  751.  * fd_kern_gettableentry()
  752.  *
  753.  * Remember only return a a file descriptor that I will modify later.
  754.  * Don't return file descriptors that aren't owned by the child, or don't
  755.  * have kernel operations.
  756.  */
  757. static int fd_kern_gettableentry(const int child, int fd)
  758. {
  759. int i;
  760. for (i = 0; i < dtablesize; i++) {
  761. if (fd_table[i]) {
  762. if (fd_table[i]->fd.i == fd) {
  763. if (child) {
  764. if ((fd_table[i]->type != FD_TEST_HALF_DUPLEX) &&
  765.         (fd_table[i]->type != FD_TEST_FULL_DUPLEX)) {
  766. continue;
  767. }
  768. } else {
  769. if ((fd_table[i]->type == FD_NT) ||
  770.                 (fd_table[i]->type == FD_NIU)) {
  771. continue;
  772. }
  773. }
  774. /* Is it a kernel fd ? */
  775. if ((!fd_table[i]->ops) || 
  776.   (fd_table[i]->ops->use_kfds != 1)) {
  777. continue;
  778. }
  779. return(i);
  780. }
  781. }
  782. }
  783. return(NOTOK);
  784. }
  785. /* ==========================================================================
  786.  * fd_kern_exec()
  787.  *
  788.  * Fixup the fd_table such that (fd == fd_table[fd]->fd.i) this way
  789.  * the new immage will be OK.
  790.  *
  791.  * Only touch those that won't be used by the parent if we're in a child
  792.  * otherwise fixup all.
  793.  *
  794.  * Returns:
  795.  * 0 no fixup necessary
  796.  * 1 fixup without problems
  797.  * 2 failed fixup on some descriptors, and clobbered them.
  798.  */
  799. int fd_kern_exec(const int child)
  800. {
  801. int ret = 0;
  802. int fd, i;
  803. for (fd = 0; fd < dtablesize; fd++) {
  804. if (fd_table[fd] == NULL) {
  805. continue;
  806. }
  807. /* Is the fd already in use ? */
  808. if (child) {
  809. if ((fd_table[fd]->type != FD_TEST_HALF_DUPLEX) &&
  810.       (fd_table[fd]->type != FD_TEST_FULL_DUPLEX)) {
  811. continue;
  812. }
  813. } else {
  814. if ((fd_table[fd]->type == FD_NT) ||
  815.               (fd_table[fd]->type == FD_NIU)) {
  816. continue;
  817. }
  818. }
  819. /* Is it a kernel fd ? */
  820. if ((!fd_table[fd]->ops) || 
  821.   (fd_table[fd]->ops->use_kfds != 1)) {
  822. continue;
  823. }
  824. /* Does it match ? */
  825. if (fd_table[fd]->fd.i == fd) {
  826. continue;
  827. }
  828. /* OK, fixup entry: Read comments before changing. This isn't obvious */ 
  829. /* i is the real file descriptor fd currently represents */
  830. if (((i = fd_table[fd]->fd.i) >= dtablesize) || (i < 0)) {
  831. /* This should never happen */
  832. PANIC();
  833. }
  834. /*
  835.  * if the real file descriptor with the same number as the fake file
  836.  * descriptor number fd is actually in use by the program, we have
  837.          * to move it out of the way
  838.  */
  839. if ((machdep_sys_fcntl(fd, F_GETFL, NULL)) >= OK) {
  840. /* fd is busy */
  841. int j;
  842. /*
  843.  * j is the fake file descriptor that represents the real file
  844.  * descriptor that we want to move. This way the fake file
  845.  * descriptor fd can move its real file descriptor i such that
  846.  * fd == i.
  847.  */
  848. if ((j = fd_kern_gettableentry(child, fd)) >= OK) {
  849. /*
  850.  * Since j represents a fake file descriptor and fd represents
  851.  * a fake file descriptor. If j < fd then a previous pass
  852.  * should have set fd_table[j]->fd.i == j.
  853.  */
  854. if (fd < j) {
  855. if ((fd_table[j]->fd.i = machdep_sys_dup(fd)) < OK) {
  856. /* Close j, there is nothing else we can do */
  857.    fd_table[j]->type = FD_NIU;
  858. ret = 2;
  859. }
  860. } else {
  861. /* This implies fd_table[j]->fd.i != j */
  862. PANIC();
  863. }
  864. }
  865. }
  866. /*
  867.  * Here the real file descriptor i is set to equel the fake file
  868.  * descriptor fd
  869.  */
  870. machdep_sys_dup2(i, fd);
  871. /*
  872.  * Now comes the really complicated part: UNDERSTAND before changing
  873.  *
  874.  * Here are the things this routine wants to do ...
  875.  *
  876.  * Case 1. The real file descriptor has only one fake file descriptor
  877.  * representing it. 
  878.  * fd -> i, fd != i ===>  fd -> fd, close(i)
  879.  * Example fd = 4, i = 2: then close(2), set fd -> i = 4
  880.  * 
  881.  * Case 2. The real file descriptor has more than one fake file
  882.  * descriptor representing it, and this is the first fake file
  883.  * descriptor representing the real file descriptor
  884.  * fd -> i, fd' -> i, fd != i ===> fd -> fd, fd' -> fd, close(i)
  885.  *
  886.  * The problem is achiving the above is very messy and difficult,
  887.  * but I should be able to take a short cut. If fd > i then there
  888.  * will be no need to ever move i, this is because the fake file
  889.  * descriptor foo that we would have wanted to represent the real
  890.  * file descriptor i has already been processed. If fd < i then by
  891.  * moving i to fd all subsequent fake file descriptors fd' should fall
  892.  * into the previous case and won't need aditional adjusting.
  893.  *
  894.  * Does this break the above fd < j check .... It shouldn't because j
  895.  * is a fake file descriptor and if j < fd then j has already moved 
  896.  * its real file descriptor foo such that foo <= j therefore foo < fd
  897.  * and not foo == fd therefor j cannot represent the real 
  898.  * filedescriptor that fd want to move to and be less than fd
  899.  */
  900. if (fd < i) {
  901. fd_table[fd]->fd.i = fd;
  902. machdep_sys_close(i);
  903. }
  904. if (ret < 1) {
  905.  ret = 1;
  906. }
  907. }
  908. }
  909. /* ==========================================================================
  910.  * fd_kern_fork()
  911.  */
  912. void fd_kern_fork()
  913. {
  914. pthread_mutex_t *mutex;
  915. int fd;
  916. for (fd = 0; fd < dtablesize; fd++) {
  917. if (fd_table[fd] == NULL) {
  918. continue;
  919. }
  920. mutex = & (fd_table[fd]->mutex);
  921. if (pthread_mutex_trylock(mutex)) {
  922. continue;
  923. }
  924. if ((fd_table[fd]->r_owner) || (fd_table[fd]->w_owner)) {
  925. pthread_mutex_unlock(mutex);
  926. continue;
  927. }
  928. /* Is it a kernel fd ? */
  929. if ((!fd_table[fd]->ops) || (fd_table[fd]->ops->use_kfds != 1)) {
  930. pthread_mutex_unlock(mutex);
  931. continue;
  932. }
  933. switch (fd_table[fd]->type) {
  934. case FD_HALF_DUPLEX:
  935. machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL, fd_table[fd]->flags);
  936. fd_table[fd]->type = FD_TEST_HALF_DUPLEX;
  937. break;
  938. case FD_FULL_DUPLEX:
  939. machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL, fd_table[fd]->flags);
  940. fd_table[fd]->type = FD_TEST_FULL_DUPLEX;
  941. break;
  942. default:
  943. break;
  944. }
  945. pthread_mutex_unlock(mutex);
  946. }
  947. }
  948. /* ==========================================================================
  949.  * Here are the berkeley socket functions. These are not POSIX.
  950.  * ======================================================================= */
  951. #if defined (HAVE_SYSCALL_SOCKET) || defined (HAVE_SYSCALL_SOCKETCALL)
  952. /* ==========================================================================
  953.  * socket()
  954.  */
  955. int socket(int af, int type, int protocol)
  956. {
  957. int fd, fd_kern;
  958.  if (!((fd = fd_allocate()) < OK)) {
  959.         if (!((fd_kern = machdep_sys_socket(af, type, protocol)) < OK)) {
  960.     int tmp_flags;
  961. tmp_flags = machdep_sys_fcntl(fd_kern, F_GETFL, 0);
  962. machdep_sys_fcntl(fd_kern, F_SETFL, tmp_flags | __FD_NONBLOCK);
  963.             /* Should fstat the file to determine what type it is */
  964.             fd_table[fd]->ops  = & __fd_kern_ops;
  965.             fd_table[fd]->type  = FD_FULL_DUPLEX;
  966. fd_table[fd]->fd.i = fd_kern;
  967.          fd_table[fd]->flags = tmp_flags;
  968.             return(fd);
  969.         }
  970.         fd_table[fd]->count = 0;
  971. SET_ERRNO(-fd_kern);
  972.     }
  973.     return(NOTOK);
  974. }
  975. #endif
  976. #if defined (HAVE_SYSCALL_BIND) || defined (HAVE_SYSCALL_SOCKETCALL)
  977. /* ==========================================================================
  978.  * bind()
  979.  */
  980. #ifdef _OS_HAS_SOCKLEN_T
  981. int bind(int fd, const struct sockaddr *name, socklen_t namelen)
  982. #else
  983. int bind(int fd, const struct sockaddr *name, int namelen)
  984. #endif
  985. {
  986. /* Not much to do in bind */
  987. int ret;
  988. if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  989.         if ((ret = machdep_sys_bind(fd_table[fd]->fd.i, name, namelen)) < OK) { 
  990. SET_ERRNO(-ret);
  991. ret = NOTOK;
  992. }
  993. fd_unlock(fd, FD_RDWR);
  994. }
  995. return(ret);
  996. }
  997. #endif
  998. #if defined (HAVE_SYSCALL_CONNECT) || defined (HAVE_SYSCALL_SOCKETCALL)
  999. /* ==========================================================================
  1000.  * connect()
  1001.  */
  1002. #ifdef _OS_HAS_SOCKLEN_T
  1003. int connect(int fd, const struct sockaddr *name, socklen_t namelen)
  1004. #else
  1005. int connect(int fd, const struct sockaddr *name, int namelen)
  1006. #endif
  1007. {
  1008.   struct sockaddr tmpname;
  1009.   int ret, tmpnamelen;
  1010.   if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  1011.     if ((ret = machdep_sys_connect(fd_table[fd]->fd.i, name, namelen)) < OK) {
  1012.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1013.   ((ret == -EWOULDBLOCK) || (ret == -EINPROGRESS) ||
  1014.    (ret == -EALREADY) || (ret == -EAGAIN))) {
  1015. pthread_sched_prevent();
  1016. /* queue pthread for a FDW_WAIT */
  1017. SET_PF_WAIT_EVENT(pthread_run);
  1018. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1019. pthread_queue_enq(&fd_wait_write, pthread_run);
  1020. pthread_resched_resume(PS_FDW_WAIT);
  1021. CLEAR_PF_DONE_EVENT(pthread_run);
  1022. tmpnamelen = sizeof(tmpname);
  1023. /* OK now lets see if it really worked */
  1024. if (((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
  1025.     &tmpname, &tmpnamelen)) < OK) &&
  1026.     (ret == -ENOTCONN))
  1027. {
  1028.   /* Get the error, this function should not fail */
  1029.   machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
  1030.  SO_ERROR, &ret, &tmpnamelen); 
  1031.   SET_ERRNO(ret); /* ret is already positive (mevans) */
  1032.   ret = NOTOK;
  1033. }
  1034.       } else {
  1035. if (ret < 0)
  1036. {
  1037.   SET_ERRNO(-ret);
  1038.   ret = NOTOK;
  1039. }
  1040.       }
  1041.     }
  1042.     fd_unlock(fd, FD_RDWR);
  1043.   }
  1044.   return(ret);
  1045. }
  1046. #endif
  1047. #if defined (HAVE_SYSCALL_ACCEPT) || defined (HAVE_SYSCALL_SOCKETCALL)
  1048. /* ==========================================================================
  1049.  * accept()
  1050.  */
  1051. #ifdef _OS_HAS_SOCKLEN_T
  1052. int accept(int fd, struct sockaddr *name, socklen_t *namelen)
  1053. #else
  1054. int accept(int fd, struct sockaddr *name, int *namelen)
  1055. #endif
  1056. {
  1057.   int ret, fd_kern;
  1058.   if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  1059.     while ((fd_kern = machdep_sys_accept(fd_table[fd]->fd.i, name, namelen)) < OK) {
  1060.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1061.   ((fd_kern == -EWOULDBLOCK) || (fd_kern == -EAGAIN))) {
  1062. pthread_sched_prevent();
  1063. /* queue pthread for a FDR_WAIT */
  1064. SET_PF_WAIT_EVENT(pthread_run);
  1065. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1066. pthread_queue_enq(&fd_wait_read, pthread_run);
  1067. pthread_resched_resume(PS_FDR_WAIT);
  1068. CLEAR_PF_DONE_EVENT(pthread_run);
  1069.       } else {
  1070. fd_unlock(fd, FD_RDWR);
  1071. SET_ERRNO(-fd_kern);
  1072. return(NOTOK);
  1073.       }
  1074.     }
  1075.     fd_unlock(fd, FD_RDWR);
  1076.     if (!((ret = fd_allocate()) < OK)) {
  1077.       /* This may be unnecessary */
  1078.       machdep_sys_fcntl(fd_kern, F_SETFL, __FD_NONBLOCK);
  1079.       /* Should fstat the file to determine what type it is */
  1080.       fd_table[ret]->ops  = & __fd_kern_ops;
  1081.       fd_table[ret]->type  = FD_FULL_DUPLEX;
  1082.       fd_table[ret]->fd.i = fd_kern;
  1083.       /* XXX Flags should be the same as those on the listening fd */
  1084.       fd_table[ret]->flags  = fd_table[fd]->flags;
  1085.     }
  1086.   }
  1087.   return(ret);
  1088. }
  1089. #endif
  1090. #if defined (HAVE_SYSCALL_LISTEN) || defined (HAVE_SYSCALL_SOCKETCALL)
  1091. /* ==========================================================================
  1092.  * listen()
  1093.  */
  1094. int listen(int fd, int backlog) 
  1095. {
  1096.   int ret;
  1097.   if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  1098.     if ((ret = machdep_sys_listen(fd_table[fd]->fd.i, backlog)) < OK) {
  1099.       SET_ERRNO(-ret);
  1100.       ret = NOTOK;
  1101.     }
  1102.     fd_unlock(fd, FD_RDWR);
  1103.   }
  1104.   return(ret);
  1105. }
  1106. #endif
  1107. #if defined (HAVE_SYSCALL_SEND) || defined (HAVE_SYSCALL_SOCKETCALL)
  1108. /* ==========================================================================
  1109.  * send_timedwait()
  1110.  */
  1111. ssize_t send_timedwait(int fd, const void * msg, size_t len, int flags,
  1112.        struct timespec * timeout)
  1113. {
  1114.   int ret;
  1115.   pthread_run->sighandled=0; /* Added by monty */
  1116.   if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
  1117.     while ((ret = machdep_sys_send(fd_table[fd]->fd.i,
  1118.    msg,  len, flags)) < OK)
  1119.     {
  1120.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1121.   ((ret == -EWOULDBLOCK) || (ret == -EAGAIN)))
  1122.       {
  1123. pthread_sched_prevent();
  1124. /* queue pthread for a FDW_WAIT */
  1125. SET_PF_WAIT_EVENT(pthread_run);
  1126. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1127. pthread_queue_enq(&fd_wait_write, pthread_run);
  1128. if (timeout) {
  1129.   /* get current time */
  1130.   struct timespec current_time;
  1131.   machdep_gettimeofday(&current_time);
  1132.   sleep_schedule(&current_time, timeout);
  1133.   pthread_resched_resume(PS_FDW_WAIT);
  1134.   /* We're awake */
  1135.   pthread_sched_prevent();
  1136.   if (sleep_cancel(pthread_run) == NOTOK) {
  1137.     CLEAR_PF_DONE_EVENT(pthread_run);
  1138.     pthread_sched_resume();
  1139.     ret = -ETIMEDOUT;
  1140.     break;
  1141.   }
  1142.   pthread_sched_resume();
  1143. } else {
  1144.   pthread_resched_resume(PS_FDW_WAIT);
  1145. }
  1146. CLEAR_PF_DONE_EVENT(pthread_run);
  1147. if (pthread_run->sighandled) /* Added by monty */
  1148. { /* We where aborted */
  1149.   ret= -EINTR;
  1150.   break;
  1151. }
  1152.       } else {
  1153. break;
  1154.       }
  1155.     }
  1156.     fd_unlock(fd, FD_WRITE);
  1157.   }
  1158.   if (ret < 0)
  1159.   {
  1160.     SET_ERRNO(-ret);
  1161.     return(NOTOK);
  1162.   }
  1163.   return ret;
  1164. }
  1165. /* ==========================================================================
  1166.  * send()
  1167.  */
  1168. ssize_t send(int fd, const void * msg, size_t len, int flags)
  1169. {
  1170. return(send_timedwait(fd, msg, len, flags, NULL));
  1171. }
  1172. #endif
  1173. #if defined (HAVE_SYSCALL_SENDTO) || defined (HAVE_SYSCALL_SOCKETCALL)
  1174. /* ==========================================================================
  1175.  * sendto_timedwait()
  1176.  */
  1177. ssize_t sendto_timedwait(int fd, const void * msg, size_t len,
  1178.  int flags, const struct sockaddr *to, int to_len,
  1179.  struct timespec * timeout)
  1180. {
  1181.   int ret;
  1182.   pthread_run->sighandled=0; /* Added by monty */
  1183.   if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
  1184.     while ((ret = machdep_sys_sendto(fd_table[fd]->fd.i,
  1185.      msg, len, flags, to, to_len)) < OK) {
  1186.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1187.   ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  1188. pthread_sched_prevent();
  1189. /* queue pthread for a FDW_WAIT */
  1190. SET_PF_WAIT_EVENT(pthread_run);
  1191. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1192. pthread_queue_enq(&fd_wait_write, pthread_run);
  1193. if (timeout) {
  1194.   /* get current time */
  1195.   struct timespec current_time;
  1196.   machdep_gettimeofday(&current_time);
  1197.   sleep_schedule(&current_time, timeout);
  1198.   pthread_resched_resume(PS_FDW_WAIT);
  1199.   /* We're awake */
  1200.   pthread_sched_prevent();
  1201.   if (sleep_cancel(pthread_run) == NOTOK) {
  1202.     CLEAR_PF_DONE_EVENT(pthread_run);
  1203.     pthread_sched_resume();
  1204.     ret= -ETIMEDOUT;
  1205.     break;
  1206.   }
  1207.   pthread_sched_resume();
  1208. } else {
  1209.   pthread_resched_resume(PS_FDW_WAIT);
  1210. }
  1211. CLEAR_PF_DONE_EVENT(pthread_run);
  1212. if (pthread_run->sighandled) /* Added by monty */
  1213. { /* We where aborted */
  1214.   ret= -EINTR;
  1215.   break;
  1216. }
  1217.       }
  1218.       else
  1219. break; /* ret contains the errorcode */
  1220.     }
  1221.     fd_unlock(fd, FD_WRITE);
  1222.   }
  1223.   if (ret < 0)
  1224.   {
  1225.     SET_ERRNO(-ret);
  1226.     return(NOTOK);
  1227.   }
  1228.   return(ret);
  1229. }
  1230. /* ==========================================================================
  1231.  * sendto()
  1232.  */
  1233. #ifdef _OS_HAS_SOCKLEN_T
  1234. ssize_t sendto(int fd, const void * msg, size_t len, int flags,
  1235.        const struct sockaddr *to, socklen_t to_len)
  1236. #else
  1237. ssize_t sendto(int fd, const void * msg, size_t len, int flags,
  1238.        const struct sockaddr *to, int to_len)
  1239. #endif
  1240. {
  1241. return(sendto_timedwait(fd, msg, len, flags, to, to_len, NULL));
  1242. }
  1243. #endif
  1244. #if defined (HAVE_SYSCALL_SENDMSG) || defined (HAVE_SYSCALL_SOCKETCALL)
  1245. /* ==========================================================================
  1246.  * sendmsg_timedwait()
  1247.  */
  1248. ssize_t sendmsg_timedwait(int fd, const struct msghdr *msg, int flags,
  1249.   struct timespec * timeout)
  1250. {
  1251.   int passed_fd, ret, i;
  1252.   /* Handle getting the real file descriptor */
  1253.   for(i = 0; i < (((struct omsghdr *)msg)->msg_accrightslen/sizeof(i)); i++) {
  1254.     passed_fd = *(((int *)((struct omsghdr *)msg)->msg_accrights) + i);
  1255.     if ((ret = fd_lock(passed_fd, FD_RDWR, NULL)) == OK) {
  1256.       *(((int *)((struct omsghdr *)msg)->msg_accrights) + i)
  1257. = fd_table[passed_fd]->fd.i;
  1258.       machdep_sys_fcntl(fd_table[passed_fd]->fd.i, F_SETFL, 
  1259. fd_table[passed_fd]->flags);
  1260.       switch(fd_table[passed_fd]->type) {
  1261.       case FD_TEST_FULL_DUPLEX:
  1262.       case FD_TEST_HALF_DUPLEX:
  1263. break;
  1264.       case FD_FULL_DUPLEX:
  1265. fd_table[passed_fd]->type =  FD_TEST_FULL_DUPLEX;
  1266. break;
  1267.       case FD_HALF_DUPLEX:
  1268. fd_table[passed_fd]->type =  FD_TEST_HALF_DUPLEX;
  1269. break;
  1270.       default:
  1271. PANIC();
  1272.       }
  1273.     } else {
  1274.       fd_unlock(fd, FD_RDWR);
  1275.       SET_ERRNO(EBADF);
  1276.       return(NOTOK);
  1277.     }
  1278.     fd_unlock(fd, FD_RDWR);
  1279.   }
  1280.   pthread_run->sighandled=0; /* Added by monty */
  1281.   if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
  1282.     while((ret = machdep_sys_sendmsg(fd_table[fd]->fd.i, msg, flags)) < OK){
  1283.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1284.   ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  1285. pthread_sched_prevent();
  1286. /* queue pthread for a FDW_WAIT */
  1287. SET_PF_WAIT_EVENT(pthread_run);
  1288. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1289. pthread_queue_enq(&fd_wait_write, pthread_run);
  1290. if (timeout) {
  1291.   /* get current time */
  1292.   struct timespec current_time;
  1293.   machdep_gettimeofday(&current_time);
  1294.   sleep_schedule(&current_time, timeout);
  1295.   pthread_resched_resume(PS_FDW_WAIT);
  1296.   /* We're awake */
  1297.   pthread_sched_prevent();
  1298.   if (sleep_cancel(pthread_run) == NOTOK) {
  1299.     CLEAR_PF_DONE_EVENT(pthread_run);
  1300.     pthread_sched_resume();
  1301.     SET_ERRNO(ETIMEDOUT);
  1302.     ret = NOTOK;
  1303.     break;
  1304.   }
  1305.   pthread_sched_resume();
  1306. } else {
  1307.   pthread_resched_resume(PS_FDW_WAIT);
  1308. }
  1309. CLEAR_PF_DONE_EVENT(pthread_run);
  1310. if (pthread_run->sighandled) /* Added by monty */
  1311. { /* We where aborted */
  1312.   SET_ERRNO(EINTR);
  1313.   ret= NOTOK;
  1314.   break;
  1315. }
  1316.       } else {
  1317. SET_ERRNO(-ret);
  1318. ret = NOTOK;
  1319. break;
  1320.       }
  1321.     }
  1322.     fd_unlock(fd, FD_WRITE);
  1323.   }
  1324.   return(ret);
  1325. }
  1326. /* ==========================================================================
  1327.  * sendmsg()
  1328.  */
  1329. ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
  1330. {
  1331. return(sendmsg_timedwait(fd, msg, flags, NULL));
  1332. }
  1333. #endif
  1334. #if defined (HAVE_SYSCALL_RECV) || defined (HAVE_SYSCALL_SOCKETCALL)
  1335. /* ==========================================================================
  1336.  * recv_timedwait()
  1337.  */
  1338. ssize_t recv_timedwait(int fd, void * buf, size_t len, int flags,
  1339.        struct timespec * timeout)
  1340. {
  1341.   int ret;
  1342.   pthread_run->sighandled=0; /* Added by monty */
  1343.   if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
  1344.     while ((ret = machdep_sys_recv(fd_table[fd]->fd.i,
  1345.    buf, len, flags)) < OK) {
  1346.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1347.   ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  1348. pthread_sched_prevent();
  1349. /* queue pthread for a FDR_WAIT */
  1350. SET_PF_WAIT_EVENT(pthread_run);
  1351. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1352. pthread_queue_enq(&fd_wait_read, pthread_run);
  1353. if (timeout) {
  1354.   /* get current time */
  1355.   struct timespec current_time;
  1356.   machdep_gettimeofday(&current_time);
  1357.   sleep_schedule(&current_time, timeout);
  1358.   pthread_resched_resume(PS_FDR_WAIT);
  1359.   /* We're awake */
  1360.   pthread_sched_prevent();
  1361.   if (sleep_cancel(pthread_run) == NOTOK) {
  1362.     CLEAR_PF_DONE_EVENT(pthread_run);
  1363.     pthread_sched_resume();
  1364.     ret = -ETIMEDOUT;
  1365.     break;
  1366.   }
  1367.   pthread_sched_resume();
  1368. } else {
  1369.   pthread_resched_resume(PS_FDR_WAIT);
  1370. }
  1371. CLEAR_PF_DONE_EVENT(pthread_run);
  1372. if (pthread_run->sighandled) /* Added by monty */
  1373. { /* We where aborted */
  1374.   ret= -EINTR;
  1375.   break;
  1376. }
  1377.       } else {
  1378. break;
  1379.       }
  1380.     }
  1381.     fd_unlock(fd, FD_READ);
  1382.   }
  1383.   if (ret < 0)
  1384.   {
  1385.     SET_ERRNO(-ret);
  1386.     return(NOTOK);
  1387.   }
  1388.   return(ret);
  1389. }
  1390. /* ==========================================================================
  1391.  * recv()
  1392.  */
  1393. ssize_t recv(int fd, void * buf, size_t len, int flags)
  1394. {
  1395. return(recv_timedwait(fd, buf, len, flags, NULL));
  1396. }
  1397. #endif
  1398. #if defined (HAVE_SYSCALL_RECVFROM) || defined (HAVE_SYSCALL_SOCKETCALL)
  1399. /* ==========================================================================
  1400.  * recvfrom_timedwait()
  1401.  */
  1402. ssize_t recvfrom_timedwait(int fd, void * buf, size_t len, int flags,
  1403.    struct sockaddr * from, int * from_len,
  1404.    struct timespec * timeout)
  1405. {
  1406.   int ret;
  1407.   pthread_run->sighandled=0; /* Added by monty */
  1408.   if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
  1409.     while ((ret = machdep_sys_recvfrom(fd_table[fd]->fd.i,
  1410.        buf, len, flags, from, from_len)) < OK) {
  1411.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1412.   ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  1413. pthread_sched_prevent();
  1414. /* queue pthread for a FDR_WAIT */
  1415. SET_PF_WAIT_EVENT(pthread_run);
  1416. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1417. pthread_queue_enq(&fd_wait_read, pthread_run);
  1418. if (timeout) {
  1419.   /* get current time */
  1420.   struct timespec current_time;
  1421.   machdep_gettimeofday(&current_time);
  1422.   sleep_schedule(&current_time, timeout);
  1423.   pthread_resched_resume(PS_FDR_WAIT);
  1424.   /* We're awake */
  1425.   pthread_sched_prevent();
  1426.   if (sleep_cancel(pthread_run) == NOTOK) {
  1427.     CLEAR_PF_DONE_EVENT(pthread_run);
  1428.     pthread_sched_resume();
  1429.     ret= -ETIMEDOUT;
  1430.     break;
  1431.   }
  1432.   pthread_sched_resume();
  1433. } else {
  1434.   pthread_resched_resume(PS_FDR_WAIT);
  1435. }
  1436. CLEAR_PF_DONE_EVENT(pthread_run);
  1437. if (pthread_run->sighandled) /* Added by monty */
  1438. { /* We where aborted */
  1439.   ret= -EINTR;
  1440.   break;
  1441. }
  1442.       } else {
  1443. break;
  1444.       }
  1445.     }
  1446.     fd_unlock(fd, FD_READ);
  1447.   }
  1448.   if (ret < 0)
  1449.   {
  1450.     SET_ERRNO(-ret);
  1451.     return(NOTOK);
  1452.   }
  1453.   return(ret);
  1454. }
  1455. /* ==========================================================================
  1456.  * recvfrom()
  1457.  */
  1458. #ifdef _OS_HAS_SOCKLEN_T
  1459. ssize_t recvfrom(int fd, void * buf, size_t len, int flags,
  1460.   struct sockaddr * from, socklen_t * from_len)
  1461. #else
  1462. ssize_t recvfrom(int fd, void * buf, size_t len, int flags,
  1463.   struct sockaddr * from, int * from_len)
  1464. #endif
  1465. {
  1466. return(recvfrom_timedwait(fd, buf, len, flags, from, from_len, NULL));
  1467. }
  1468. #endif
  1469. #if defined (HAVE_SYSCALL_RECVMSG) || defined (HAVE_SYSCALL_SOCKETCALL)
  1470. /* ==========================================================================
  1471.  * recvmsg_timedwait()
  1472.  */
  1473. ssize_t recvmsg_timedwait(int fd, struct msghdr *msg, int flags,
  1474.   struct timespec * timeout) 
  1475. {
  1476.   struct stat stat_buf;
  1477.   int passed_fd, ret, i;
  1478.   pthread_run->sighandled=0; /* Added by monty */
  1479.   if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
  1480.     while ((ret = machdep_sys_recvmsg(fd_table[fd]->fd.i, msg, flags)) < OK) {
  1481.       if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
  1482.   ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
  1483. pthread_sched_prevent();
  1484. /* queue pthread for a FDR_WAIT */
  1485. SET_PF_WAIT_EVENT(pthread_run);
  1486. pthread_run->data.fd.fd = fd_table[fd]->fd.i;
  1487. pthread_queue_enq(&fd_wait_read, pthread_run);
  1488. if (timeout) {
  1489.   /* get current time */
  1490.   struct timespec current_time;
  1491.   machdep_gettimeofday(&current_time);
  1492.   sleep_schedule(&current_time, timeout);
  1493.   pthread_resched_resume(PS_FDR_WAIT);
  1494.   /* We're awake */
  1495.   pthread_sched_prevent();
  1496.   if (sleep_cancel(pthread_run) == NOTOK) {
  1497.     CLEAR_PF_DONE_EVENT(pthread_run);
  1498.     pthread_sched_resume();
  1499.     SET_ERRNO(ETIMEDOUT);
  1500.     ret = NOTOK;
  1501.     break;
  1502.   }
  1503.   pthread_sched_resume();
  1504. } else {
  1505.   pthread_resched_resume(PS_FDR_WAIT);
  1506. }
  1507. CLEAR_PF_DONE_EVENT(pthread_run);
  1508. if (pthread_run->sighandled) /* Added by monty */
  1509. { /* We where aborted */
  1510.   SET_ERRNO(EINTR);
  1511.   ret= NOTOK;
  1512.   break;
  1513. }
  1514.       } else {
  1515. SET_ERRNO(-ret);
  1516. ret = NOTOK;
  1517. break;
  1518.       }
  1519.     }
  1520.     fd_unlock(fd, FD_READ);
  1521.     /* Handle getting the real file descriptor */
  1522.     for (i = 0; i < (((struct omsghdr *)msg)->msg_accrightslen / sizeof(i));
  1523.  i++) {
  1524.       passed_fd = *(((int *)((struct omsghdr *)msg)->msg_accrights) + i);
  1525.       if (!((fd = fd_allocate()) < OK)) {
  1526. fd_table[fd]->flags = machdep_sys_fcntl(passed_fd, F_GETFL);
  1527. if (!( fd_table[fd]->flags & __FD_NONBLOCK)) {
  1528.   machdep_sys_fcntl(passed_fd, F_SETFL,  
  1529.     fd_table[fd]->flags | __FD_NONBLOCK);
  1530. }
  1531. /* fstat the file to determine what type it is */
  1532. machdep_sys_fstat(passed_fd, &stat_buf);
  1533. if (S_ISREG(stat_buf.st_mode)) {
  1534.   fd_table[fd]->type = FD_HALF_DUPLEX;
  1535. } else {
  1536.   fd_table[fd]->type = FD_FULL_DUPLEX;
  1537. }
  1538. *(((int *)((struct omsghdr *)msg)->msg_accrights) + i) = fd;
  1539. fd_table[fd]->ops = &(__fd_kern_ops);
  1540. fd_table[fd]->fd.i = passed_fd;
  1541.       } else {
  1542. SET_ERRNO(EBADF);
  1543. return(NOTOK);
  1544. break;
  1545.       }
  1546.     }
  1547.   }
  1548.   return(ret);
  1549. }
  1550. /* ==========================================================================
  1551.  * recvmsg()
  1552.  */
  1553. ssize_t recvmsg(int fd, struct msghdr *msg, int flags) 
  1554. {
  1555. return(recvmsg_timedwait(fd, msg, flags, NULL));
  1556. }
  1557. #endif
  1558. #if defined (HAVE_SYSCALL_SHUTDOWN) || defined (HAVE_SYSCALL_SOCKETCALL)
  1559. /* ==========================================================================
  1560.  * shutdown()
  1561.  */
  1562. int shutdown(int fd, int how)
  1563. {
  1564. int ret;
  1565. switch(how) {
  1566. case 0: /* Read */
  1567. if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
  1568. if ((ret = machdep_sys_shutdown(fd_table[fd]->fd.i, how)) < OK) {
  1569. SET_ERRNO(-ret);
  1570. ret = NOTOK;
  1571. }
  1572. fd_unlock(fd, FD_READ);
  1573. }
  1574. case 1: /* Write */
  1575. if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
  1576. if ((ret = machdep_sys_shutdown(fd_table[fd]->fd.i, how)) < OK) {
  1577. SET_ERRNO(-ret);
  1578. ret = NOTOK;
  1579. }
  1580. fd_unlock(fd, FD_WRITE);
  1581. }
  1582. case 2: /* Read-Write */
  1583. if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  1584. if ((ret = machdep_sys_shutdown(fd_table[fd]->fd.i, how)) < OK) {
  1585. SET_ERRNO(-ret);
  1586. ret = NOTOK;
  1587. }
  1588. fd_unlock(fd, FD_RDWR);
  1589. }
  1590. default:
  1591. SET_ERRNO(EBADF);
  1592. ret = NOTOK;
  1593. break;
  1594. }
  1595. return(ret);
  1596. }
  1597. #endif
  1598. #if defined (HAVE_SYSCALL_SETSOCKOPT) || defined (HAVE_SYSCALL_SOCKETCALL)
  1599. /* ==========================================================================
  1600.  * setsockopt()
  1601.  */
  1602. #ifdef _OS_HAS_SOCKLEN_T
  1603. int setsockopt(int fd, int level, int optname, const void * optval, socklen_t optlen)
  1604. #else
  1605. int setsockopt(int fd, int level, int optname, const void * optval, int optlen)
  1606. #endif
  1607. {
  1608.    int ret;
  1609.    if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
  1610.       if ((ret = machdep_sys_setsockopt(fd_table[fd]->fd.i, level,
  1611.   optname, optval, optlen)) < OK) {
  1612. SET_ERRNO(-ret);
  1613. ret = NOTOK;
  1614.       }
  1615.      fd_unlock(fd, FD_RDWR);
  1616.     }
  1617. return ret;
  1618. }
  1619. #endif
  1620. #if defined (HAVE_SYSCALL_GETSOCKOPT) || defined (HAVE_SYSCALL_SOCKETCALL)
  1621. /* ==========================================================================
  1622.  * getsockopt()
  1623.  */
  1624. #ifdef _OS_HAS_SOCKLEN_T
  1625. int getsockopt(int fd, int level, int optname, void * optval, socklen_t * optlen)
  1626. #else
  1627. int getsockopt(int fd, int level, int optname, void * optval, int * optlen)
  1628. #endif
  1629. {
  1630. int ret;
  1631. if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
  1632.       if ((ret = machdep_sys_getsockopt(fd_table[fd]->fd.i, level,
  1633.   optname, optval, optlen)) < OK) {
  1634. SET_ERRNO(-ret);
  1635. ret = NOTOK;
  1636.       }
  1637.      fd_unlock(fd, FD_RDWR);
  1638.     }
  1639. return ret;
  1640. }
  1641. #endif
  1642. #if defined (HAVE_SYSCALL_GETSOCKOPT) || defined (HAVE_SYSCALL_SOCKETCALL)
  1643. /* ==========================================================================
  1644.  * getsockname()
  1645.  */
  1646. #ifdef _OS_HAS_SOCKLEN_T
  1647. int getsockname(int fd, struct sockaddr * name, socklen_t * naddrlen)
  1648. #else
  1649. int getsockname(int fd, struct sockaddr * name, int * naddrlen)
  1650. #endif
  1651. {
  1652. int ret;
  1653. if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
  1654. if ((ret = machdep_sys_getsockname(fd_table[fd]->fd.i,
  1655.    name, naddrlen)) < OK) {
  1656. SET_ERRNO(-ret);
  1657. ret = NOTOK;
  1658. }
  1659. fd_unlock(fd, FD_RDWR);
  1660. }
  1661. return ret;
  1662. }
  1663. #endif
  1664. #if defined (HAVE_SYSCALL_GETPEERNAME) || defined (HAVE_SYSCALL_SOCKETCALL)
  1665. /* ==========================================================================
  1666.  * getpeername()
  1667.  */
  1668. #ifdef _OS_HAS_SOCKLEN_T
  1669. int getpeername(int fd, struct sockaddr * peer, socklen_t * paddrlen)
  1670. #else
  1671. int getpeername(int fd, struct sockaddr * peer, int * paddrlen)
  1672. #endif
  1673. {
  1674. int ret;
  1675. if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
  1676. if ((ret = machdep_sys_getpeername(fd_table[fd]->fd.i, 
  1677.    peer, paddrlen)) < OK) {
  1678. SET_ERRNO(-ret);
  1679. ret = NOTOK;
  1680. }
  1681. fd_unlock(fd, FD_READ);
  1682. }
  1683. return ret;
  1684. }
  1685. #endif
  1686. #if defined (HAVE_SYSCALL_SOCKETPAIR) || defined (HAVE_SYSCALL_SOCKETCALL)
  1687. /* ==========================================================================
  1688.  * socketpair()
  1689.  */
  1690. int socketpair(int af, int type, int protocol, int pair[2])
  1691. {
  1692.     int ret, fd[2];
  1693.     if (!((pair[0] = fd_allocate()) < OK)) {
  1694. if (!((pair[1] = fd_allocate()) < OK)) {
  1695.          if (!((ret = machdep_sys_socketpair(af, type, protocol, fd)) < OK)){
  1696.      int tmp_flags;
  1697.      tmp_flags = machdep_sys_fcntl(fd[0], F_GETFL, 0);
  1698.      machdep_sys_fcntl(fd[0], F_SETFL, tmp_flags | __FD_NONBLOCK);
  1699.              fd_table[pair[0]]->ops  = & __fd_kern_ops;
  1700.              fd_table[pair[0]]->type  = FD_FULL_DUPLEX;
  1701.      fd_table[pair[0]]->flags  = tmp_flags;
  1702.      fd_table[pair[0]]->fd.i = fd[0];
  1703.      tmp_flags = machdep_sys_fcntl(fd[1], F_GETFL, 0);
  1704.      machdep_sys_fcntl(fd[1], F_SETFL, tmp_flags | __FD_NONBLOCK);
  1705.              fd_table[pair[1]]->ops  = & __fd_kern_ops;
  1706.              fd_table[pair[1]]->type  = FD_FULL_DUPLEX;
  1707.      fd_table[pair[1]]->flags  = tmp_flags;
  1708.      fd_table[pair[1]]->fd.i = fd[1];
  1709.              return(ret);
  1710.          }
  1711.          fd_table[pair[1]]->count = 0;
  1712. }
  1713.         fd_table[pair[0]]->count = 0;
  1714. SET_ERRNO(-ret);
  1715.     }
  1716.     return(NOTOK);
  1717. }
  1718. #endif