bytes = read(fd->fd, buffer, sizeof(buffer) - 1);
if (bytes == -1)
logerr(__func__);
- if (bytes == -1 || bytes == 0) {
- control_hangup(fd);
- return -1;
- }
+ if (bytes == -1 || bytes == 0)
+ return (int)bytes;
#ifdef PRIVSEP
if (IN_PRIVSEP(fd->ctx)) {
if (err == 1 &&
ps_ctl_sendargs(fd, buffer, (size_t)bytes) == -1) {
logerr(__func__);
- control_free(fd);
return -1;
}
- return 0;
+ return 1;
}
#endif
- control_recvdata(fd, buffer, (size_t)bytes);
- return 0;
+ return control_recvdata(fd, buffer, (size_t)bytes);
}
static int
control_handle_data(void *arg, unsigned short events)
{
struct fd_list *fd = arg;
+ int err;
if (!(events & (ELE_READ | ELE_WRITE | ELE_HANGUP)))
logerrx("%s: unexpected event 0x%04x", __func__, events);
if (events & ELE_WRITE && !(events & ELE_HANGUP)) {
- if (control_handle_write(fd) == -1)
- return;
+ err = control_handle_write(fd);
+ if (err == -1)
+ goto hangup;
}
if (events & ELE_READ) {
- if (control_handle_read(fd) == -1)
- return;
+ err = control_handle_read(fd);
+ if (err == -1 || err == 0)
+ goto hangup;
}
if (events & ELE_HANGUP)
- control_hangup(fd);
+ goto hangup;
+
+ return;
+
+hangup:
+ control_hangup(fd);
}
-void
+int
control_recvdata(struct fd_list *fd, char *data, size_t len)
{
char *p = data, *e;
if (e == NULL) {
errno = EINVAL;
logerrx("%s: no terminator", __func__);
- return;
+ return -1;
}
- if ((size_t)argc >= sizeof(argvp) / sizeof(argvp[0])) {
+ if ((size_t)argc + 1 >=
+ sizeof(argvp) / sizeof(argvp[0])) {
errno = ENOBUFS;
logerrx("%s: no arg buffer", __func__);
- return;
+ return -1;
}
*ap++ = p;
argc++;
*ap = NULL;
if (dhcpcd_handleargs(fd->ctx, fd, argc, argvp) == -1) {
logerr(__func__);
- if (errno != EINTR && errno != EAGAIN) {
- control_free(fd);
- return;
- }
+ if (errno != EINTR && errno != EAGAIN)
+ return -1;
}
}
+
+ return 1;
}
struct fd_list *
void control_free(struct fd_list *);
void control_delete(struct fd_list *);
int control_queue(struct fd_list *, void *, size_t);
-void control_recvdata(struct fd_list *fd, char *, size_t);
+int control_recvdata(struct fd_list *fd, char *, size_t);
#endif
struct iovec *iov = msg->msg_iov;
struct fd_list *fd;
unsigned int fd_flags = FD_SENDLEN;
+ int err;
switch (psm->ps_flags) {
case PS_CTL_PRIV:
if (fd == NULL)
return -1;
ctx->ps_control_client = fd;
- control_recvdata(fd, iov->iov_base, iov->iov_len);
+ err = control_recvdata(fd, iov->iov_base, iov->iov_len);
+ if (err == -1 || err == 0) {
+ control_free(fd);
+ ctx->ps_control_client = NULL;
+ }
break;
case PS_CTL_EOF:
ctx->ps_control_client = NULL;