home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ixemul-45.0-src.tgz / tar.out / contrib / ixemul / library / unp.c < prev    next >
C/C++ Source or Header  |  1996-10-01  |  19KB  |  833 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1996 by Hans Verkuil
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /*
  21.    Missing features:
  22.  
  23.    datagram support
  24.    setsockopt/getsockopt are dummy functions
  25.    no timeout while connecting
  26.  
  27. */
  28.  
  29. #define _KERNEL
  30. #include "ixemul.h"
  31. #include "unp.h"
  32. #include "kprintf.h"
  33.  
  34. #include <sys/socket.h>
  35. #include <sys/socketvar.h>
  36. #include <sys/unix_socket.h>
  37. #include <sys/un.h>
  38. #include <sys/ioctl.h>
  39. #include <net/if.h>
  40. #include <net/route.h>
  41. #include <netinet/in.h>
  42. #include <machine/param.h>
  43. #include <string.h>
  44. #include "select.h"
  45.  
  46. struct ix_unix_name *
  47. find_unix_name(const char *path)
  48. {
  49.   struct ix_unix_name *un;
  50.  
  51.   for (un = ix.ix_unix_names; un; un = un->next)
  52.     if (!strcmp(un->path, path))
  53.       break;
  54.   return un;
  55. }
  56.  
  57. struct sock_stream *
  58. init_stream(void)
  59. {
  60.   struct sock_stream *s = kmalloc(sizeof(struct sock_stream));
  61.  
  62.   if (s)
  63.     {
  64.       s->reader = s->writer = s->buffer;
  65.       s->flags = 0;
  66.       s->task = 0;
  67.     }
  68.   return s;
  69. }
  70.  
  71. static struct ix_unix_name *
  72. add_unix_name(const char *path, int queue_size)
  73. {
  74.   struct ix_unix_name *un = kmalloc(sizeof(struct ix_unix_name));
  75.  
  76.   if (un == NULL)
  77.     errno_return(ENOMEM, NULL);
  78.  
  79.   if (queue_size == 0)
  80.     queue_size = 1;
  81.   un->queue = kmalloc(queue_size * 4);
  82.   if (un->queue == NULL)
  83.     {
  84.       kfree(un);
  85.       errno_return(ENOMEM, NULL);
  86.     }
  87.   strcpy(un->path, path);
  88.   un->next = ix.ix_unix_names;
  89.   ix.ix_unix_names = un;
  90.   un->queue_size = queue_size;
  91.   un->queue_index = 0;
  92.   un->task = 0;
  93.   return un;
  94. }
  95.  
  96. struct sock_stream *
  97. find_stream(struct file *f, int read_stream)
  98. {
  99.   struct unix_socket *us;
  100.  
  101.   if (f->f_type == DTYPE_PIPE)
  102.     return f->f_ss;
  103.  
  104.   us = f->f_sock;
  105.   if (us->server != f)
  106.     read_stream = !read_stream;
  107.   return (read_stream ? us->to_server : us->from_server);
  108. }
  109.  
  110. struct sock_stream *
  111. get_stream(struct file *f, int read_stream)
  112. {
  113.   struct sock_stream *ss = find_stream(f, read_stream);
  114.  
  115.   if (ss == NULL)
  116.     return ss;
  117.  
  118.   Forbid();
  119.   for (;;)
  120.     {
  121.       if (!(ss->flags & UNF_LOCKED))
  122.         {
  123.           ss->flags &= ~UNF_WANT_LOCK;
  124.           ss->flags |= UNF_LOCKED;
  125.           /* got it ! */
  126.           break;
  127.     }
  128.       ss->flags |= UNF_WANT_LOCK;
  129.       if (ix_sleep((caddr_t)&ss->flags, "get_sock") < 0)
  130.         {
  131.       Permit();
  132.       setrun(FindTask(0));
  133.       Forbid();
  134.         }
  135.       /* have to always recheck whether we really got the lock */
  136.     }
  137.   Permit();
  138.   return ss;
  139. }
  140.  
  141. void
  142. release_stream(struct sock_stream *ss)
  143. {
  144.   if (ss)
  145.     {
  146.       Forbid ();
  147.       if (ss->flags & UNF_WANT_LOCK)
  148.         ix_wakeup ((u_int)&ss->flags);
  149.         
  150.       ss->flags &= ~(UNF_WANT_LOCK | UNF_LOCKED);
  151.       Permit ();
  152.     }
  153. }
  154.  
  155. static int stream_is_closed(struct sock_stream *ss)
  156. {
  157.   return (ss == NULL || (ss->flags & (UNF_NO_READER | UNF_NO_WRITER)) ==
  158.                                      (UNF_NO_READER | UNF_NO_WRITER));
  159. }
  160.  
  161. static void close_stream(struct file *f, int read_stream)
  162. {
  163.   struct sock_stream **ss;
  164.   struct unix_socket *us = f->f_sock;
  165.   int to_server;
  166.  
  167.   if (us == NULL)
  168.     return;
  169.   to_server = (us->server != f) ? !read_stream : read_stream;
  170.   ss = (to_server ? &us->to_server : &us->from_server);
  171.  
  172.   if (*ss)
  173.     {
  174.       (*ss)->flags |= (read_stream ? UNF_NO_READER : UNF_NO_WRITER);
  175.       if (stream_is_closed(*ss))
  176.         {
  177.           kfree (*ss);
  178.           *ss = NULL;
  179.         }
  180.       else
  181.         {
  182.           Forbid();
  183.           if ((*ss)->task)
  184.             Signal((*ss)->task, 1UL << u.u_pipe_sig);
  185.           Permit();
  186.           ix_wakeup ((u_int)*ss);
  187.         }
  188.     }
  189.   if (read_stream && us->unix_name && f->f_count == 0)
  190.     {
  191.       struct ix_unix_name *un;
  192.     
  193.       if (us->unix_name == ix.ix_unix_names)
  194.         {
  195.           ix.ix_unix_names = ix.ix_unix_names->next;
  196.         }
  197.       else
  198.         {
  199.           for (un = ix.ix_unix_names; un; un = un->next)
  200.             if (un->next == us->unix_name)
  201.               {
  202.                 un->next = us->unix_name->next;
  203.                 break;
  204.               }
  205.         }
  206.       kfree(us->unix_name);
  207.       us->unix_name = NULL;
  208.     }
  209.   if (stream_is_closed(us->to_server) && stream_is_closed(us->from_server) &&
  210.       us->unix_name == NULL && f->f_count == 0)
  211.     {
  212.       kfree(us);
  213.       f->f_sock = 0;
  214.     }
  215. }
  216.  
  217. int unp_socket(int domain, int type, int protocol, struct unix_socket *sock)
  218. {
  219.   int omask, err, fd;
  220.   struct file *fp;
  221.   struct unix_socket *us;
  222.  
  223.   if (type != SOCK_STREAM || protocol != 0)
  224.     errno_return(EPROTONOSUPPORT, -1);
  225.  
  226.   if (sock)
  227.     us = sock;
  228.   else if ((us = kmalloc(sizeof(struct unix_socket))) == NULL)
  229.     errno_return(ENOMEM, -1);
  230.   else
  231.     {
  232.       us->path[0] = 0;
  233.       us->from_server = us->to_server = NULL;
  234.       us->unix_name = NULL;
  235.       us->server = NULL;
  236.       us->state = UNS_WAITING;
  237.     }
  238.  
  239.   omask = syscall (SYS_sigsetmask, ~0);
  240.  
  241.   if ((err = falloc (&fp, &fd)))
  242.     {
  243.       errno = err;
  244.       syscall (SYS_sigsetmask, omask);
  245.       if (sock == NULL)
  246.         kfree(us);
  247.       return -1;
  248.     }
  249.  
  250.   fp->f_sock = us;
  251.   _set_socket_params(fp, domain);
  252.  
  253.   syscall (SYS_sigsetmask, omask);
  254.  
  255.   return fd;
  256. }
  257.  
  258. int unp_bind(int s, const struct sockaddr *name, int namelen)
  259. {
  260.   struct file *fp = u.u_ofile[s];
  261.   struct ix_unix_name *un;
  262.   int tmp;
  263.   char *path = ((struct sockaddr_un *)name)->sun_path;
  264.  
  265.   if (fp->f_sock->path[0])
  266.     errno_return(EINVAL, -1);
  267.  
  268.   ix_lock_base();
  269.   un = find_unix_name(path);
  270.   ix_unlock_base();
  271.   if (un)  
  272.     errno_return(EADDRINUSE, -1);
  273.  
  274.   tmp = syscall(SYS_creat, path, 0777);
  275.   if (tmp < 0)
  276.     return -1;
  277.   syscall(SYS_close, tmp);
  278.   strcpy(fp->f_sock->path, path);
  279.   return 0;
  280. }
  281.  
  282. int unp_listen(int s, int backlog)
  283. {
  284.   struct file *fp = u.u_ofile[s];
  285.   struct unix_socket *us = fp->f_sock;
  286.  
  287.   if (!us->path[0] || us->unix_name || us->to_server || us->from_server)
  288.     errno_return(EOPNOTSUPP, -1);
  289.   
  290.   ix_lock_base();
  291.   us->unix_name = add_unix_name(us->path, backlog);
  292.   ix_unlock_base();
  293.   return (us->unix_name ? 0 : -1);
  294. }
  295.  
  296. int unp_accept(int s, struct sockaddr *name, int *namelen)
  297. {
  298.   struct file *f = u.u_ofile[s];
  299.   struct unix_socket *client = NULL;
  300.   struct ix_unix_name *un = f->f_sock->unix_name;
  301.   int omask, err = 0, sleep_rc, fd;
  302.   struct sockaddr_un *sa = (struct sockaddr_un *)name;
  303.  
  304.   if (un == NULL)
  305.     errno_return(EOPNOTSUPP, -1);
  306.   omask = syscall (SYS_sigsetmask, ~0);
  307.   __get_file (f);
  308.  
  309.   do {
  310.     while (un->queue_index == 0)
  311.       {
  312.         if (f->f_flags & FNDELAY)
  313.           {
  314.             err = EWOULDBLOCK;
  315.             goto error;
  316.           }
  317.         Forbid ();
  318.         __release_file (f);
  319.         syscall (SYS_sigsetmask, omask);
  320.         sleep_rc = ix_sleep((caddr_t)un, "accept");
  321.         Permit ();
  322.         if (sleep_rc < 0)
  323.           setrun (FindTask (0));
  324.         omask = syscall (SYS_sigsetmask, ~0);
  325.         __get_file (f);
  326.       }
  327.     ix_lock_base();
  328.     client = NULL;
  329.     if (un->queue_index)
  330.       {
  331.         client = (struct unix_socket *)un->queue[0];
  332.         if (--un->queue_index)
  333.           memcpy(un->queue, un->queue + 4, un->queue_index * 4);
  334.         if (client)
  335.           client->state = UNS_PROCESSING;
  336.       }
  337.     ix_unlock_base();
  338.   } while (client == NULL);
  339.     
  340. error:
  341.   __release_file (f);
  342.   if (err)
  343.     {
  344.       syscall (SYS_sigsetmask, omask);
  345.       errno_return(err, -1);
  346.     }
  347.   fd = unp_socket(PF_UNIX, SOCK_STREAM, 0, client);
  348.   if (fd == -1)
  349.     client->state = UNS_ERROR;
  350.   else
  351.     {
  352.       f = u.u_ofile[fd];
  353.       client->server = f;
  354.       client->state = UNS_ACCEPTED;
  355.       sa->sun_family = AF_UNIX;
  356.       strcpy(sa->sun_path, un->path);
  357.       sa->sun_len = *namelen = 3 + strlen(sa->sun_path);
  358.     }
  359.   ix_wakeup((u_int)client);
  360.   syscall (SYS_sigsetmask, omask);
  361.   return fd;
  362. }
  363.  
  364. int unp_connect(int s, const struct sockaddr *name, int namelen)
  365. {
  366.   struct file *f = u.u_ofile[s];
  367.   struct unix_socket *us = f->f_sock;
  368.   struct ix_unix_name *un;
  369.   int sleep_rc, state;
  370.   char *path = ((struct sockaddr_un *)name)->sun_path;
  371.  
  372.   if (us->unix_name)
  373.     errno_return(EOPNOTSUPP, -1);
  374.   if (us->to_server || us->from_server)
  375.     errno_return(EISCONN, -1);
  376.   strcpy(us->path, path);
  377.   ix_lock_base();
  378.   un = find_unix_name(path);
  379.   if (un == NULL)
  380.     {
  381.       ix_unlock_base();
  382.       errno_return(EADDRNOTAVAIL, -1);
  383.     }
  384.   if (un->queue_size == un->queue_index)
  385.     {
  386.       ix_unlock_base();
  387.       errno_return(ECONNREFUSED, -1);
  388.     }
  389.   us->to_server = init_stream();
  390.   if (us->to_server)
  391.     us->from_server = init_stream();
  392.   if (!us->from_server)
  393.     {
  394.       if (us->to_server)
  395.         kfree(us->to_server);
  396.       us->to_server = NULL;
  397.       ix_unlock_base();
  398.       errno_return(ENOMEM, -1);
  399.     }
  400.   un->queue[un->queue_index++] = (int)us;
  401.   ix_unlock_base();
  402.   Forbid();
  403.   if (un->task)
  404.     Signal(un->task, 1UL << u.u_pipe_sig);
  405.   Permit();
  406.   ix_wakeup((u_int)un);
  407.  
  408.   do {
  409.     Forbid ();
  410.     sleep_rc = ix_sleep((caddr_t)us, "connect");
  411.     state = us->state;
  412.     Permit ();
  413.     if (sleep_rc < 0)
  414.       setrun (FindTask (0));
  415.   } while (sleep_rc < 0 || (state != UNS_ERROR && state != UNS_ACCEPTED));
  416.  
  417.   if (state == UNS_ERROR)
  418.     {
  419.       kfree(us->to_server);
  420.       kfree(us->from_server);
  421.       us->to_server = us->from_server = NULL;
  422.       errno_return(ECONNREFUSED, -1);
  423.     }
  424.   return 0;
  425. }
  426.  
  427. int unp_send(int s, const void *buf, int len, int flags)
  428. {
  429.   if (flags)
  430.     errno_return(EOPNOTSUPP, -1);
  431.   return unp_write(u.u_ofile[s], buf, len);
  432. }
  433.  
  434. int unp_recv(int s, void *buf, int len, int flags)
  435. {
  436.   if (flags)
  437.     errno_return(EOPNOTSUPP, -1);
  438.   return unp_read(u.u_ofile[s], buf, len);
  439. }
  440.  
  441. int unp_shutdown(int s, int how)
  442. {
  443.   struct file *f = u.u_ofile[s];
  444.  
  445.   switch (how)
  446.   {
  447.     case 0:
  448.       close_stream(f, TRUE);
  449.       break;
  450.     case 1:
  451.       close_stream(f, FALSE);
  452.       break;
  453.     case 2:
  454.       close_stream(f, TRUE);
  455.       close_stream(f, FALSE);
  456.       break;
  457.   }
  458.   return 0;
  459. }
  460.  
  461. int unp_setsockopt(int s, int level, int name, const void *val, int valsize)
  462. {
  463.   return 0;
  464. }
  465.  
  466. int unp_getsockopt(int s, int level, int name, void *val, int *valsize)
  467. {
  468.   *valsize = 0;
  469.   return 0;
  470. }
  471.  
  472. int unp_getsockname(int s, struct sockaddr *asa, int *alen)
  473. {
  474.   struct file *f = u.u_ofile[s];
  475.   struct sockaddr_un *un = (struct sockaddr_un *)asa;
  476.  
  477.   strcpy(un->sun_path, f->f_sock->path);
  478.   un->sun_family = AF_UNIX;
  479.   un->sun_len = *alen = 5 + strlen(un->sun_path);
  480.   return 0;
  481. }
  482.  
  483. int unp_getpeername(int s, struct sockaddr *asa, int *alen)
  484. {
  485.   return unp_getsockname(s, asa, alen);
  486. }
  487.  
  488. int
  489. stream_read (struct file *f, char *buf, int len)
  490. {
  491.   int omask = syscall (SYS_sigsetmask, ~0);
  492.   int err = errno;
  493.   int really_read = 0;
  494.   struct sock_stream *ss = get_stream(f, TRUE);
  495.  
  496.   while (len)
  497.     {
  498.       if (ss == NULL || ss->reader == ss->writer)
  499.     {
  500.       if (ss == NULL || (ss->flags & UNF_NO_WRITER))
  501.         {
  502.           err = 0;
  503.           break;
  504.         }
  505.     
  506.       if (f->f_flags & FNDELAY)
  507.         {
  508.           if (!really_read)
  509.         {
  510.           really_read = -1;
  511.           err = EAGAIN;
  512.         }
  513.           break;
  514.         }
  515.       else if (really_read)
  516.         {
  517.           err = 0;
  518.           break;
  519.         }
  520.       else
  521.         {
  522.           int sleep_rc;
  523.  
  524.           /* wait for something to be read or all readers to close */
  525.           Forbid ();
  526.           /* sigh.. Forbid() is necessary, or the other end may change
  527.              the pipe, and in the worst case also settle for sleep(), and
  528.              there it is.. deadlock.. */
  529.           release_stream(ss);
  530.  
  531.           /* make read interruptible */
  532.           syscall (SYS_sigsetmask, omask);
  533.           sleep_rc = ix_sleep ((caddr_t)ss, "sockread");
  534.           Permit ();
  535.           if (sleep_rc < 0)
  536.             setrun (FindTask (0));
  537.           omask = syscall (SYS_sigsetmask, ~0);
  538.  
  539.           ss = get_stream(f, TRUE);
  540.           continue;        /* retry */
  541.         }
  542.     }
  543.       else
  544.     {
  545.       /* okay, there's something to read from the pipe */
  546.       if (ss->reader > ss->writer)
  547.         {
  548.           /* read till end of buffer and wrap around */
  549.           int avail = UNIX_SOCKET_SIZE - (ss->reader - ss->buffer);
  550.           int do_read = len < avail ? len : avail;
  551.  
  552.           really_read += do_read;
  553.           bcopy (ss->reader, buf, do_read);
  554.           len -= do_read;
  555.           buf += do_read;
  556.           ss->reader += do_read;
  557.           if (ss->reader - ss->buffer == UNIX_SOCKET_SIZE)
  558.         /* wrap around */
  559.         ss->reader = ss->buffer;
  560.         }
  561.       if (len && ss->reader < ss->writer)
  562.         {
  563.           int avail = ss->writer - ss->reader;
  564.           int do_read = len < avail ? len : avail;
  565.  
  566.           really_read += do_read;
  567.           bcopy (ss->reader, buf, do_read);
  568.           ss->reader += do_read;
  569.           len -= do_read;
  570.           buf += do_read;
  571.         }
  572.     }
  573.  
  574.       ix_wakeup ((u_int)ss);
  575.     }
  576.  
  577.   release_stream(ss);
  578.  
  579.   syscall (SYS_sigsetmask, omask);
  580.   errno = err;
  581.   return really_read;
  582. }
  583.  
  584. int unp_read(struct file *f, char *buf, int len)
  585. {
  586.   if (f->f_sock->state != UNS_ACCEPTED)
  587.     errno_return(ENOTCONN, -1);
  588.   return stream_read(f, buf, len);
  589. }
  590.  
  591. int
  592. stream_write (struct file *f, const char *buf, int len)
  593. {
  594.   int omask = syscall (SYS_sigsetmask, ~0);
  595.   int err = errno;
  596.   int really_written = 0;
  597.   struct sock_stream *ss = get_stream(f, FALSE);
  598.  
  599.   while (len)
  600.     {
  601.       if (ss == NULL || (ss->flags & UNF_NO_READER))
  602.     {
  603.       really_written = -1;
  604.       err = EPIPE;
  605.       /* this is something no `real' Amiga pipe handler will do ;-)) */
  606.       _psignal (FindTask (0), SIGPIPE);
  607.       break;
  608.         }
  609.     
  610.       /* buffer full ?? */
  611.       if (ss->reader == ss->writer + 1
  612.       || (ss->reader == ss->buffer 
  613.           && ss->writer == ss->buffer + UNIX_SOCKET_SIZE - 1))
  614.     {
  615.       if (f->f_flags & FNDELAY)
  616.         {
  617.           if (! really_written)
  618.             {
  619.               really_written = -1;
  620.               err = EAGAIN;
  621.             }
  622.           break;
  623.         }
  624.       else
  625.         {
  626.           int sleep_rc;
  627.  
  628.           /* wait for something to be read or all readers to close */
  629.           Forbid ();
  630.           /* sigh.. Forbid() is necessary, or the other end may change
  631.              the pipe, and in the worst case also settle for sleep(), and
  632.              there it is.. deadlock.. */
  633.           release_stream(ss);
  634.  
  635.           /* make write interruptible */
  636.           syscall (SYS_sigsetmask, omask);
  637.           sleep_rc = ix_sleep ((caddr_t)ss, "sockwrite");
  638.           Permit ();
  639.           if (sleep_rc < 0)
  640.             setrun (FindTask (0));
  641.           omask = syscall (SYS_sigsetmask, ~0);
  642.  
  643.           ss = get_stream(f, FALSE);
  644.           continue;        /* retry */
  645.         }
  646.     }
  647.       else
  648.     {
  649.       /* okay, there's some space left to write to the pipe */
  650.  
  651.       if (ss->writer >= ss->reader)
  652.         {
  653.           /* write till end of buffer */
  654.           int avail = UNIX_SOCKET_SIZE - 1 - (ss->writer - ss->buffer);
  655.           int do_write;
  656.  
  657.           if (ss->reader > ss->buffer)
  658.             avail++;
  659.           do_write = len < avail ? len : avail;
  660.  
  661.           really_written += do_write;
  662.           bcopy (buf, ss->writer, do_write);
  663.           len -= do_write;
  664.           buf += do_write;
  665.           ss->writer += do_write;
  666.           if (ss->writer - ss->buffer == UNIX_SOCKET_SIZE)
  667.             ss->writer = ss->buffer;
  668.         }
  669.  
  670.       if (ss->writer < ss->reader - 1)
  671.         {
  672.           int avail = ss->reader - ss->writer - 1;
  673.           int do_write = len < avail ? len : avail;
  674.  
  675.           really_written += do_write;
  676.           bcopy (buf, ss->writer, do_write);
  677.           ss->writer += do_write;
  678.           len -= do_write;
  679.           buf += do_write;
  680.         }
  681.       Forbid();
  682.       if (ss->task)
  683.         Signal(ss->task, 1UL << u.u_pipe_sig);
  684.       Permit();
  685.     }
  686.     
  687.       ix_wakeup ((u_int)ss);
  688.     }
  689.  
  690.   release_stream(ss);
  691.  
  692.   syscall (SYS_sigsetmask, omask);
  693.   errno = err;
  694.   return really_written;
  695. }
  696.  
  697. int unp_write(struct file *f, const char *buf, int len)
  698. {
  699.   if (f->f_sock->state != UNS_ACCEPTED)
  700.     errno_return(ENOTCONN, -1);
  701.   return stream_write(f, buf, len);
  702. }
  703.  
  704. int unp_ioctl(struct file *f, int cmd, int inout, int arglen, caddr_t arg)
  705. {
  706.   int omask;
  707.   int result = 0;
  708.   struct sock_stream *ss;
  709.   
  710.   omask = syscall (SYS_sigsetmask, ~0);
  711.   ss = get_stream(f, TRUE);
  712.  
  713.   switch (cmd)
  714.     {
  715.     case FIONREAD:
  716.       {
  717.     unsigned int *pt = (unsigned int *)arg;
  718.  
  719.         if (ss == NULL)
  720.       *pt = 0;
  721.     else if (ss->reader < ss->writer)
  722.       *pt = ss->writer - ss->reader;
  723.     else if (ss->reader > ss->writer)
  724.       *pt = UNIX_SOCKET_SIZE - (ss->reader - ss->writer);
  725.     else
  726.       *pt = 0;
  727.     result = 0;
  728.         break;
  729.       }
  730.  
  731.     case FIONBIO:
  732.       {
  733.     result = f->f_flags & FNDELAY ? 1 : 0;
  734.     if (*(unsigned int *)arg)
  735.       f->f_flags |= FNDELAY;
  736.     else
  737.       f->f_flags &= ~FNDELAY;
  738.     /* I didn't find it documented in a manpage, but I assume, we
  739.      * should return the former state, not just zero.. */
  740.     break;
  741.       }
  742.  
  743.     case FIOASYNC:
  744.       {
  745.     /* DOESN'T WORK YET */
  746.  
  747.     int flags = *(unsigned long*)arg;
  748.     result = f->f_flags & FASYNC ? 1 : 0;
  749.     if (flags)
  750.       f->f_flags |= FASYNC;
  751.     else
  752.       f->f_flags &= ~FASYNC;
  753.  
  754.     /* ATTENTION: have to call some function here in the future !!! */
  755.  
  756.     /* I didn't find it documented in a manpage, but I assume, we
  757.      * should return the former state, not just zero.. */
  758.     break;
  759.       }
  760.  
  761.     case FIOCLEX:
  762.     case FIONCLEX:
  763.     case FIOSETOWN:
  764.     case FIOGETOWN:
  765.       /* this is no error, but nevertheless we don't take any actions.. */      
  766.       result = 0;
  767.       break;
  768.     }
  769.  
  770.   release_stream(ss);
  771.   syscall (SYS_sigsetmask, omask);
  772.   return result;
  773. }
  774.  
  775. int unp_select(struct file *f, int select_cmd, int io_mode, fd_set *ignored, u_long *also_ignored)
  776. {
  777.   struct sock_stream *ss = find_stream(f, io_mode == SELMODE_IN);
  778.  
  779.   SetSignal(0, 1UL << u.u_pipe_sig);  /* reset signal */
  780.   if (f->f_type != DTYPE_PIPE && ss == NULL)
  781.     {
  782.       struct ix_unix_name *un = f->f_sock->unix_name;
  783.       int result = 1UL << u.u_pipe_sig;
  784.  
  785.       if (un == NULL)
  786.         return 0;
  787.       ix_lock_base();
  788.       un->task = NULL;
  789.       if (select_cmd == SELCMD_CHECK || select_cmd == SELCMD_POLL)
  790.         {
  791.           if (io_mode == SELMODE_IN)
  792.             result = un->queue_index != 0;
  793.           if (io_mode == SELMODE_OUT)
  794.             result = 0;
  795.         }
  796.       else
  797.     un->task = FindTask(0);
  798.       ix_unlock_base();
  799.       return result;
  800.     }
  801.   ss->task = NULL;
  802.   if (select_cmd == SELCMD_CHECK || select_cmd == SELCMD_POLL)
  803.     {
  804.       /* we support both, read and write checks (hey, something new ;-)) */
  805.       if (io_mode == SELMODE_IN)
  806.     return (ss->reader != ss->writer || (ss->flags & UNF_NO_WRITER));
  807.       else if (io_mode == SELMODE_OUT)
  808.     return !(ss->reader == ss->writer + 1
  809.          || (ss->reader == ss->buffer 
  810.              && ss->writer == ss->buffer + UNIX_SOCKET_SIZE - 1))
  811.         || (ss->flags & UNF_NO_READER);
  812.     }
  813.  
  814.   ss->task = FindTask(0);
  815.   return 1UL << u.u_pipe_sig;
  816. }
  817.  
  818. int unp_close(struct file *f)
  819. {
  820.   ix_lock_base ();
  821.  
  822.   f->f_count--;
  823.  
  824.   if (f->f_count == 0 && f->f_sock)
  825.     {
  826.       close_stream(f, TRUE);
  827.       close_stream(f, FALSE);
  828.     }
  829.  
  830.   ix_unlock_base ();
  831.   return 0;
  832. }
  833.