#! /usr/bin/tcc -run /* -*-c-*- */ /* Some of the scripts in the `flaccrip' suite want to chop streams of PCM * data about. Once upon a time, they used dd(1) for this, but dd does * entirely the wrong thing on short reads, and short reads happen quite * regularly on pipes. * * The requirements on this program are that it copy exactly the first N * bytes from stdin to stdout, without reading anything else from stdin or * writing anything else to stdout. (That's why it doesn't use stdio to do * the copying: stdio buffering will read too much from stdin, which will * cause stream corruption later.) * * As a special bonus, it's quite paranoid about error checking, and does way * more work on dealing with short reads and writes than is necessary for * working on pipes. It will fail miserably if either stdin or stdout is * non-blocking. */ #include #include #include #include #include #include int main(int argc, char *argv[]) { unsigned long n; size_t nn, nleft; ssize_t sz; char buf[40960], *p; if (argc != 2) { fprintf(stderr, "Usage: %s LENGTH\n", argv[0]); exit(1); } n = strtoul(argv[1], 0, 0); while (n) { nn = nleft = n > sizeof(buf) ? sizeof(buf) : n; p = buf; while (nleft) { sz = read(STDIN_FILENO, p, nleft); if (sz < 0) { if (errno == EINTR) continue; fprintf(stderr, "%s: read error: %s", argv[0], strerror(errno)); exit(1); } else if (!sz) { fprintf(stderr, "%s: unexpected eof", argv[0]); exit(1); } nleft -= sz; p += sz; } nleft = nn; p = buf; while (nleft) { sz = write(STDOUT_FILENO, p, nleft); if (sz < 0) { if (errno == EINTR) continue; fprintf(stderr, "%s: write error: %s", argv[0], strerror(errno)); exit(1); } else if (!sz) { fprintf(stderr, "%s: empty write", argv[0]); exit(1); } nleft -= sz; p += sz; } n -= nn; } return (0); }