chiark / gitweb /
Basic building and packaging machinery, which does nothing useful.
[autoys] / flaccrip / cat-prefix
1 #! /usr/bin/tcc -run
2 /* -*-c-*- */
3
4 /* Some of the scripts in the `flaccrip' suite want to chop streams of PCM
5  * data about.  Once upon a time, they used dd(1) for this, but dd does
6  * entirely the wrong thing on short reads, and short reads happen quite
7  * regularly on pipes.
8  *
9  * The requirements on this program are that it copy exactly the first N
10  * bytes from stdin to stdout, without reading anything else from stdin or
11  * writing anything else to stdout.  (That's why it doesn't use stdio to do
12  * the copying: stdio buffering will read too much from stdin, which will
13  * cause stream corruption later.)
14  *
15  * As a special bonus, it's quite paranoid about error checking, and does way
16  * more work on dealing with short reads and writes than is necessary for
17  * working on pipes.  It will fail miserably if either stdin or stdout is
18  * non-blocking.
19  */
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 int main(int argc, char *argv[])
30 {
31   unsigned long n;
32   size_t nn, nleft;
33   ssize_t sz;
34   char buf[40960], *p;
35
36   if (argc != 2) {
37     fprintf(stderr, "Usage: %s LENGTH\n", argv[0]);
38     exit(1);
39   }
40   n = strtoul(argv[1], 0, 0);
41
42   while (n) {
43     nn = nleft = n > sizeof(buf) ? sizeof(buf) : n;
44     p = buf;
45     while (nleft) {
46       sz = read(STDIN_FILENO, p, nleft);
47       if (sz < 0) {
48         if (errno == EINTR)
49           continue;
50         fprintf(stderr, "%s: read error: %s", argv[0], strerror(errno));
51         exit(1);
52       } else if (!sz) {
53         fprintf(stderr, "%s: unexpected eof", argv[0]);
54         exit(1);
55       }
56       nleft -= sz; p += sz;
57     }
58
59     nleft = nn;
60     p = buf;
61     while (nleft) {
62       sz = write(STDOUT_FILENO, p, nleft);
63       if (sz < 0) {
64         if (errno == EINTR)
65           continue;
66         fprintf(stderr, "%s: write error: %s", argv[0], strerror(errno));
67         exit(1);
68       } else if (!sz) {
69         fprintf(stderr, "%s: empty write", argv[0]);
70         exit(1);
71       }
72       nleft -= sz; p += sz;
73     }
74
75     n -= nn;
76   }
77   return (0);
78 }