summaryrefslogtreecommitdiffstats
path: root/compat
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2014-08-09 20:17:26 +0100
committerThomas Adam <thomas@xteddy.org>2014-08-09 20:32:01 +0100
commit0e23ab4ccef2848a90b876db3c0e6a796422544c (patch)
treedcce67c06b757b283120822be7172fe3da6e60d2 /compat
parent92997b781a035626bef4e84fbcd7f2282f761a3c (diff)
Sync libutil from OpenBSD (imsg)
Changes in the imsg API need to be reflected here as tmux wasn't creating any clients because of it.
Diffstat (limited to 'compat')
-rw-r--r--compat/imsg-buffer.c38
-rw-r--r--compat/imsg.c99
-rw-r--r--compat/imsg.h11
3 files changed, 110 insertions, 38 deletions
diff --git a/compat/imsg-buffer.c b/compat/imsg-buffer.c
index 2ddf0f77..2242e01e 100644
--- a/compat/imsg-buffer.c
+++ b/compat/imsg-buffer.c
@@ -1,5 +1,5 @@
/* $Id$ */
-/* $OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
+/* $OpenBSD: imsg-buffer.c,v 1.4 2014/06/30 00:25:17 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -17,17 +17,19 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <unistd.h>
#include "tmux.h"
+#include "imsg.h"
int ibuf_realloc(struct ibuf *, size_t);
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
@@ -158,22 +160,23 @@ ibuf_write(struct msgbuf *msgbuf)
i++;
}
+again:
if ((n = writev(msgbuf->fd, iov, i)) == -1) {
- if (errno == EAGAIN || errno == ENOBUFS ||
- errno == EINTR) /* try later */
- return (0);
- else
- return (-1);
+ if (errno == EINTR)
+ goto again;
+ if (errno == ENOBUFS)
+ errno = EAGAIN;
+ return (-1);
}
if (n == 0) { /* connection closed */
errno = 0;
- return (-2);
+ return (0);
}
msgbuf_drain(msgbuf, n);
- return (0);
+ return (1);
}
void
@@ -257,17 +260,18 @@ msgbuf_write(struct msgbuf *msgbuf)
*(int *)CMSG_DATA(cmsg) = buf->fd;
}
+again:
if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
- if (errno == EAGAIN || errno == ENOBUFS ||
- errno == EINTR) /* try later */
- return (0);
- else
- return (-1);
+ if (errno == EINTR)
+ goto again;
+ if (errno == ENOBUFS)
+ errno = EAGAIN;
+ return (-1);
}
if (n == 0) { /* connection closed */
errno = 0;
- return (-2);
+ return (0);
}
/*
@@ -281,7 +285,7 @@ msgbuf_write(struct msgbuf *msgbuf)
msgbuf_drain(msgbuf, n);
- return (0);
+ return (1);
}
void
diff --git a/compat/imsg.c b/compat/imsg.c
index c4dd191d..c99cda1f 100644
--- a/compat/imsg.c
+++ b/compat/imsg.c
@@ -1,5 +1,5 @@
/* $Id$ */
-/* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
+/* $OpenBSD: imsg.c,v 1.6 2014/06/30 00:26:22 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -17,20 +17,55 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <unistd.h>
#include "tmux.h"
+#include "imsg.h"
+
+int imsg_fd_overhead = 0;
int imsg_get_fd(struct imsgbuf *);
+int available_fds(unsigned int);
+
+/* TA: 2014-09-08: Note that the original code calls getdtablecount() which is
+ * OpenBSD specific. Until such time that it's ported elsewhere from
+ * <unistd.h>, I've mimicked what OpenSMTPD are doing, by using available_fds()
+ * instead.
+ */
+
+int
+available_fds(unsigned int n)
+{
+ unsigned int i;
+ int ret, fds[256];
+
+ if (n > (sizeof(fds)/sizeof(fds[0])))
+ return (1);
+
+ ret = 0;
+ for (i = 0; i < n; i++) {
+ fds[i] = -1;
+ if ((fds[i] = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ ret = 1;
+ break;
+ }
+ }
+
+ for (i = 0; i < n && fds[i] >= 0; i++)
+ close(fds[i]);
+
+ return (ret);
+}
+
void
imsg_init(struct imsgbuf *ibuf, int fd)
{
@@ -49,10 +84,10 @@ imsg_read(struct imsgbuf *ibuf)
struct cmsghdr *cmsg;
union {
struct cmsghdr hdr;
- char buf[CMSG_SPACE(sizeof(int) * 16)];
+ char buf[CMSG_SPACE(sizeof(int) * 1)];
} cmsgbuf;
struct iovec iov;
- ssize_t n;
+ ssize_t n = -1;
int fd;
struct imsg_fd *ifd;
@@ -65,11 +100,23 @@ imsg_read(struct imsgbuf *ibuf)
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
+ return (-1);
+
+again:
+ if (available_fds(imsg_fd_overhead +
+ (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) {
+ errno = EAGAIN;
+ free(ifd);
+ return (-1);
+ }
+
if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
- if (errno != EINTR && errno != EAGAIN) {
- return (-1);
- }
- return (-2);
+ if (errno == EMSGSIZE)
+ goto fail;
+ if (errno != EINTR && errno != EAGAIN)
+ goto fail;
+ goto again;
}
ibuf->r.wpos += n;
@@ -78,17 +125,33 @@ imsg_read(struct imsgbuf *ibuf)
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
- fd = (*(int *)CMSG_DATA(cmsg));
- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
- close(fd);
- return (-1);
+ int i;
+ int j;
+
+ /*
+ * We only accept one file descriptor. Due to C
+ * padding rules, our control buffer might contain
+ * more than one fd, and we must close them.
+ */
+ j = ((char *)cmsg + cmsg->cmsg_len -
+ (char *)CMSG_DATA(cmsg)) / sizeof(int);
+ for (i = 0; i < j; i++) {
+ fd = ((int *)CMSG_DATA(cmsg))[i];
+ if (ifd != NULL) {
+ ifd->fd = fd;
+ TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
+ entry);
+ ifd = NULL;
+ } else
+ close(fd);
}
- ifd->fd = fd;
- TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry);
}
/* we do not handle other ctl data level */
}
+fail:
+ if (ifd)
+ free(ifd);
return (n);
}
@@ -112,7 +175,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
return (0);
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
- if ((imsg->data = malloc(datalen)) == NULL && datalen != 0)
+ if ((imsg->data = malloc(datalen)) == NULL)
return (-1);
if (imsg->hdr.flags & IMSGF_HASFD)
@@ -134,7 +197,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
int
imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
- pid_t pid, int fd, void *data, u_int16_t datalen)
+ pid_t pid, int fd, const void *data, u_int16_t datalen)
{
struct ibuf *wbuf;
@@ -204,7 +267,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
}
int
-imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
+imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen)
{
if (datalen)
if (ibuf_add(msg, data, datalen) == -1) {
diff --git a/compat/imsg.h b/compat/imsg.h
index f8a78e22..49a2aeb3 100644
--- a/compat/imsg.h
+++ b/compat/imsg.h
@@ -1,5 +1,5 @@
/* $Id$ */
-/* $OpenBSD: imsg.h,v 1.4 2010/05/26 13:56:07 nicm Exp $ */
+/* $OpenBSD: imsg.h,v 1.3 2013/12/26 17:32:33 eric Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -21,6 +21,9 @@
#include "tmux.h"
+#ifndef _IMSG_H_
+#define _IMSG_H_
+
#define IBUF_READ_SIZE 65535
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
#define MAX_IMSGSIZE 16384
@@ -98,13 +101,15 @@ void imsg_init(struct imsgbuf *, int);
ssize_t imsg_read(struct imsgbuf *);
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
- int, void *, u_int16_t);
+ int, const void *, u_int16_t);
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
int, const struct iovec *, int);
struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
u_int16_t);
-int imsg_add(struct ibuf *, void *, u_int16_t);
+int imsg_add(struct ibuf *, const void *, u_int16_t);
void imsg_close(struct imsgbuf *, struct ibuf *);
void imsg_free(struct imsg *);
int imsg_flush(struct imsgbuf *);
void imsg_clear(struct imsgbuf *);
+
+#endif