aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-22 16:06:16 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-22 16:06:16 +0000
commite31f721e140a7bb2377f1c1b09715f1bcbf9ec7a (patch)
tree4760b57ee5b042475b461734d08fecf780aa3f52
parentf4c52b32dbfb20a31dcc04aab64e18c224a84e61 (diff)
downloadbusybox-w32-e31f721e140a7bb2377f1c1b09715f1bcbf9ec7a.tar.gz
busybox-w32-e31f721e140a7bb2377f1c1b09715f1bcbf9ec7a.tar.bz2
busybox-w32-e31f721e140a7bb2377f1c1b09715f1bcbf9ec7a.zip
tail: -50 text bytes
-rw-r--r--coreutils/tail.c136
1 files changed, 48 insertions, 88 deletions
diff --git a/coreutils/tail.c b/coreutils/tail.c
index b690b370e..a753a10b7 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -29,44 +29,30 @@
29static const struct suffix_mult tail_suffixes[] = { 29static const struct suffix_mult tail_suffixes[] = {
30 { "b", 512 }, 30 { "b", 512 },
31 { "k", 1024 }, 31 { "k", 1024 },
32 { "m", 1048576 }, 32 { "m", 1024*1024 },
33 { NULL, 0 } 33 { NULL, 0 }
34}; 34};
35 35
36static int status; 36static int status;
37 37
38static void tail_xbb_full_write(const char *buf, size_t len)
39{
40 /* If we get a write error, there is really no sense in continuing. */
41 if (full_write(STDOUT_FILENO, buf, len) < 0)
42 bb_perror_nomsg_and_die();
43}
44
45static void tail_xprint_header(const char *fmt, const char *filename) 38static void tail_xprint_header(const char *fmt, const char *filename)
46{ 39{
47#if defined __GLIBC__ 40 if (fdprintf(STDOUT_FILENO, fmt, filename) < 0)
48 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
49 bb_perror_nomsg_and_die(); 41 bb_perror_nomsg_and_die();
50 }
51#else
52 int hdr_len = strlen(fmt) + strlen(filename);
53 char *hdr = xzalloc(hdr_len);
54 sprintf(hdr, filename, filename);
55 tail_xbb_full_write(hdr, hdr_len);
56#endif
57} 42}
58 43
59static ssize_t tail_read(int fd, char *buf, size_t count) 44static ssize_t tail_read(int fd, char *buf, size_t count)
60{ 45{
61 ssize_t r; 46 ssize_t r;
62 off_t current,end; 47 off_t current, end;
63 struct stat sbuf; 48 struct stat sbuf;
64 49
65 end = current = lseek(fd, 0, SEEK_CUR); 50 end = current = lseek(fd, 0, SEEK_CUR);
66 if (!fstat(fd, &sbuf)) 51 if (!fstat(fd, &sbuf))
67 end = sbuf.st_size; 52 end = sbuf.st_size;
68 lseek(fd, end < current ? 0 : current, SEEK_SET); 53 lseek(fd, end < current ? 0 : current, SEEK_SET);
69 if ((r = safe_read(fd, buf, count)) < 0) { 54 r = safe_read(fd, buf, count);
55 if (r < 0) {
70 bb_perror_msg(bb_msg_read_error); 56 bb_perror_msg(bb_msg_read_error);
71 status = EXIT_FAILURE; 57 status = EXIT_FAILURE;
72 } 58 }
@@ -74,82 +60,55 @@ static ssize_t tail_read(int fd, char *buf, size_t count)
74 return r; 60 return r;
75} 61}
76 62
77static const char tail_opts[] =
78 "fn:c:"
79#if ENABLE_FEATURE_FANCY_TAIL
80 "qs:v"
81#endif
82 ;
83
84static const char header_fmt[] = "\n==> %s <==\n"; 63static const char header_fmt[] = "\n==> %s <==\n";
85 64
86int tail_main(int argc, char **argv) 65int tail_main(int argc, char **argv)
87{ 66{
88 long count = 10; 67 unsigned count = 10;
89 unsigned sleep_period = 1; 68 unsigned sleep_period = 1;
90 int from_top = 0; 69 int from_top = 0;
91 int follow = 0;
92 int header_threshhold = 1; 70 int header_threshhold = 1;
93 int count_bytes = 0; 71 const char *str_c, *str_n, *str_s;
94 72
95 char *tailbuf; 73 char *tailbuf;
96 size_t tailbufsize; 74 size_t tailbufsize;
97 int taillen = 0; 75 int taillen = 0;
98 int newline = 0; 76 int newline = 0;
77 int nfiles, nread, nwrite, seen, i, opt;
99 78
100 int *fds, nfiles, nread, nwrite, seen, i, opt; 79 int *fds;
101 char *s, *buf; 80 char *s, *buf;
102 const char *fmt; 81 const char *fmt;
103 82
83 void eat_num(const char *p) {
84 if (*p == '-') p++;
85 else if (*p == '+') { p++; from_top = 1; }
86 count = xatou_sfx(p, tail_suffixes);
87 }
88
89
104#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL 90#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
105 /* Allow legacy syntax of an initial numeric option without -n. */ 91 /* Allow legacy syntax of an initial numeric option without -n. */
106 if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-') 92 if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-')
107 && isdigit(argv[1][1]) 93 && isdigit(argv[1][1])
108 ) { 94 ) {
109 optind = 2; 95 argv[0] = "-n";
110 optarg = argv[1]; 96 argv--;
111 goto GET_COUNT; 97 argc++;
112 } 98 }
113#endif 99#endif
114 100
115 while ((opt = getopt(argc, argv, tail_opts)) > 0) { 101 opt = getopt32(argc, argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"), &str_c, &str_n, &str_s);
116 switch (opt) { 102#define FOLLOW (opt & 0x1)
117 case 'f': 103#define COUNT_BYTES (opt & 0x2)
118 follow = 1; 104 //if (opt & 0x1) // -f
119 break; 105 if (opt & 0x2) eat_num(str_c); // -c
120 case 'c': 106 if (opt & 0x4) eat_num(str_n); // -n
121 count_bytes = 1;
122 /* FALLS THROUGH */
123 case 'n':
124#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
125 GET_COUNT:
126#endif
127 from_top = 0;
128 if (*optarg == '+') {
129 ++optarg;
130 from_top = 1;
131 }
132 count = xatol_sfx(optarg, tail_suffixes);
133 /* Note: Leading whitespace is an error trapped above. */
134 if (count < 0) {
135 count = -count;
136 }
137 break;
138#if ENABLE_FEATURE_FANCY_TAIL 107#if ENABLE_FEATURE_FANCY_TAIL
139 case 'q': 108 if (opt & 0x8) header_threshhold = INT_MAX; // -q
140 header_threshhold = INT_MAX; 109 if (opt & 0x10) sleep_period = xatou(str_s); // -s
141 break; 110 if (opt & 0x20) header_threshhold = 0; // -v
142 case 's':
143 sleep_period = xatou(optarg);
144 break;
145 case 'v':
146 header_threshhold = 0;
147 break;
148#endif 111#endif
149 default:
150 bb_show_usage();
151 }
152 }
153 argc -= optind; 112 argc -= optind;
154 argv += optind; 113 argv += optind;
155 114
@@ -160,34 +119,35 @@ int tail_main(int argc, char **argv)
160 struct stat statbuf; 119 struct stat statbuf;
161 120
162 if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) { 121 if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
163 follow = 0; 122 opt &= ~1; /* clear FOLLOW */
164 } 123 }
165 *argv = (char *) bb_msg_standard_input; 124 *argv = (char *) bb_msg_standard_input;
166 goto DO_STDIN; 125 goto DO_STDIN;
167 } 126 }
168 127
169 do { 128 do {
170 if (LONE_DASH(argv[i])) { 129 if (NOT_LONE_DASH(argv[i])) {
171 DO_STDIN: 130 fds[nfiles] = open(argv[i], O_RDONLY);
131 if (fds[nfiles] < 0) {
132 bb_perror_msg("%s", argv[i]);
133 status = EXIT_FAILURE;
134 continue;
135 }
136 } else {
137 DO_STDIN: /* "-" */
172 fds[nfiles] = STDIN_FILENO; 138 fds[nfiles] = STDIN_FILENO;
173 } else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) {
174 bb_perror_msg("%s", argv[i]);
175 status = EXIT_FAILURE;
176 continue;
177 } 139 }
178 argv[nfiles] = argv[i]; 140 argv[nfiles] = argv[i];
179 ++nfiles; 141 ++nfiles;
180 } while (++i < argc); 142 } while (++i < argc);
181 143
182 if (!nfiles) { 144 if (!nfiles)
183 bb_error_msg_and_die("no files"); 145 bb_error_msg_and_die("no files");
184 }
185 146
186 tailbufsize = BUFSIZ; 147 tailbufsize = BUFSIZ;
187 148
188 /* tail the files */ 149 /* tail the files */
189 if (from_top < count_bytes) { /* Each is 0 or 1, so true iff 0 < 1. */ 150 if (!from_top && COUNT_BYTES) {
190 /* Hence, !from_top && count_bytes */
191 if (tailbufsize < count) { 151 if (tailbufsize < count) {
192 tailbufsize = count + BUFSIZ; 152 tailbufsize = count + BUFSIZ;
193 } 153 }
@@ -203,7 +163,7 @@ int tail_main(int argc, char **argv)
203 * starting file position may not be the beginning of the file. 163 * starting file position may not be the beginning of the file.
204 * Beware of backing up too far. See example in wc.c. 164 * Beware of backing up too far. See example in wc.c.
205 */ 165 */
206 if ((!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) { 166 if (!(count|from_top) && lseek(fds[i], 0, SEEK_END) >= 0) {
207 continue; 167 continue;
208 } 168 }
209 169
@@ -221,22 +181,22 @@ int tail_main(int argc, char **argv)
221 if (from_top) { 181 if (from_top) {
222 nwrite = nread; 182 nwrite = nread;
223 if (seen < count) { 183 if (seen < count) {
224 if (count_bytes) { 184 if (COUNT_BYTES) {
225 nwrite -= (count - seen); 185 nwrite -= (count - seen);
226 seen = count; 186 seen = count;
227 } else { 187 } else {
228 s = buf; 188 s = buf;
229 do { 189 do {
230 --nwrite; 190 --nwrite;
231 if ((*s++ == '\n') && (++seen == count)) { 191 if (*s++ == '\n' && ++seen == count) {
232 break; 192 break;
233 } 193 }
234 } while (nwrite); 194 } while (nwrite);
235 } 195 }
236 } 196 }
237 tail_xbb_full_write(buf + nread - nwrite, nwrite); 197 xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
238 } else if (count) { 198 } else if (count) {
239 if (count_bytes) { 199 if (COUNT_BYTES) {
240 taillen += nread; 200 taillen += nread;
241 if (taillen > count) { 201 if (taillen > count) {
242 memmove(tailbuf, tailbuf + taillen - count, count); 202 memmove(tailbuf, tailbuf + taillen - count, count);
@@ -286,7 +246,7 @@ int tail_main(int argc, char **argv)
286 } 246 }
287 247
288 if (!from_top) { 248 if (!from_top) {
289 tail_xbb_full_write(tailbuf, taillen); 249 xwrite(STDOUT_FILENO, tailbuf, taillen);
290 } 250 }
291 251
292 taillen = 0; 252 taillen = 0;
@@ -296,7 +256,7 @@ int tail_main(int argc, char **argv)
296 256
297 fmt = NULL; 257 fmt = NULL;
298 258
299 while (follow) { 259 if (FOLLOW) while (1) {
300 sleep(sleep_period); 260 sleep(sleep_period);
301 i = 0; 261 i = 0;
302 do { 262 do {
@@ -308,7 +268,7 @@ int tail_main(int argc, char **argv)
308 tail_xprint_header(fmt, argv[i]); 268 tail_xprint_header(fmt, argv[i]);
309 fmt = NULL; 269 fmt = NULL;
310 } 270 }
311 tail_xbb_full_write(buf, nread); 271 xwrite(STDOUT_FILENO, buf, nread);
312 } 272 }
313 } while (++i < nfiles); 273 } while (++i < nfiles);
314 } 274 }