commit - 70b68b95fb01cb2b260ca9a92849088b4ee34fb2
commit + 056b9939639819c1a2e85f0e73fc02dda5b27b78
blob - 004de43f19fb128200743738afea48b0a2631923
blob + 2d9b5159b468ad7de6156909a7d880704f13c4ca
--- regress/Makefile
+++ regress/Makefile
-SUBDIR= agentcfg anthropic buf conf deploy diff editor http journal json log markdown \
+SUBDIR= agentcfg anthropic buf conf deploy diff editor http imsgev journal json log markdown \
model_window openai output print sandbox skills sse term tools turn web xmalloc
.include <bsd.subdir.mk>
blob - d397b20feb0f182630b200d95785c71f75775960
blob + 5d18e65afa8d09013140fc89fe12daa92eeb6006
--- regress/README
+++ regress/README
steady pledge before untrusted
input; forbidden syscalls trip
PLDG violations)
-I10 mutual distrust across roles imsg length/type validation in
- worker.c/coord.c; hub-and-spoke
+I10 mutual distrust across roles imsgev (partially consumed payloads
+ fail closed); imsg length/type
+ validation in worker.c/coord.c; hub-and-spoke
authority map in proto.h; turn
(a hostile second terminal cannot
flip a committed turn; a tool
(coord.c); tools proves anchored
process-group cleanup even after
forced executor death
-I13 length-aware strings buf, json (NUL round-trip),
+I13 length-aware strings buf, json (NUL round-trip), imsgev
+ (empty and embedded-NUL payload views),
sse (NUL transparency),
anthropic, openai, http, web, output
(NUL-bearing framing, headers, bodies,
src/fugu/priv.c, coord.c sandbox (spawn/handshake/teardown),
turn (lead and subagent turn loops)
src/fugu/journal.c journal, turn
-src/common/imsgev.c, worker.c sandbox (worker runtime)
+src/common/imsgev.c imsgev (whole-payload views); sandbox
+ (event runtime)
+src/common/worker.c sandbox (worker runtime)
src/fugu-api (request/stream) turn (correlated concurrent lead/agent
requests), print (deadline/retry/long-key
reflection), openai (real requests + SSE)
blob - /dev/null
blob + 93314c1cf5366d4e2cbfa834d399e80834883a5f (mode 644)
--- /dev/null
+++ regress/imsgev/Makefile
+PROG= imsgev_test
+SRCS= imsgev_test.c imsgev.c log.c
+
+LDADD= -levent -lutil
+DPADD= ${LIBEVENT} ${LIBUTIL}
+
+.include <bsd.regress.mk>
blob - /dev/null
blob + f2fdf7f0d1295eab089010d5678c8daf04235d2d (mode 644)
--- /dev/null
+++ regress/imsgev/imsgev_test.c
+/*
+ * Copyright (c) 2026 Isaac <isaac@itm.works>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <err.h>
+#include <errno.h>
+#include <imsg.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "imsgev.h"
+
+#include "regress.h"
+
+static void
+make_imsg(const void *data, size_t len, struct imsgbuf *receiver,
+ struct imsg *imsg)
+{
+ struct imsgbuf sender;
+ int fds[2];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fds) == -1)
+ err(1, "socketpair");
+ if (imsgbuf_init(&sender, fds[0]) == -1)
+ err(1, "imsgbuf_init sender");
+ if (imsgbuf_init(receiver, fds[1]) == -1)
+ err(1, "imsgbuf_init receiver");
+ if (imsg_compose(&sender, 1, 0, -1, -1, data, len) == -1)
+ err(1, "imsg_compose");
+ if (imsgbuf_flush(&sender) == -1)
+ err(1, "imsgbuf_flush");
+ if (imsgbuf_read(receiver) != 1)
+ errx(1, "imsgbuf_read");
+ if (imsgbuf_get(receiver, imsg) != 1)
+ errx(1, "imsgbuf_get");
+ imsgbuf_clear(&sender);
+ close(fds[0]);
+ close(fds[1]);
+}
+
+int
+main(void)
+{
+ static const u_char binary[] = { 'a', '\0', 'b' };
+ struct imsgev_payload payload;
+ struct imsgbuf receiver;
+ struct imsg imsg;
+ u_char byte;
+
+ make_imsg(NULL, 0, &receiver, &imsg);
+ payload.data = (const u_char *)1;
+ payload.len = 1;
+ CHECK(imsgev_get_payload(&imsg, &payload) == 0);
+ CHECK(payload.data == NULL);
+ CHECK(payload.len == 0);
+ imsg_free(&imsg);
+ imsgbuf_clear(&receiver);
+
+ make_imsg(binary, sizeof(binary), &receiver, &imsg);
+ CHECK(imsgev_get_payload(&imsg, &payload) == 0);
+ CHECK(payload.len == sizeof(binary));
+ CHECK(payload.data != NULL &&
+ memcmp(payload.data, binary, sizeof(binary)) == 0);
+ imsg_free(&imsg);
+ imsgbuf_clear(&receiver);
+
+ make_imsg(binary, sizeof(binary), &receiver, &imsg);
+ CHECK(imsg_get_buf(&imsg, &byte, sizeof(byte)) == 0);
+ CHECK(byte == 'a');
+ payload.data = (const u_char *)1;
+ payload.len = SIZE_MAX;
+ errno = 0;
+ CHECK(imsgev_get_payload(&imsg, &payload) == -1);
+ CHECK(errno == EBADMSG);
+ CHECK(payload.data == NULL);
+ CHECK(payload.len == 0);
+ imsg_free(&imsg);
+ imsgbuf_clear(&receiver);
+
+ REGRESS_END();
+}
blob - 2cee5e52e25388738c7402a78e90bdad830f7263
blob + eae76c222a9645b9bd3757daa9fcf0204a9b45c7
--- src/common/imsgev.c
+++ src/common/imsgev.c
#include <sys/types.h>
#include <event.h>
+#include <errno.h>
#include <imsg.h>
#include <stdint.h>
return (ret);
}
+int
+imsgev_get_payload(struct imsg *imsg, struct imsgev_payload *payload)
+{
+ struct ibuf ib;
+ size_t len;
+
+ payload->data = NULL;
+ payload->len = 0;
+ if (imsg->hdr.len < IMSG_HEADER_SIZE) {
+ errno = EBADMSG;
+ return (-1);
+ }
+ len = imsg_get_len(imsg);
+ if (len != imsg->hdr.len - IMSG_HEADER_SIZE) {
+ errno = EBADMSG;
+ return (-1);
+ }
+ if (len == 0)
+ return (0);
+ if (imsg_get_ibuf(imsg, &ib) == -1 || ibuf_size(&ib) != len) {
+ errno = EBADMSG;
+ return (-1);
+ }
+ payload->data = ibuf_data(&ib);
+ payload->len = ibuf_size(&ib);
+ return (0);
+}
+
void
imsgev_clear(struct imsgev *iev)
{
blob - 912e02e97f21c2bd74e1163842b466f0df041b0e
blob + c19e3d504553e550f77a3268b8d2a63617840730
--- src/common/imsgev.h
+++ src/common/imsgev.h
short events;
};
+/*
+ * A whole, unconsumed imsg payload. The bytes are borrowed until
+ * imsg_free(). An empty payload is a successful { NULL, 0 } view;
+ * malformed or previously consumed payloads fail with EBADMSG.
+ */
+struct imsgev_payload {
+ const u_char *data;
+ size_t len;
+};
+
void imsgev_init(struct imsgev *, int, void (*)(int, short, void *),
void *);
void imsgev_add(struct imsgev *);
int imsgev_compose(struct imsgev *, uint32_t, uint32_t, pid_t, int,
const void *, size_t);
+int imsgev_get_payload(struct imsg *, struct imsgev_payload *);
void imsgev_clear(struct imsgev *);
#endif /* IMSGEV_H */
blob - 5b7aab176b5f31d13771bcc71ec0e14336c9c592
blob + 6a041592b8100a7964a10178d9a337589172090f
--- src/fugu/coord.c
+++ src/fugu/coord.c
return (n);
}
-static const u_char *
-imsg_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
static int
protect_has(const struct buf *b, const char *path)
{
static void
stream_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
uint32_t type = imsg_get_type(imsg);
if (imsg_get_id(imsg) != c->lead_api_id)
fatalx("lead provider correlation mismatch");
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get provider stream payload");
+ p = payload.data;
+ len = payload.len;
switch (type) {
case FUGU_IMSG_A_TEXT:
static void
tool_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
if (c->wait != WAIT_TOOL)
return;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get tool result payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_TOOL_OUT:
tool_ctl_event(struct coord *c, struct imsg *imsg)
{
struct tool_turn_ack ack;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get tool Turn ACK payload");
+ p = payload.data;
+ len = payload.len;
if (c->tool_ctl_expected == 0 || p == NULL || len != sizeof(ack))
fatalx("unexpected tool Turn ACK");
memcpy(&ack, p, sizeof(ack));
static void
web_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
return;
if (imsg_get_id(imsg) != c->web_id)
fatalx("web result correlation mismatch");
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get web result payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_WEB_OUT:
static void
ctx_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
if (c->wait != WAIT_CTX)
return;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get project context payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_CTX_DATA:
static void
ui_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get UI input payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_UI_SUBMIT:
/* A submit only lands while idle: mid-turn, the tty queues
static void
model_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
if (!c->ui)
return; /* line mode never asks (2.2) */
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get model listing payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_MODEL:
{
static void
compose_event(struct coord *c, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get compose payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_UI_COMPOSE:
if (len == 0)
static void
agent_provider_event(struct subagent *a, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
uint32_t type = imsg_get_type(imsg);
if (!a->api_inflight)
fatalx("provider event for idle subagent");
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get relayed provider payload");
+ p = payload.data;
+ len = payload.len;
if (!a->done && imsgev_compose(&a->iev, type, 0, -1, -1, p, len) == -1)
fatal("relay provider event to subagent");
if (type == FUGU_IMSG_A_DONE || type == FUGU_IMSG_A_ERROR)
agent_web_event(struct subagent *a, struct imsg *imsg)
{
struct coord *c = a->coord;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
uint32_t outtype;
if (!a->web_inflight || c->agent_web_active != a ||
c->web_busy_id != a->web_id || imsg_get_id(imsg) != a->web_id)
fatalx("web event for idle subagent");
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get relayed web payload");
+ p = payload.data;
+ len = payload.len;
if (imsg_get_type(imsg) == FUGU_IMSG_WEB_OUT)
outtype = FUGU_IMSG_AGENT_WEB_OUT;
else if (imsg_get_type(imsg) == FUGU_IMSG_WEB_RESULT)
struct coord *c = a->coord;
struct imsgbuf *ibuf = &a->iev.ibuf;
struct imsg imsg;
+ struct imsgev_payload payload;
const u_char *p;
struct tool_req req;
ssize_t n;
if (n == 0)
break;
type = imsg_get_type(&imsg);
- p = imsg_bytes(&imsg, &len);
+ if (imsgev_get_payload(&imsg, &payload) == -1)
+ fatal("get subagent broker payload");
+ p = payload.data;
+ len = payload.len;
switch (type) {
case FUGU_IMSG_READY:
if (len != 0 || a->ready)
blob - 0d4591c227b88282ec35a94f224dd3819ac44845
blob + 2935e1ff82c36ffc61949854b34bf9e6fe29eda1
--- src/fugu-api/main.c
+++ src/fugu-api/main.c
return (tls_default_ca_cert_file());
}
-/* A read-only view of an imsg's payload; valid until imsg_free. */
-static const u_char *
-imsg_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
/* A key crosses the wire as trailing bytes; it feeds an HTTP header,
* so it must be NUL-free (I13). */
static char *
{
struct api *a = w->ctx;
struct hello_api h;
+ struct imsgev_payload payload;
struct prov *v;
const u_char *p;
size_t len;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get API HELLO payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len < sizeof(h))
fatalx("fugu-api: short HELLO");
memcpy(&h, p, sizeof(h));
prov_add(struct api *a, struct imsg *imsg)
{
struct hello_prov hp;
+ struct imsgev_payload payload;
struct prov *v;
const u_char *p;
size_t len;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get PROV payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len < sizeof(hp))
fatalx("fugu-api: short PROV");
memcpy(&hp, p, sizeof(hp));
{
struct api *a = w->ctx;
struct api_request *r;
+ struct imsgev_payload payload;
size_t len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_REQUEST: {
- const u_char *p = imsg_bytes(imsg, &len);
+ const u_char *p;
uint32_t id = imsg_get_id(imsg);
size_t cap, growth;
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get REQUEST payload");
+ p = payload.data;
+ len = payload.len;
if ((r = request_find(a, id)) == NULL)
r = request_new(w, id);
if (r->phase != REQ_ASSEMBLY && r->phase != REQ_REJECTED)
blob - fb3c99fc91d2262de753a404e38cb12639ff8994
blob + 7840fd7766fb54edcb5b70b8462764f98d184973
--- src/fugu-editor/main.c
+++ src/fugu-editor/main.c
static volatile sig_atomic_t edit_child; /* running editor pgid */
static char edit_path[64]; /* the live temp file, for SIGTERM cleanup */
-/* Borrow an imsg's payload bytes (length-checked by the caller). */
-static const u_char *
-imsg_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
/* A coordinator death mid-compose must not orphan the user's editor or
* leave the seeded temp file behind ("the temp file never survives"). */
static void
static int
edit_dispatch(struct worker *w, struct imsg *imsg)
{
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_EDIT_SEED:
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get EDIT_SEED payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || seed.len + len > FUGU_EDIT_MAX)
fatalx("compose seed overrun"); /* I10, fail closed */
buf_add(&seed, p, len);
blob - d37bcaf8fb50b8ec2b9e2ed1e60476b21a7b9895
blob + 83c5b7c960279f612572e5e849cb4f2e3152ad0b
--- src/fugu-tool/agent.c
+++ src/fugu-tool/agent.c
return (0);
}
-static const u_char *
-frame_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
static void
agent_send(struct agent_state *a, uint32_t type, const void *data, size_t len)
{
{
struct buf body;
struct imsg imsg;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
uint32_t type;
while (agent_next(a, &imsg)) {
type = imsg_get_type(&imsg);
- p = frame_bytes(&imsg, &len);
+ if (imsgev_get_payload(&imsg, &payload) == -1)
+ fatal("get subagent provider payload");
+ p = payload.data;
+ len = payload.len;
switch (type) {
case FUGU_IMSG_A_TEXT:
if (len > FUGU_RESPONSE_MAX - a->text.len) {
struct tool_req req;
struct tool_result result;
struct imsg imsg;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
buf_reset(out);
*is_error = 1;
while (agent_next(a, &imsg)) {
- p = frame_bytes(&imsg, &len);
+ if (imsgev_get_payload(&imsg, &payload) == -1)
+ fatal("get subagent web payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(&imsg)) {
case FUGU_IMSG_AGENT_WEB_OUT:
if (p == NULL || len == 0 || len > FUGU_WEB_OUT_MAX - out->len)
blob - b06198cd808cda70d20ee3537d1329ccc42fd8ce
blob + 2f07ba49a039d9992f3210584cd7ced3f6ef9042
--- src/fugu-tool/main.c
+++ src/fugu-tool/main.c
job_pump(ts->ctx->jobs);
}
-/* A read-only view of an imsg's payload; valid until imsg_free. */
-static const u_char *
-imsg_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
/*
* Unveil the protect entries away with empty permissions (I5/I9).
*
{
struct tool_state *ts = w->ctx;
struct hello_tool h;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
int passed_fd, snapshot_fd, write_ok, net_ok;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get tool HELLO payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len < sizeof(h))
fatalx("fugu-tool: short HELLO");
memcpy(&h, p, sizeof(h));
tool_dispatch(struct worker *w, struct imsg *imsg)
{
struct tool_state *ts = w->ctx;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_AGENT_START:
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get AGENT_START payload");
+ p = payload.data;
+ len = payload.len;
if (!ts->agent || agent_boot_start(&ts->boot, p, len) == -1)
fatalx("fugu-tool: bad AGENT_START");
return (0);
case FUGU_IMSG_AGENT_SYSTEM:
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get AGENT_SYSTEM payload");
+ p = payload.data;
+ len = payload.len;
if (!ts->agent || agent_boot_system(&ts->boot, p, len) == -1)
fatalx("fugu-tool: bad AGENT_SYSTEM");
return (0);
case FUGU_IMSG_AGENT_PROMPT:
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get AGENT_PROMPT payload");
+ p = payload.data;
+ len = payload.len;
if (!ts->agent || agent_boot_prompt(&ts->boot, p, len) == -1)
fatalx("fugu-tool: bad AGENT_PROMPT");
return (0);
case FUGU_IMSG_TOOL_REQ: {
struct tool_req req;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get TOOL_REQ payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len < sizeof(req))
fatalx("fugu-tool: short TOOL_REQ");
memcpy(&req, p, sizeof(req));
return (0);
}
case FUGU_IMSG_TOOL_ARG:
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get TOOL_ARG payload");
+ p = payload.data;
+ len = payload.len;
if (ts->arg.len + len > FUGU_TOOL_ARG_MAX)
fatalx("fugu-tool: tool input too large");
if (p != NULL && len > 0)
size_t off;
/* the payload is a NUL-terminated path (coordinator-built) */
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get CTX_READ payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len == 0 || len >= sizeof(path) ||
memchr(p, '\0', len) != NULL)
fatalx("fugu-tool: bad CTX_READ");
size_t plen;
/* path '\0' bullet-bytes */
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get CTX_APPEND payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || (plen = strnlen((const char *)p, len)) == len)
fatalx("fugu-tool: bad CTX_APPEND");
path = (const char *)p;
blob - 28f63779f1fa42debfdf0de1872100134d910011
blob + a3bfff69f738ee02517ed6fd50a3bd136efdecc8
--- src/fugu-tty/ui.c
+++ src/fugu-tty/ui.c
static struct ui *UI; /* for the atexit terminal restore */
-/* Borrow an imsg's payload bytes (length-checked by the caller). */
-static const u_char *
-imsg_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
/* ---- small helpers -------------------------------------------------- */
static int
ui_render(struct worker *w, struct imsg *imsg)
{
struct ui *u = w->ctx;
+ struct imsgev_payload payload;
const u_char *p;
size_t len;
if (u == NULL)
return (-1);
- p = imsg_bytes(imsg, &len); /* fetched once: the ibuf is consumed */
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get UI payload");
+ p = payload.data;
+ len = payload.len;
switch (imsg_get_type(imsg)) {
case FUGU_IMSG_UI_CONFIG:
blob - 7e6959a1391bfc8c861ed9768748cdee3b54e804
blob + efcc30a384f2600ea0ffd58567d501f97d1025dc
--- src/fugu-web/main.c
+++ src/fugu-web/main.c
static struct web_state *web_cleanup_state;
-static const u_char *
-imsg_bytes(struct imsg *imsg, size_t *lenp)
-{
- struct ibuf ib;
-
- if (imsg_get_len(imsg) == 0 || imsg_get_ibuf(imsg, &ib) == -1) {
- *lenp = 0;
- return (NULL);
- }
- *lenp = ibuf_size(&ib);
- return (ibuf_data(&ib));
-}
-
static const char *
env_or(const char *name, const char *fallback)
{
{
struct web_state *ws = w->ctx;
struct hello_web h;
+ struct imsgev_payload payload;
const u_char *p, *token, *allow, *block;
size_t len, left, providerlen;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get web HELLO payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len < sizeof(h) || len > FUGU_WEB_HELLO_MAX)
fatalx("fugu-web: malformed HELLO");
memcpy(&h, p, sizeof(h));
web_dispatch(struct worker *w, struct imsg *imsg)
{
struct web_state *ws = w->ctx;
+ struct imsgev_payload payload;
const u_char *p;
size_t len, i, namelen;
case FUGU_IMSG_WEB_REQ: {
struct tool_req req;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get WEB_REQ payload");
+ p = payload.data;
+ len = payload.len;
if (p == NULL || len != sizeof(req) || ws->have_name ||
imsg_get_id(imsg) == 0)
fatalx("fugu-web: malformed WEB_REQ");
return (0);
}
case FUGU_IMSG_WEB_ARG:
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get WEB_ARG payload");
+ p = payload.data;
+ len = payload.len;
if (!ws->have_name || imsg_get_id(imsg) != ws->reqid ||
p == NULL || len == 0 ||
len > FUGU_WEB_ARG_MAX - ws->arg.len)
struct buf out;
int is_error;
- p = imsg_bytes(imsg, &len);
+ if (imsgev_get_payload(imsg, &payload) == -1)
+ fatal("get WEB_RUN payload");
+ p = payload.data;
+ len = payload.len;
if (p != NULL || len != 0 || !ws->have_name ||
imsg_get_id(imsg) != ws->reqid)
fatalx("fugu-web: malformed WEB_RUN");