ex_cat.c
#include "ex_utils.h"
#define CONF_USE_MMAP_DEF FALSE
static void ex_cat_read_fd_write_stdout(Vstr_base *s1, int fd)
{
while (TRUE)
{
int io_w_state = IO_OK;
int io_r_state = io_get(s1, fd);
if (io_r_state == IO_EOF)
break;
io_w_state = io_put(s1, STDOUT_FILENO);
io_limit(io_r_state, fd, io_w_state, STDOUT_FILENO, s1);
}
}
static void ex_cat_limit(Vstr_base *s1)
{
while ((s1->len >= EX_MAX_W_DATA_INCORE) || (s1->len >= EX_MAX_R_DATA_INCORE))
{
if (io_put(s1, STDOUT_FILENO) == IO_BLOCK)
io_block(-1, STDOUT_FILENO);
}
}
int main(int argc, char *argv[])
{
Vstr_base *s1 = ex_init(NULL);
int count = 1;
int use_mmap = CONF_USE_MMAP_DEF;
while (count < argc)
{
if (!strcmp("--", argv[count]))
{
++count;
break;
}
else if (!strcmp("--mmap", argv[count]))
use_mmap = !use_mmap;
else if (!strcmp("--version", argv[count]))
{
vstr_add_fmt(s1, 0, "%s", "\
jcat 1.0.0\n\
Written by James Antill\n\
\n\
Uses Vstr string library.\n\
");
goto out;
}
else if (!strcmp("--help", argv[count]))
{
vstr_add_fmt(s1, 0, "%s", "\
Usage: jcat [FILENAME]...\n\
or: jcat OPTION\n\
Output filenames.\n\
\n\
--help Display this help and exit\n\
--version Output version information and exit\n\
--mmap Toggle use of mmap() to load input files\n\
-- Treat rest of cmd line as input filenames\n\
\n\
Report bugs to James Antill <james@and.org>.\n\
");
goto out;
}
else
break;
++count;
}
if (count >= argc)
{
io_fd_set_o_nonblock(STDIN_FILENO);
ex_cat_read_fd_write_stdout(s1, STDIN_FILENO);
}
while (count < argc)
{
unsigned int ern = 0;
if (use_mmap)
vstr_sc_mmap_file(s1, s1->len, argv[count], 0, 0, &ern);
if (!use_mmap ||
(ern == VSTR_TYPE_SC_MMAP_FILE_ERR_FSTAT_ERRNO) ||
(ern == VSTR_TYPE_SC_MMAP_FILE_ERR_MMAP_ERRNO) ||
(ern == VSTR_TYPE_SC_MMAP_FILE_ERR_TOO_LARGE))
{
int fd = io_open(argv[count]);
ex_cat_read_fd_write_stdout(s1, fd);
if (close(fd) == -1)
warn("close(%s)", argv[count]);
}
else if (ern && (ern != VSTR_TYPE_SC_MMAP_FILE_ERR_CLOSE_ERRNO))
err(EXIT_FAILURE, "add");
else
ex_cat_limit(s1);
++count;
}
out:
io_put_all(s1, STDOUT_FILENO);
exit (ex_exit(s1, NULL));
}