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 / socket.c < prev    next >
C/C++ Source or Header  |  1996-10-01  |  11KB  |  563 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1996 by Jeff Shepherd
  5.  *  Portions Copyright (C) 1996 by Hans Verkuil
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #define _KERNEL
  23. #include "ixemul.h"
  24. #include "unp.h"
  25. #include "kprintf.h"
  26.  
  27. #include <sys/socket.h>
  28. #include <sys/socketvar.h>
  29. #include <sys/unix_socket.h>
  30. #include <sys/ioctl.h>
  31. #include <net/if.h>
  32. #include <net/route.h>
  33. #include <netinet/in.h>
  34. #include <machine/param.h>
  35. #include <string.h>
  36.  
  37. static struct file *getsock (int fdes);
  38. static int soo_read   (struct file *fp, char *buf, int len);
  39. static int soo_write  (struct file *fp, char *buf, int len);
  40. static int soo_ioctl  (struct file *fp, int cmd, int inout, int arglen, caddr_t data);
  41. static int soo_select (struct file *fp, int select_cmd, int io_mode, fd_set *ignored, u_long *also_ignored);
  42. static int soo_close  (struct file *fp);
  43. void _set_socket_params(struct file *fp, int type);
  44.  
  45. static void socket_cleanup(int ostat)
  46. {
  47.   if (CURSIG (&u))
  48.     SetSignal (0, SIGBREAKF_CTRL_C);
  49.  
  50.   u.p_stat = ostat;
  51.  
  52.   if (errno == EINTR)
  53.     setrun (FindTask (0));
  54.  
  55.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  56. }
  57.  
  58. static void socket_cleanup_epipe(int ostat)
  59. {
  60.   if (CURSIG (&u))
  61.     SetSignal (0, SIGBREAKF_CTRL_C);
  62.  
  63.   u.p_stat = ostat;
  64.  
  65.   /* the library doesn't send this to us of course ;-) */
  66.   if (errno == EPIPE)
  67.     _psignal (FindTask (0), SIGPIPE);
  68.  
  69.   if (errno == EINTR)
  70.     setrun (FindTask (0));
  71.  
  72.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  73. }
  74.  
  75. int
  76. socket (int domain, int type, int protocol)
  77. {
  78.   struct file *fp;
  79.   int fd, err, ostat, omask;
  80.  
  81.   if (domain == PF_UNIX)
  82.     return unp_socket(domain, type, protocol, NULL);
  83.  
  84.   if (!u.u_ixnetbase)
  85.     {
  86.       errno = ENOSYS;
  87.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  88.       return -1;
  89.     }
  90.  
  91.   ostat = u.p_stat;
  92.   u.p_stat = SWAIT;
  93.   omask = syscall (SYS_sigsetmask, ~0);
  94.  
  95.   do
  96.     {
  97.       if ((err = falloc (&fp, &fd)))
  98.         break;
  99.  
  100.       fp->f_so = netcall(NET__socket, domain, type, protocol);
  101.       err = (fp->f_so == -1) ? errno : 0;
  102.  
  103.       if (err)
  104.         {
  105.       /* free the allocated fd */
  106.           u.u_ofile[fd] = 0;
  107.           fp->f_count = 0;
  108.           break;
  109.         }
  110.  
  111.       _set_socket_params(fp, domain);
  112.     }
  113.   while (0);
  114.  
  115.   syscall (SYS_sigsetmask, omask);
  116.   errno = err;
  117.   socket_cleanup(ostat);
  118.   return err ? -1 : fd;
  119. }
  120.  
  121.  
  122. int
  123. bind (int s, const struct sockaddr *name, int namelen)
  124. {
  125.   struct file *fp = getsock (s);
  126.   int ostat, error;
  127.  
  128.   if (!fp)
  129.     return -1;
  130.  
  131.   if (fp->f_type == DTYPE_USOCKET)
  132.     return unp_bind(s, name, namelen);
  133.  
  134.   ostat = u.p_stat;
  135.   u.p_stat = SWAIT;
  136.   error = netcall(NET__bind, fp, name, namelen);
  137.   socket_cleanup(ostat);
  138.   return error;
  139. }
  140.  
  141. int
  142. listen (int s, int backlog)
  143. {
  144.   struct file *fp = getsock (s);
  145.   int ostat, error;
  146.  
  147.   if (!fp)
  148.     return -1;
  149.  
  150.   if (fp->f_type == DTYPE_USOCKET)
  151.     return unp_listen(s, backlog);
  152.  
  153.   ostat = u.p_stat;
  154.   u.p_stat = SWAIT;
  155.  
  156.   error = netcall(NET__listen, fp, backlog);
  157.   socket_cleanup(ostat);
  158.   return error;
  159. }
  160.  
  161. int
  162. accept (int s, struct sockaddr *name, int *namelen) 
  163. {
  164.   struct file *fp = getsock (s), *fp2;
  165.   int err, fd2, ostat;
  166.  
  167.   if (!fp)
  168.     return -1;
  169.  
  170.   if (fp->f_type == DTYPE_USOCKET)
  171.     return unp_accept(s, name, namelen);
  172.  
  173.   ostat = u.p_stat;
  174.   u.p_stat = SWAIT;
  175.  
  176.   do
  177.     {
  178.       /* first try to get a new descriptor. If that fails, don't even
  179.          bother to call the library */
  180.       if ((err = falloc (&fp2, &fd2)))
  181.         break;
  182.  
  183.       fp2->f_so = netcall(NET__accept, fp, name, namelen);
  184.       err = (fp2->f_so == -1) ? errno : 0;
  185.       if (err)
  186.         {
  187.           /* the second file */
  188.           u.u_ofile[fd2] = 0;
  189.           fp2->f_count = 0;
  190.           break;
  191.         }
  192.       _set_socket_params(fp2, (fp->f_type == DTYPE_SOCKET) ? AF_INET : AF_UNIX);
  193.     }
  194.   while (0);
  195.  
  196.   errno = err;
  197.   socket_cleanup(ostat);
  198.   return err ? -1 : fd2;
  199. }
  200.  
  201.  
  202. int
  203. connect (int s, const struct sockaddr *name, int namelen)
  204. {
  205.   struct file *fp = getsock (s);
  206.   int ostat, error;
  207.  
  208.   if (!fp)
  209.     return -1;
  210.  
  211.   if (fp->f_type == DTYPE_USOCKET)
  212.     return unp_connect(s, name, namelen);
  213.  
  214.   ostat = u.p_stat;
  215.   u.p_stat = SWAIT;
  216.  
  217.   error = netcall(NET__connect, fp, name, namelen);
  218.   socket_cleanup(ostat);
  219.   return error;
  220. }
  221.  
  222. int
  223. socketpair (int domain, int type, int protocol, int sv[2])
  224. {
  225.   errno = EPFNOSUPPORT;
  226.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  227.   return -1;
  228. }
  229.  
  230. int
  231. sendto (int s, const void *buf, int len, int flags, const struct sockaddr *to, int tolen)
  232. {
  233.   struct file *fp = getsock (s);
  234.   int ostat;
  235.   int rc;
  236.  
  237.   if (!fp || fp->f_type == DTYPE_USOCKET)
  238.     return -1;
  239.  
  240.   ostat = u.p_stat;
  241.   u.p_stat = SWAIT;
  242.  
  243.   rc = netcall(NET__sendto, fp, buf, len, flags, to, tolen);
  244.   socket_cleanup_epipe(ostat);
  245.   return rc;
  246. }
  247.  
  248.  
  249. int
  250. send (int s, const void *buf, int len, int flags)
  251. {
  252.   struct file *fp = getsock (s);
  253.   int ostat;
  254.   int rc;
  255.  
  256.   if (!fp)
  257.     return -1;
  258.  
  259.   if (fp->f_type == DTYPE_USOCKET)
  260.     return unp_send(s, buf, len, flags);
  261.  
  262.   ostat = u.p_stat;
  263.   u.p_stat = SWAIT;
  264.  
  265.   rc = netcall(NET__send, fp, buf, len, flags);
  266.   socket_cleanup_epipe(ostat);
  267.   return rc;
  268. }
  269.  
  270.  
  271. int
  272. sendmsg (int s, const struct msghdr *msg, int flags)
  273. {
  274.   struct file *fp = getsock (s);
  275.   int ostat, rc;
  276.  
  277.   if (!fp || fp->f_type == DTYPE_USOCKET)
  278.     return -1;
  279.  
  280.   ostat = u.p_stat;
  281.   u.p_stat = SWAIT;
  282.  
  283.   rc = netcall(NET__sendmsg, fp, msg, flags);
  284.   socket_cleanup_epipe(ostat);
  285.   return rc;
  286. }
  287.  
  288.  
  289. int
  290. recvfrom (int s, void *buf, int len, int flags, struct sockaddr *from, int *fromlen)
  291. {
  292.   struct file *fp = getsock (s);
  293.   int ostat, rc;
  294.  
  295.   if (!fp || fp->f_type == DTYPE_USOCKET)
  296.     return -1;
  297.  
  298.   ostat = u.p_stat;
  299.   u.p_stat = SWAIT;
  300.  
  301.   rc = netcall(NET__recvfrom, fp, buf, len, flags, from, fromlen);
  302.   socket_cleanup(ostat);
  303.   return rc;
  304. }
  305.  
  306.  
  307. int
  308. recv (int s, void *buf, int len, int flags)
  309. {
  310.   struct file *fp = getsock (s);
  311.   int ostat, rc;
  312.  
  313.   if (!fp)
  314.     return -1;
  315.  
  316.   if (fp->f_type == DTYPE_USOCKET)
  317.     return unp_recv(s, buf, len, flags);
  318.  
  319.   ostat = u.p_stat;
  320.   u.p_stat = SWAIT;
  321.  
  322.   rc = netcall(NET__recv, fp, buf, len, flags);
  323.   socket_cleanup(ostat);
  324.   return rc;
  325. }
  326.  
  327.  
  328. int
  329. recvmsg (int s, struct msghdr *msg, int flags)
  330. {
  331.   struct file *fp = getsock (s);
  332.   int ostat, rc;
  333.  
  334.   if (!fp || fp->f_type == DTYPE_USOCKET)
  335.     return -1;
  336.  
  337.   ostat = u.p_stat;
  338.   u.p_stat = SWAIT;
  339.  
  340.   rc = netcall(NET__recvmsg, fp, msg, flags);
  341.   socket_cleanup(ostat);
  342.   return rc;
  343. }
  344.  
  345.  
  346. int
  347. shutdown (int s, int how) 
  348. {
  349.   struct file *fp = getsock (s);
  350.   int ostat, err;
  351.  
  352.   if (!fp)
  353.     return -1;
  354.  
  355.   if (fp->f_type == DTYPE_USOCKET)
  356.     return unp_shutdown(s, how);
  357.  
  358.   ostat = u.p_stat;
  359.   u.p_stat = SWAIT;
  360.  
  361.   err = netcall(NET__shutdown, fp, how);
  362.   socket_cleanup(ostat);
  363.   return err;
  364. }
  365.  
  366.  
  367. int
  368. setsockopt (int s, int level, int name, const void *val, int valsize)
  369. {
  370.   struct file *fp = getsock (s);
  371.   int ostat, err;
  372.  
  373.   if (!fp)
  374.     return -1;
  375.  
  376.   if (fp->f_type == DTYPE_USOCKET)
  377.     return unp_setsockopt(s, level, name, val, valsize);
  378.  
  379.   ostat = u.p_stat;
  380.   u.p_stat = SWAIT;
  381.  
  382.   err = netcall(NET__setsockopt, fp, level, name, val, valsize);
  383.   socket_cleanup(ostat);
  384.   return err;
  385. }
  386.  
  387.  
  388. int
  389. getsockopt (int s, int level, int name, void *val, int *valsize)
  390. {
  391.   struct file *fp = getsock (s);
  392.   int ostat, err;
  393.  
  394.   if (!fp)
  395.     return -1;
  396.  
  397.   if (fp->f_type == DTYPE_USOCKET)
  398.     return unp_getsockopt(s, level, name, val, valsize);
  399.  
  400.   ostat = u.p_stat;
  401.   u.p_stat = SWAIT;
  402.  
  403.   err = netcall(NET__getsockopt, fp, level, name, val, valsize);
  404.   socket_cleanup(ostat);
  405.   return err;
  406. }
  407.  
  408.  
  409. /*
  410.  * Get socket name.
  411.  */
  412. int
  413. getsockname (int fdes, struct sockaddr *asa, int *alen)
  414. {
  415.   struct file *fp = getsock (fdes);
  416.   int ostat, err;
  417.  
  418.   if (!fp)
  419.     return -1;
  420.  
  421.   if (fp->f_type == DTYPE_USOCKET)
  422.     return unp_getsockname(fdes, asa, alen);
  423.  
  424.   ostat = u.p_stat;
  425.   u.p_stat = SWAIT;
  426.  
  427.   err = netcall(NET__getsockname, fp, asa, alen);
  428.   socket_cleanup(ostat);
  429.   return err;
  430. }
  431.  
  432. /*
  433.  * Get name of peer for connected socket.
  434.  */
  435. int
  436. getpeername (int fdes, struct sockaddr *asa, int *alen)
  437. {
  438.   struct file *fp = getsock (fdes);
  439.   int ostat, err;
  440.  
  441.   if (!fp)
  442.     return -1;
  443.  
  444.   if (fp->f_type == DTYPE_USOCKET)
  445.     return unp_getpeername(fdes, asa, alen);
  446.  
  447.   ostat = u.p_stat;
  448.   u.p_stat = SWAIT;
  449.  
  450.   err = netcall(NET__getpeername, fp, asa, alen);
  451.   socket_cleanup(ostat);
  452.   return err;
  453. }
  454.  
  455. static struct file *
  456. getsock (int fdes)
  457. {
  458.   struct file *fp;
  459.  
  460.   if ((unsigned) fdes >= NOFILE)
  461.     {
  462.       errno = EBADF;
  463.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  464.       return 0;
  465.     }
  466.  
  467.   fp = u.u_ofile[fdes];
  468.  
  469.   if (fp == NULL)
  470.     {
  471.       errno = EBADF;
  472.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  473.       return 0;
  474.     }
  475.  
  476.   if (fp->f_type != DTYPE_SOCKET && fp->f_type != DTYPE_USOCKET)
  477.     {
  478.       errno = ENOTSOCK;
  479.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  480.       return 0;
  481.     }
  482.  
  483.   if (fp->f_type == DTYPE_SOCKET && !u.u_ixnetbase)
  484.     {
  485.       errno = EPIPE; /* ????? */
  486.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  487.       return 0;
  488.     }
  489.  
  490.   return (fp);
  491. }
  492.  
  493. static int
  494. soo_read (struct file *fp, char *buf, int len)
  495. {
  496.   return netcall(NET__tcp_read, fp, buf, len);
  497. }
  498.  
  499. static int
  500. soo_write (struct file *fp, char *buf, int len)
  501. {
  502.   return netcall(NET__tcp_write, fp, buf, len);
  503. }
  504.  
  505. static int
  506. soo_ioctl (struct file *fp, int cmd, int inout, int arglen, caddr_t data)
  507. {
  508.   return netcall(NET__tcp_ioctl, fp, cmd, inout, arglen, data);
  509. }
  510.  
  511. /* ix_lock_base() is very fussy - so put most of the close() code here */
  512. static int
  513. soo_close (struct file *fp)
  514. {
  515.   int err;
  516.  
  517.   ix_lock_base ();
  518.   err = --fp->f_count;
  519.   ix_unlock_base ();
  520.  
  521.   if (err)
  522.     return 0;
  523.  
  524.   err = netcall(NET__tcp_close, fp);
  525.  
  526.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  527.   return err;
  528. }
  529.  
  530. static int
  531. soo_select(struct file *fp, int select_cmd, int io_mode,
  532.        fd_set *ignored, u_long *also_ignored)
  533. {
  534.   return netcall(NET__tcp_select, fp, select_cmd, io_mode, ignored, also_ignored);
  535. }
  536.  
  537. /* needed to set of the function pointers */
  538. void _set_socket_params(struct file *fp, int type)
  539. {
  540.   fp->f_stb.st_mode = 0666 | S_IFSOCK; /* not always, but.. */
  541.   fp->f_stb.st_size = 128;    /* sizeof mbuf. */
  542.   fp->f_stb.st_blksize = 128;
  543.   fp->f_flags = FREAD | FWRITE;
  544.   fp->f_type = ( (type == AF_INET) ? DTYPE_SOCKET : DTYPE_USOCKET);
  545.  
  546.   if (fp->f_type == DTYPE_SOCKET)
  547.     {
  548.       fp->f_read   = soo_read;
  549.       fp->f_write  = soo_write;
  550.       fp->f_ioctl  = soo_ioctl;
  551.       fp->f_close  = soo_close;
  552.       fp->f_select = soo_select;
  553.     }
  554.   else
  555.     {
  556.       fp->f_read   = unp_read;
  557.       fp->f_write  = unp_write;
  558.       fp->f_ioctl  = unp_ioctl;
  559.       fp->f_close  = unp_close;
  560.       fp->f_select = unp_select;
  561.     }
  562. }
  563.