+ if (fp->f_type != DTYPE_SOCKET) {
+ u.u_error = ENOTSOCK;
+ goto bad;
+ }
+ s = splnet();
+ so = fp->f_socket;
+ if ((so->so_options & SO_ACCEPTCONN) == 0) {
+ u.u_error = EINVAL;
+ splx(s);
+ goto bad;
+ }
+ if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
+ u.u_error = EWOULDBLOCK;
+ splx(s);
+ goto bad;
+ }
+ while (so->so_qlen == 0 && so->so_error == 0) {
+ if (so->so_state & SS_CANTRCVMORE) {
+ so->so_error = ECONNABORTED;
+ break;
+ }
+ sleep((caddr_t)&so->so_timeo, PZERO+1);
+ }
+ if (so->so_error) {
+ u.u_error = so->so_error;
+ splx(s);
+ goto bad;
+ }
+ if ((so->so_options & SO_NEWFDONCONN) == 0) {
+ struct socket *nso = so->so_q;
+ (void) soqremque(nso, 1);
+ u.u_error = soclose(so, 1);
+ fp->f_socket = nso;
+ nso->so_q = 0;
+ so = nso;
+ goto ret;
+ }
+ if (ufalloc() < 0) {
+ splx(s);
+ goto bad;
+ }
+ fp = falloc();
+ if (fp == 0) {
+ u.u_ofile[u.u_r.r_val1] = 0;
+ splx(s);
+ goto bad;
+ }
+ { struct socket *aso = so->so_q;
+ if (soqremque(aso, 1) == 0)
+ panic("accept");
+ so = aso;
+ }
+ fp->f_type = DTYPE_SOCKET;
+ fp->f_flag = FREAD|FWRITE;
+ fp->f_socket = so;
+ret:
+ nam = m_get(M_WAIT, MT_SONAME);
+ (void) soaccept(so, nam, &aopt);
+ if (uap->name) {
+ if (namelen > nam->m_len)
+ namelen = nam->m_len;
+ /* SHOULD COPY OUT A CHAIN HERE */
+ (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
+ (u_int)namelen);
+ (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
+ sizeof (*uap->anamelen));
+ }
+ m_freem(nam);
+ splx(s);