📄 rtems_syscall.c
字号:
/* * $Id: rtems_syscall.c,v 1.17.2.1 2003/05/29 19:09:45 joel Exp $ */#include <string.h>#include <stdarg.h>/* #include <stdlib.h> */#include <stdio.h>#include <errno.h>#include <rtems.h>#include <rtems/libio.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <sys/errno.h>#include <sys/types.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/protosw.h>#include <sys/proc.h>#include <sys/fcntl.h>#include <sys/filio.h>#include <sys/sysctl.h>#include <net/if.h>#include <net/route.h>/* * Hooks to RTEMS I/O system */static const rtems_filesystem_file_handlers_r socket_handlers;int rtems_bsdnet_makeFdForSocket(void *so, const rtems_filesystem_file_handlers_r *h);struct socket *rtems_bsdnet_fdToSocket(int fd);/* * Package system call argument into mbuf. */static intsockargstombuf (struct mbuf **mp, const void *buf, int buflen, int type){ struct mbuf *m; if ((u_int)buflen > MLEN) return (EINVAL); m = m_get(M_WAIT, type); if (m == NULL) return (ENOBUFS); m->m_len = buflen; memcpy (mtod(m, caddr_t), buf, buflen); *mp = m; if (type == MT_SONAME) { struct sockaddr *sa; sa = mtod(m, struct sockaddr *); sa->sa_len = buflen; } return 0;}/* ********************************************************************* * BSD-style entry points * ********************************************************************* */intsocket (int domain, int type, int protocol){ int fd; int error; struct socket *so; rtems_bsdnet_semaphore_obtain (); error = socreate(domain, &so, type, protocol, NULL); if (error == 0) { fd = rtems_bsdnet_makeFdForSocket (so, &socket_handlers); if (fd < 0) soclose (so); } else { errno = error; fd = -1; } rtems_bsdnet_semaphore_release (); return fd;}intbind (int s, struct sockaddr *name, int namelen){ int error; int ret = -1; struct socket *so; struct mbuf *nam; rtems_bsdnet_semaphore_obtain (); if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) { error = sockargstombuf (&nam, name, namelen, MT_SONAME); if (error == 0) { error = sobind (so, nam); if (error == 0) ret = 0; else errno = error; m_freem (nam); } else { errno = error; } } rtems_bsdnet_semaphore_release (); return ret;}intconnect (int s, struct sockaddr *name, int namelen){ int error; int ret = -1; struct socket *so; struct mbuf *nam; rtems_bsdnet_semaphore_obtain (); if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { rtems_bsdnet_semaphore_release (); return -1; } if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { errno = EALREADY; rtems_bsdnet_semaphore_release (); return -1; } error = sockargstombuf (&nam, name, namelen, MT_SONAME); if (error) { errno = error; rtems_bsdnet_semaphore_release (); return -1; } error = soconnect (so, nam); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { m_freem(nam); errno = EINPROGRESS; rtems_bsdnet_semaphore_release (); return -1; } while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = soconnsleep (so); if (error) break; } if (error == 0) { error = so->so_error; so->so_error = 0; } bad: so->so_state &= ~SS_ISCONNECTING; m_freem (nam); if (error) errno = error; else ret = 0; rtems_bsdnet_semaphore_release (); return ret;}intlisten (int s, int backlog){ int error; int ret = -1; struct socket *so; rtems_bsdnet_semaphore_obtain (); if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) { error = solisten (so, backlog); if (error == 0) ret = 0; else errno = error; } rtems_bsdnet_semaphore_release (); return ret;}intaccept (int s, struct sockaddr *name, int *namelen){ int fd; struct socket *head, *so; struct mbuf *nam; rtems_bsdnet_semaphore_obtain (); if ((head = rtems_bsdnet_fdToSocket (s)) == NULL) { rtems_bsdnet_semaphore_release (); return -1; } if ((head->so_options & SO_ACCEPTCONN) == 0) { errno = EINVAL; rtems_bsdnet_semaphore_release (); return -1; } if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) { errno = EWOULDBLOCK; rtems_bsdnet_semaphore_release (); return -1; } while (head->so_comp.tqh_first == NULL && head->so_error == 0) { if (head->so_state & SS_CANTRCVMORE) { head->so_error = ECONNABORTED; break; } head->so_error = soconnsleep (head); } if (head->so_error) { errno = head->so_error; head->so_error = 0; rtems_bsdnet_semaphore_release (); return -1; } so = head->so_comp.tqh_first; TAILQ_REMOVE(&head->so_comp, so, so_list); head->so_qlen--; fd = rtems_bsdnet_makeFdForSocket (so, &socket_handlers); if (fd < 0) { TAILQ_INSERT_HEAD(&head->so_comp, so, so_list); head->so_qlen++; soconnwakeup (head); rtems_bsdnet_semaphore_release (); return -1; } so->so_state &= ~SS_COMP; so->so_head = NULL; nam = m_get(M_WAIT, MT_SONAME); (void) soaccept(so, nam); if (name) { /* check length before it is destroyed */ if (*namelen > nam->m_len) *namelen = nam->m_len; memcpy (name, mtod(nam, caddr_t), *namelen); } m_freem(nam); rtems_bsdnet_semaphore_release (); return (fd);}/* * Shutdown routine */intshutdown (int s, int how){ struct socket *so; int error; rtems_bsdnet_semaphore_obtain (); if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { rtems_bsdnet_semaphore_release (); return -1; } error = soshutdown(so, how); rtems_bsdnet_semaphore_release (); if (error) { errno = error; return -1; } return 0;}/* * All `transmit' operations end up calling this routine. */ssize_tsendmsg (int s, const struct msghdr *mp, int flags){ int ret = -1; int error; struct uio auio; struct iovec *iov; struct socket *so; struct mbuf *to, *control; int i; int len; rtems_bsdnet_semaphore_obtain (); if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { rtems_bsdnet_semaphore_release (); return -1; } auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_WRITE; auio.uio_offset = 0; auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { if ((auio.uio_resid += iov->iov_len) < 0) { errno = EINVAL; rtems_bsdnet_semaphore_release (); return -1; } } if (mp->msg_name) { error = sockargstombuf (&to, mp->msg_name, mp->msg_namelen, MT_SONAME); if (error) { errno = error; rtems_bsdnet_semaphore_release (); return -1; } } else { to = NULL; } if (mp->msg_control) { if (mp->msg_controllen < sizeof (struct cmsghdr)) { errno = EINVAL; if (to) m_freem(to); rtems_bsdnet_semaphore_release (); return -1; } sockargstombuf (&control, mp->msg_control, mp->msg_controllen, MT_CONTROL); } else { control = NULL; } len = auio.uio_resid; error = sosend (so, to, &auio, (struct mbuf *)0, control, flags); if (error) { if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK)) error = 0; } if (error) errno = error; else ret = len - auio.uio_resid; if (to) m_freem(to); rtems_bsdnet_semaphore_release (); return (ret);}/* * Send a message to a host */ssize_tsendto (int s, const void *buf, size_t buflen, int flags, const struct sockaddr *to, int tolen){ struct msghdr msg; struct iovec iov; iov.iov_base = (void *)buf; iov.iov_len = buflen; msg.msg_name = (caddr_t)to; msg.msg_namelen = tolen; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; return sendmsg (s, &msg, flags);}/* * Send a message to a connected host */ssize_tsend (int s, const void *buf, size_t buflen, int flags){ return sendto (s, buf, buflen, flags, NULL, 0);}/* * All `receive' operations end up calling this routine. */ssize_trecvmsg (int s, struct msghdr *mp, int flags){ int ret = -1; int error; struct uio auio; struct iovec *iov; struct socket *so; struct mbuf *from = NULL, *control = NULL; int i; int len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -