#define DEBUG 0
-static int _tcp_socket(int protocol);
-static int _udp_socket(int protocol);
+static int _tcp_socket(int type, int protocol);
+static int _udp_socket(int type, int protocol);
static int _uds_socket(int type, int protocol);
+static void _socket_flags(int type, int *result);
int socket(int domain, int type, int protocol)
{
+ int sock_type;
+
+ sock_type = type & ~SOCK_FLAGS_MASK;
+
#if DEBUG
fprintf(stderr, "socket: domain %d, type %d, protocol %d\n",
domain, type, protocol);
return -1;
}
- if (domain == AF_UNIX && (type == SOCK_STREAM ||
- type == SOCK_DGRAM || type == SOCK_SEQPACKET))
+ if (domain == AF_UNIX && (sock_type == SOCK_STREAM ||
+ sock_type == SOCK_DGRAM ||
+ sock_type == SOCK_SEQPACKET))
return _uds_socket(type, protocol);
- if (domain == AF_INET && type == SOCK_STREAM)
- return _tcp_socket(protocol);
+ if (domain == AF_INET && sock_type == SOCK_STREAM)
+ return _tcp_socket(type, protocol);
- if (domain == AF_INET && type == SOCK_DGRAM)
- return _udp_socket(protocol);
+ if (domain == AF_INET && sock_type == SOCK_DGRAM)
+ return _udp_socket(type, protocol);
#if DEBUG
fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n",
return -1;
}
-static int _tcp_socket(int protocol)
+static void
+_socket_flags(int type, int *result)
+{
+ /* Process socket flags */
+ if (type & SOCK_CLOEXEC) {
+ *result |= O_CLOEXEC;
+ }
+ if (type & SOCK_NONBLOCK) {
+ *result |= O_NONBLOCK;
+ }
+ if (type & SOCK_NOSIGPIPE) {
+ *result |= O_NOSIGPIPE;
+ }
+}
+
+static int _tcp_socket(int type, int protocol)
{
- int fd;
+ int flags = O_RDWR;
+
if (protocol != 0 && protocol != IPPROTO_TCP)
{
#if DEBUG
errno= EPROTONOSUPPORT;
return -1;
}
- fd= open(TCP_DEVICE, O_RDWR);
- return fd;
+
+ _socket_flags(type, &flags);
+
+ return open(TCP_DEVICE, flags);
}
-static int _udp_socket(int protocol)
+static int _udp_socket(int type, int protocol)
{
- int r, fd, t_errno;
+ int r, fd, t_errno, flags = O_RDWR;
struct sockaddr_in sin;
if (protocol != 0 && protocol != IPPROTO_UDP)
errno= EPROTONOSUPPORT;
return -1;
}
- fd= open(UDP_DEVICE, O_RDWR);
+ _socket_flags(type, &flags);
+ fd= open(UDP_DEVICE, flags);
if (fd == -1)
return fd;
static int _uds_socket(int type, int protocol)
{
- int fd, r;
+ int fd, r, flags = O_RDWR, sock_type;
if (protocol != 0)
{
#if DEBUG
return -1;
}
- fd= open(UDS_DEVICE, O_RDWR);
+ _socket_flags(type, &flags);
+ fd= open(UDS_DEVICE, flags);
if (fd == -1) {
return fd;
}
/* set the type for the socket via ioctl (SOCK_DGRAM,
* SOCK_STREAM, SOCK_SEQPACKET, etc)
*/
- r= ioctl(fd, NWIOSUDSTYPE, &type);
+ sock_type = type & ~SOCK_FLAGS_MASK;
+ r= ioctl(fd, NWIOSUDSTYPE, &sock_type);
if (r == -1) {
int ioctl_errno;
break;
}
-
+ case F_GETNOSIGPIPE:
+ /* POSIX: return value other than -1 is flag is set, else -1 */
+ r = -1;
+ if (f->filp_flags & O_NOSIGPIPE)
+ r = 0;
+ break;
+ case F_SETNOSIGPIPE:
+ fl = (O_NOSIGPIPE);
+ f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
+ break;
default:
r = EINVAL;
}
* pipe_check *
*===========================================================================*/
int pipe_check(
-struct vnode *vp, /* the inode of the pipe */
+struct filp *filp, /* the filp of the pipe */
int rw_flag, /* READING or WRITING */
int oflags, /* flags set by open or fcntl */
int bytes, /* bytes to be read or written (all chunks) */
* and there is no writer, return 0 bytes. If a process is writing to a
* pipe and no one is reading from it, give a broken pipe error.
*/
+ struct vnode *vp;
off_t pos;
int r = OK;
+ vp = filp->filp_vno;
+
/* Reads start at the beginning; writes append to pipes */
if (notouch) /* In this case we don't actually care whether data transfer
* would succeed. See POSIX 1003.1-2008 */
/* Process is writing to a pipe. */
if (find_filp(vp, R_BIT) == NULL) {
- /* Process is writing, but there is no reader. Tell kernel to generate
- * a SIGPIPE signal. */
- if (!notouch) sys_kill(fp->fp_endpoint, SIGPIPE);
-
return(EPIPE);
}
int do_pipe(void);
int map_vnode(struct vnode *vp, endpoint_t fs_e);
void unpause(endpoint_t proc_e);
-int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes,
+int pipe_check(struct filp *filp, int rw_flag, int oflags, int bytes,
int notouch);
void release(struct vnode *vp, int op, int count);
void revive(endpoint_t proc_e, int returned);
register struct vnode *vp;
u64_t position, res_pos, new_pos;
unsigned int cum_io, cum_io_incr, res_cum_io;
- int op, oflags, r;
+ int op, r;
position = f->filp_pos;
- oflags = f->filp_flags;
vp = f->filp_vno;
r = OK;
cum_io = 0;
if (size > SSIZE_MAX) return(EINVAL);
- if (S_ISFIFO(vp->v_mode)) {
+ op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
+
+ if (S_ISFIFO(vp->v_mode)) { /* Pipes */
if (fp->fp_cum_io_partial != 0) {
panic("VFS: read_write: fp_cum_io_partial not clear");
}
r = rw_pipe(rw_flag, for_e, f, buf, size);
- return(r);
- }
-
- op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
-
- if (S_ISCHR(vp->v_mode)) { /* Character special files. */
+ } else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
dev_t dev;
int suspend_reopen;
suspend_reopen = (f->filp_state & FS_NEEDS_REOPEN);
dev = (dev_t) vp->v_sdev;
- r = dev_io(op, dev, for_e, buf, position, size, oflags,
+ r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags,
suspend_reopen);
if (r >= 0) {
cum_io = r;
} else { /* Regular files */
if (rw_flag == WRITING) {
/* Check for O_APPEND flag. */
- if (oflags & O_APPEND) position = cvul64(vp->v_size);
+ if (f->filp_flags & O_APPEND) position = cvul64(vp->v_size);
}
/* Issue request */
f->filp_pos = position;
- if (r == OK) return(cum_io);
+ if (r == EPIPE && rw_flag == WRITING) {
+ /* Process is writing, but there is no reader. Tell the kernel to
+ * generate s SIGPIPE signal.
+ */
+ if (!(f->filp_flags & O_NOSIGPIPE)) {
+ sys_kill(fp->fp_endpoint, SIGPIPE);
+ }
+ }
+
+ if (r == OK) {
+ return(cum_io);
+ }
return(r);
}
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
cum_io = fp->fp_cum_io_partial;
- r = pipe_check(vp, rw_flag, oflags, req_size, 0);
+ r = pipe_check(f, rw_flag, oflags, req_size, 0);
if (r <= 0) {
if (r == SUSPEND) pipe_suspend(f, buf, req_size);
return(r);
if ((*ops & (SEL_RD|SEL_ERR))) {
/* Check if we can read 1 byte */
- err = pipe_check(f->filp_vno, READING, f->filp_flags & ~O_NONBLOCK, 1,
+ err = pipe_check(f, READING, f->filp_flags & ~O_NONBLOCK, 1,
1 /* Check only */);
if (err != SUSPEND)
if ((*ops & (SEL_WR|SEL_ERR))) {
/* Check if we can write 1 byte */
- err = pipe_check(f->filp_vno, WRITING, f->filp_flags & ~O_NONBLOCK, 1,
+ err = pipe_check(f, WRITING, f->filp_flags & ~O_NONBLOCK, 1,
1 /* Check only */);
if (err != SUSPEND)
* restart
*/
#define O_CLOEXEC 020000 /* close on exec */
-
+#if defined(_NETBSD_SOURCE)
+#define O_NOSIGPIPE 040000 /* don't deliver sigpipe */
+#endif
#ifndef __minix /* NOT SUPPORTED! */
#if defined(_NETBSD_SOURCE)
#define F_SETLK 6 /* set record locking information */
#define F_SETLKW 7 /* set record locking info; wait if blocked */
#define F_FREESP 8 /* free a section of a regular file */
+#if defined(_NETBSD_SOURCE)
+#define F_GETNOSIGPIPE 9
+#define F_SETNOSIGPIPE 10
+#endif
/* File descriptor flags used for fcntl(). POSIX Table 6-2. */
#define FD_CLOEXEC 1 /* close on exec flag for third arg of fcntl */