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