#include <sys/param.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void
usage(void)
{
fprintf(stderr, "usage: %s [-b bytes | -c lines | -e] [-s buffer-size]\n",
getprogname());
exit(1);
}
int
main(int argc, char *argv[])
{
char *buf;
const char *errstr;
size_t bufsz = 0, reps;
ssize_t ret;
enum { MODE_BYTES, MODE_COUNT, MODE_EOF } mode;
int ch;
mode = MODE_EOF;
while ((ch = getopt(argc, argv, "b:c:es:")) != -1) {
switch (ch) {
case 'b':
mode = MODE_BYTES;
reps = strtonum(optarg, 0, SSIZE_MAX, &errstr);
if (errstr != NULL)
errx(1, "strtonum: %s", errstr);
break;
case 'c':
mode = MODE_COUNT;
reps = strtonum(optarg, 1, SSIZE_MAX, &errstr);
if (errstr != NULL)
errx(1, "strtonum: %s", errstr);
break;
case 'e':
mode = MODE_EOF;
break;
case 's':
bufsz = strtonum(optarg, 1, SSIZE_MAX, &errstr);
if (errstr != NULL)
errx(1, "strtonum: %s", errstr);
break;
default:
usage();
}
}
if (bufsz == 0) {
if (mode == MODE_BYTES)
bufsz = reps;
else
bufsz = LINE_MAX;
}
buf = malloc(bufsz);
if (buf == NULL)
err(1, "malloc");
for (;;) {
size_t readsz;
if (mode == MODE_BYTES)
readsz = MIN(bufsz, reps);
else
readsz = bufsz;
ret = read(STDIN_FILENO, buf, readsz);
if (ret == -1 && errno == EINTR)
continue;
if (ret == -1)
err(1, "read");
if (ret == 0) {
if (mode == MODE_EOF)
return (0);
errx(1, "premature EOF");
}
write(STDOUT_FILENO, buf, ret);
switch (mode) {
case MODE_BYTES:
reps -= ret;
if (reps == 0)
return (0);
break;
case MODE_COUNT:
reps--;
if (reps == 0)
return (0);
break;
default:
break;
}
}
return (0);
}