|
|
1.1 root 1: #include <stdio.h>
2: #include <signal.h>
3:
4: #define Read 1
5: #define Write 2
6: #define Endfile 3
7: #define Error 4
8:
9: int inpipe, outpipe;
10: int infd = 0, outfd = 1;
11: int bufmax = 32768;
12: char *buffer;
13: int reclen;
14: extern char *optarg;
15: extern int optind;
16: extern char *malloc();
17:
18: int
19: gettoken()
20: {
21: char c;
22:
23: switch (read (inpipe, &c, 1)) {
24: case 0: return Endfile;
25: case 1: return c;
26: default:
27: perror ("gettoken");
28: return Error;
29: }
30: }
31:
32: void
33: puttoken(t)
34: char t;
35: {
36: write (outpipe, &t, 1);
37: }
38:
39: int
40: readbuf()
41: {
42: reclen = read (infd, buffer, bufmax);
43:
44: if (reclen < 0) {
45: perror ("read");
46: return 0;
47: }
48:
49: return reclen > 0;
50: }
51:
52: int
53: writebuf()
54: {
55: if (write (outfd, buffer, reclen) != reclen) {
56: perror ("write");
57: return 0;
58: }
59: return 1;
60: }
61:
62: int
63: copyloop()
64: {
65: for (;;) {
66: int t;
67: if ((t = gettoken()) != Read)
68: return t;
69: if (!readbuf()) {
70: puttoken (Endfile);
71: return Endfile;
72: }
73: puttoken (Read);
74: if ((t = gettoken()) != Write)
75: return t;
76: if (!writebuf()) {
77: puttoken (Error);
78: return Error;
79: }
80: puttoken (Write);
81: }
82: }
83:
84: int
85: copyfile()
86: {
87: int p0[2], p1[2];
88: int p, pid, status;
89: pipe (p0);
90: pipe (p1);
91: switch (pid = fork()) {
92: default: /* parent */
93: inpipe = p0[0];
94: close (p0[1]);
95: outpipe = p1[1];
96: close (p1[0]);
97:
98: status = copyloop();
99: if (status != Endfile) {
100: fprintf (stderr, "error: parent status %d\n", status);
101: return 1;
102: }
103:
104: do p = wait (&status);
105: while (p >= 0 && p != pid);
106: if (p < 0) {
107: perror ("wait");
108: return 1;
109: }
110:
111: if (status != Endfile<<8) {
112: fprintf (stderr, "error: child status %d\n", status);
113: return 1;
114: }
115:
116: return 0;
117:
118: case 0: /* child */
119: inpipe = p1[0];
120: close (p1[1]);
121: outpipe = p0[1];
122: close (p0[0]);
123: puttoken (Read);
124: puttoken (Write);
125: exit (copyloop());
126:
127: case -1: /* error */
128: perror ("fork");
129: return 1;
130: }
131: }
132:
133: main (argc, argv)
134: int argc;
135: char **argv;
136: {
137: int c;
138: while ((c = getopt (argc, argv, "b:")) != -1) {
139: switch (c) {
140: case 'b':
141: bufmax = atoi (optarg);
142: if (bufmax <= 0) {
143: fprintf (stderr, "invalid buffer size\n");
144: exit (1);
145: }
146: }
147: }
148:
149: if ((buffer = malloc (bufmax)) == NULL) {
150: fprintf (stderr, "out of memory\n");
151: exit (1);
152: }
153:
154: if (argc > optind + 1) {
155: fprintf (stderr, "only one input file\n");
156: exit (1);
157: }
158:
159: if (argc > optind) {
160: infd = open (argv[optind], 0);
161: if (infd < 0) {
162: perror (argv[optind]);
163: exit (1);
164: }
165: }
166:
167: signal (SIGPIPE, SIG_IGN);
168: return copyfile();
169: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.