source: trunk/minix/commands/simple/cat.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 2.5 KB
RevLine 
[9]1/* cat - concatenates files Author: Andy Tanenbaum */
2
3/* 30 March 1990 - Slightly modified for efficiency by Norbert Schlenker. */
4/* 23 March 2002 - Proper error messages by Kees J. Bot. */
5
6
7#include <errno.h>
8#include <sys/types.h>
9#include <fcntl.h>
10#include <string.h>
11#include <unistd.h>
12#include <stdlib.h>
13#include <minix/minlib.h>
14#include <stdio.h>
15
16#define CHUNK_SIZE (2048 * sizeof(char *))
17
18static int unbuffered;
19static char ibuf[CHUNK_SIZE];
20static char obuf[CHUNK_SIZE];
21static char *op = obuf;
22
23int main(int argc, char **argv);
24static void copyout(char *file, int fd);
25static void output(char *buf, size_t count);
26static void report(char *label);
27static void fatal(char *label);
28
29static char STDIN[] = "standard input";
30static char STDOUT[] = "standard output";
31
32static int excode = 0;
33
34int main(int argc, char *argv[])
35{
36 int i, fd;
37
38 i = 1;
39 while (i < argc && argv[i][0] == '-') {
40 char *opt = argv[i] + 1;
41
42 if (opt[0] == 0) break; /* - */
43 i++;
44 if (opt[0] == '-' && opt[1] == 0) break; /* -- */
45
46 while (*opt != 0) switch (*opt++) {
47 case 'u':
48 unbuffered = 1;
49 break;
50 default:
51 std_err("Usage: cat [-u] [file ...]\n");
52 exit(1);
53 }
54 }
55
56 if (i >= argc) {
57 copyout(STDIN, STDIN_FILENO);
58 } else {
59 while (i < argc) {
60 char *file = argv[i++];
61
62 if (file[0] == '-' && file[1] == 0) {
63 copyout(STDIN, STDIN_FILENO);
64 } else {
65 fd = open(file, O_RDONLY);
66 if (fd < 0) {
67 report(file);
68 } else {
69 copyout(file, fd);
70 close(fd);
71 }
72 }
73 }
74 }
75 output(obuf, (op - obuf));
76 return(excode);
77}
78
79static void copyout(char *file, int fd)
80{
81 int n;
82
83 while (1) {
84 n = read(fd, ibuf, CHUNK_SIZE);
85 if (n < 0) fatal(file);
86 if (n == 0) return;
87 if (unbuffered || (op == obuf && n == CHUNK_SIZE)) {
88 output(ibuf, n);
89 } else {
90 int bytes_left;
91
92 bytes_left = &obuf[CHUNK_SIZE] - op;
93 if (n <= bytes_left) {
94 memcpy(op, ibuf, (size_t)n);
95 op += n;
96 } else {
97 memcpy(op, ibuf, (size_t)bytes_left);
98 output(obuf, CHUNK_SIZE);
99 n -= bytes_left;
100 memcpy(obuf, ibuf + bytes_left, (size_t)n);
101 op = obuf + n;
102 }
103 }
104 }
105}
106
107static void output(char *buf, size_t count)
108{
109 ssize_t n;
110
111 while (count > 0) {
112 n = write(STDOUT_FILENO, buf, count);
113 if (n <= 0) {
114 if (n < 0) fatal(STDOUT);
115 std_err("cat: standard output: EOF\n");
116 exit(1);
117 }
118 buf += n;
119 count -= n;
120 }
121}
122
123static void report(char *label)
124{
125 int e = errno;
126 std_err("cat: ");
127 std_err(label);
128 std_err(": ");
129 std_err(strerror(e));
130 std_err("\n");
131 excode = 1;
132}
133
134static void fatal(char *label)
135{
136 report(label);
137 exit(1);
138}
Note: See TracBrowser for help on using the repository browser.