static enum mad_flow receive(int fd, void **message, unsigned int *size) { enum mad_flow result; unsigned int actual; if (*message == 0) *size = 0; /* receive size */ result = receive_io(fd, &actual, sizeof(actual)); /* receive message */ if (result == MAD_FLOW_CONTINUE) { if (actual > *size) actual -= *size; else { *size = actual; actual = 0; } if (*size > 0) { if (*message == 0) { *message = malloc(*size); if (*message == 0) return MAD_FLOW_BREAK; } result = receive_io_blocking(fd, *message, *size); } /* throw away remainder of message */ while (actual && result == MAD_FLOW_CONTINUE) { char sink[256]; unsigned int len; len = actual > sizeof(sink) ? sizeof(sink) : actual; result = receive_io_blocking(fd, sink, len); actual -= len; } } return result; }
static enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len) { int flags, blocking; enum mad_flow result; flags = fcntl(fd, F_GETFL); if (flags == -1) return MAD_FLOW_BREAK; blocking = flags & ~O_NONBLOCK; if (blocking != flags && fcntl(fd, F_SETFL, blocking) == -1) return MAD_FLOW_BREAK; result = receive_io(fd, buffer, len); if (flags != blocking && fcntl(fd, F_SETFL, flags) == -1) return MAD_FLOW_BREAK; return result; }