ex_utils.h
#ifndef EX_UTILS_H
#define EX_UTILS_H 1
#define VSTR_COMPILE_INCLUDE 1
#include <vstr.h>
#include <errno.h>
#include <err.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#ifndef FALSE
# define FALSE 0
#endif
#ifndef TRUE
# define TRUE 1
#endif
#define EX_UTILS_GETOPT_NUM(name, var) \
else if (!strncmp("--" name, argv[count], strlen("--" name))) \
{ \
if (!strncmp("--" name "=", argv[count], strlen("--" name "="))) \
(var) = strtol(argv[count] + strlen("--" name "="), NULL, 0); \
else \
{ \
(var) = 0; \
\
++count; \
if (count >= argc) \
break; \
\
(var) = strtol(argv[count], NULL, 0); \
} \
} \
else if (0) ASSERT(FALSE)
#define EX_UTILS_GETOPT_CSTR(name, var) \
else if (!strncmp("--" name, argv[count], strlen("--" name))) \
{ \
if (!strncmp("--" name "=", argv[count], strlen("--" name "="))) \
(var) = argv[count] + strlen("--" name "="); \
else \
{ \
(var) = NULL; \
\
++count; \
if (count >= argc) \
break; \
\
(var) = argv[count]; \
} \
} \
else if (0) ASSERT(FALSE)
#define assert(x) do { if (x) {} else errx(EXIT_FAILURE, "assert(" #x "), FAILED at line %u", __LINE__); } while (FALSE)
#define ASSERT(x) do { if (x) {} else errx(EXIT_FAILURE, "ASSERT(" #x "), FAILED at line %u", __LINE__); } while (FALSE)
#ifndef EX_MAX_R_DATA_INCORE
# define EX_MAX_R_DATA_INCORE (8 * 1024)
#endif
#ifndef EX_MAX_W_DATA_INCORE
# define EX_MAX_W_DATA_INCORE (8 * 1024)
#endif
#define IO_OK 0
#define IO_BLOCK 1
#define IO_EOF 2
#define IO_NONE 3
static void io_block(int io_r_fd, int io_w_fd)
{
struct pollfd ios_beg[2];
struct pollfd *ios = ios_beg;
unsigned int num = 0;
ios[0].revents = ios[1].revents = 0;
if (io_r_fd == io_w_fd)
{
num = 1;
ios[0].events = POLLIN | POLLOUT;
ios[0].fd = io_w_fd;
}
else
{
if (io_r_fd != -1)
{
ios->events = POLLIN;
ios->fd = io_r_fd;
++num; ++ios;
}
if (io_w_fd != -1)
{
ios->events = POLLOUT;
ios->fd = io_w_fd;
++num; ++ios;
}
}
while (poll(ios_beg, num, -1) == -1)
{
if (errno != EINTR)
err(EXIT_FAILURE, "poll");
}
}
static int io_put(Vstr_base *io_w, int fd)
{
if (!io_w->len)
return (IO_NONE);
if (!vstr_sc_write_fd(io_w, 1, io_w->len, fd, NULL))
{
if (errno == EAGAIN)
return (IO_BLOCK);
err(EXIT_FAILURE, "write");
}
return (IO_OK);
}
static void io_put_all(Vstr_base *io_w, int fd)
{
int state = IO_NONE;
while ((state = io_put(io_w, fd)) != IO_NONE)
{
if (state == IO_BLOCK)
io_block(-1, fd);
}
}
#ifndef EX_UTILS_NO_USE_INPUT
static int io_get(Vstr_base *io_r, int fd)
{
if (io_r->len < EX_MAX_R_DATA_INCORE)
{
unsigned int ern = 0;
vstr_sc_read_iov_fd(io_r, io_r->len, fd, 8, 16, &ern);
if (ern == VSTR_TYPE_SC_READ_FD_ERR_EOF)
return (IO_EOF);
else if ((ern == VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO) && (errno == EAGAIN))
return (IO_BLOCK);
else if (ern)
err(EXIT_FAILURE, "read");
}
return (IO_OK);
}
static void io_limit(int io_r_state, int io_r_fd,
int io_w_state, int io_w_fd, Vstr_base *s_w)
{
if (io_w_state == IO_BLOCK)
{
if (io_r_state == IO_BLOCK)
io_block(io_r_fd, io_w_fd);
else if (s_w->len > EX_MAX_W_DATA_INCORE)
io_block(-1, io_w_fd);
}
else if ((io_w_state == IO_NONE) && (io_r_state == IO_BLOCK))
io_block(io_r_fd, -1);
}
#endif
static int io_fd_set_o_nonblock(int fd)
{
int flags = 0;
if ((flags = fcntl(fd, F_GETFL)) == -1)
return (FALSE);
if (!(flags & O_NONBLOCK) &&
(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1))
return (FALSE);
return (TRUE);
}
#ifndef EX_UTILS_NO_USE_OPEN
# ifndef VSTR_AUTOCONF_HAVE_OPEN64
# define open64 open
# endif
static int io_open(const char *filename)
{
int fd = open64(filename, O_RDONLY | O_NOCTTY);
if (fd == -1)
err(EXIT_FAILURE, "open(%s)", filename);
io_fd_set_o_nonblock(fd);
return (fd);
}
#endif
static Vstr_base *ex_init(Vstr_base **s2)
{
Vstr_base *s1 = NULL;
struct stat stat_buf;
if (!vstr_init())
errno = ENOMEM, err(EXIT_FAILURE, "init");
if (fstat(1, &stat_buf) == -1)
warn("fstat(STDOUT)");
else
{
if (!stat_buf.st_blksize)
stat_buf.st_blksize = 4096;
if (!vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_NUM_BUF_SZ,
stat_buf.st_blksize / 8))
warnx("Couldn't alter node size to match block size");
}
if (!(s1 = vstr_make_base(NULL)) ||
(s2 && !(*s2 = vstr_make_base(NULL))))
errno = ENOMEM, err(EXIT_FAILURE, "Create string");
vstr_make_spare_nodes(NULL, VSTR_TYPE_NODE_BUF, 32);
io_fd_set_o_nonblock(STDOUT_FILENO);
return (s1);
}
static int ex_exit(Vstr_base *s1, Vstr_base *s2)
{
vstr_free_base(s1);
vstr_free_base(s2);
vstr_exit();
return (EXIT_SUCCESS);
}
#endif