Contents of /trunk/mkinitrd-magellan/busybox/coreutils/tail.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 6281 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 6281 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Mini tail implementation for busybox |
4 | * |
5 | * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> |
6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ |
9 | |
10 | /* BB_AUDIT SUSv3 compliant (need fancy for -c) */ |
11 | /* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */ |
12 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/tail.html */ |
13 | |
14 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) |
15 | * |
16 | * Pretty much rewritten to fix numerous bugs and reduce realloc() calls. |
17 | * Bugs fixed (although I may have forgotten one or two... it was pretty bad) |
18 | * 1) mixing printf/write without fflush()ing stdout |
19 | * 2) no check that any open files are present |
20 | * 3) optstring had -q taking an arg |
21 | * 4) no error checking on write in some cases, and a warning even then |
22 | * 5) q and s interaction bug |
23 | * 6) no check for lseek error |
24 | * 7) lseek attempted when count==0 even if arg was +0 (from top) |
25 | */ |
26 | |
27 | #include "busybox.h" |
28 | |
29 | static const struct suffix_mult tail_suffixes[] = { |
30 | { "b", 512 }, |
31 | { "k", 1024 }, |
32 | { "m", 1024*1024 }, |
33 | { NULL, 0 } |
34 | }; |
35 | |
36 | static int status; |
37 | |
38 | static void tail_xprint_header(const char *fmt, const char *filename) |
39 | { |
40 | if (fdprintf(STDOUT_FILENO, fmt, filename) < 0) |
41 | bb_perror_nomsg_and_die(); |
42 | } |
43 | |
44 | static ssize_t tail_read(int fd, char *buf, size_t count) |
45 | { |
46 | ssize_t r; |
47 | off_t current, end; |
48 | struct stat sbuf; |
49 | |
50 | end = current = lseek(fd, 0, SEEK_CUR); |
51 | if (!fstat(fd, &sbuf)) |
52 | end = sbuf.st_size; |
53 | lseek(fd, end < current ? 0 : current, SEEK_SET); |
54 | r = safe_read(fd, buf, count); |
55 | if (r < 0) { |
56 | bb_perror_msg(bb_msg_read_error); |
57 | status = EXIT_FAILURE; |
58 | } |
59 | |
60 | return r; |
61 | } |
62 | |
63 | static const char header_fmt[] = "\n==> %s <==\n"; |
64 | |
65 | int tail_main(int argc, char **argv) |
66 | { |
67 | unsigned count = 10; |
68 | unsigned sleep_period = 1; |
69 | int from_top = 0; |
70 | int header_threshhold = 1; |
71 | const char *str_c, *str_n, *str_s; |
72 | |
73 | char *tailbuf; |
74 | size_t tailbufsize; |
75 | int taillen = 0; |
76 | int newline = 0; |
77 | int nfiles, nread, nwrite, seen, i, opt; |
78 | |
79 | int *fds; |
80 | char *s, *buf; |
81 | const char *fmt; |
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 | |
90 | #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL |
91 | /* Allow legacy syntax of an initial numeric option without -n. */ |
92 | if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-') |
93 | && isdigit(argv[1][1]) |
94 | ) { |
95 | argv[0] = "-n"; |
96 | argv--; |
97 | argc++; |
98 | } |
99 | #endif |
100 | |
101 | opt = getopt32(argc, argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"), &str_c, &str_n, &str_s); |
102 | #define FOLLOW (opt & 0x1) |
103 | #define COUNT_BYTES (opt & 0x2) |
104 | //if (opt & 0x1) // -f |
105 | if (opt & 0x2) eat_num(str_c); // -c |
106 | if (opt & 0x4) eat_num(str_n); // -n |
107 | #if ENABLE_FEATURE_FANCY_TAIL |
108 | if (opt & 0x8) header_threshhold = INT_MAX; // -q |
109 | if (opt & 0x10) sleep_period = xatou(str_s); // -s |
110 | if (opt & 0x20) header_threshhold = 0; // -v |
111 | #endif |
112 | argc -= optind; |
113 | argv += optind; |
114 | |
115 | /* open all the files */ |
116 | fds = xmalloc(sizeof(int) * (argc + 1)); |
117 | nfiles = i = 0; |
118 | if (argc == 0) { |
119 | struct stat statbuf; |
120 | |
121 | if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) { |
122 | opt &= ~1; /* clear FOLLOW */ |
123 | } |
124 | *argv = (char *) bb_msg_standard_input; |
125 | goto DO_STDIN; |
126 | } |
127 | |
128 | do { |
129 | if (NOT_LONE_DASH(argv[i])) { |
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: /* "-" */ |
138 | fds[nfiles] = STDIN_FILENO; |
139 | } |
140 | argv[nfiles] = argv[i]; |
141 | ++nfiles; |
142 | } while (++i < argc); |
143 | |
144 | if (!nfiles) |
145 | bb_error_msg_and_die("no files"); |
146 | |
147 | tailbufsize = BUFSIZ; |
148 | |
149 | /* tail the files */ |
150 | if (!from_top && COUNT_BYTES) { |
151 | if (tailbufsize < count) { |
152 | tailbufsize = count + BUFSIZ; |
153 | } |
154 | } |
155 | |
156 | buf = tailbuf = xmalloc(tailbufsize); |
157 | |
158 | fmt = header_fmt + 1; /* Skip header leading newline on first output. */ |
159 | i = 0; |
160 | do { |
161 | /* Be careful. It would be possible to optimize the count-bytes |
162 | * case if the file is seekable. If you do though, remember that |
163 | * starting file position may not be the beginning of the file. |
164 | * Beware of backing up too far. See example in wc.c. |
165 | */ |
166 | if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) { |
167 | continue; |
168 | } |
169 | |
170 | if (nfiles > header_threshhold) { |
171 | tail_xprint_header(fmt, argv[i]); |
172 | fmt = header_fmt; |
173 | } |
174 | |
175 | buf = tailbuf; |
176 | taillen = 0; |
177 | seen = 1; |
178 | newline = 0; |
179 | |
180 | while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { |
181 | if (from_top) { |
182 | nwrite = nread; |
183 | if (seen < count) { |
184 | if (COUNT_BYTES) { |
185 | nwrite -= (count - seen); |
186 | seen = count; |
187 | } else { |
188 | s = buf; |
189 | do { |
190 | --nwrite; |
191 | if (*s++ == '\n' && ++seen == count) { |
192 | break; |
193 | } |
194 | } while (nwrite); |
195 | } |
196 | } |
197 | xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite); |
198 | } else if (count) { |
199 | if (COUNT_BYTES) { |
200 | taillen += nread; |
201 | if (taillen > count) { |
202 | memmove(tailbuf, tailbuf + taillen - count, count); |
203 | taillen = count; |
204 | } |
205 | } else { |
206 | int k = nread; |
207 | int nbuf = 0; |
208 | |
209 | while (k) { |
210 | --k; |
211 | if (buf[k] == '\n') { |
212 | ++nbuf; |
213 | } |
214 | } |
215 | |
216 | if (newline + nbuf < count) { |
217 | newline += nbuf; |
218 | taillen += nread; |
219 | |
220 | } else { |
221 | int extra = 0; |
222 | if (buf[nread-1] != '\n') { |
223 | extra = 1; |
224 | } |
225 | |
226 | k = newline + nbuf + extra - count; |
227 | s = tailbuf; |
228 | while (k) { |
229 | if (*s == '\n') { |
230 | --k; |
231 | } |
232 | ++s; |
233 | } |
234 | |
235 | taillen += nread - (s - tailbuf); |
236 | memmove(tailbuf, s, taillen); |
237 | newline = count - extra; |
238 | } |
239 | if (tailbufsize < taillen + BUFSIZ) { |
240 | tailbufsize = taillen + BUFSIZ; |
241 | tailbuf = xrealloc(tailbuf, tailbufsize); |
242 | } |
243 | } |
244 | buf = tailbuf + taillen; |
245 | } |
246 | } |
247 | |
248 | if (!from_top) { |
249 | xwrite(STDOUT_FILENO, tailbuf, taillen); |
250 | } |
251 | |
252 | taillen = 0; |
253 | } while (++i < nfiles); |
254 | |
255 | buf = xrealloc(tailbuf, BUFSIZ); |
256 | |
257 | fmt = NULL; |
258 | |
259 | if (FOLLOW) while (1) { |
260 | sleep(sleep_period); |
261 | i = 0; |
262 | do { |
263 | if (nfiles > header_threshhold) { |
264 | fmt = header_fmt; |
265 | } |
266 | while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) { |
267 | if (fmt) { |
268 | tail_xprint_header(fmt, argv[i]); |
269 | fmt = NULL; |
270 | } |
271 | xwrite(STDOUT_FILENO, buf, nread); |
272 | } |
273 | } while (++i < nfiles); |
274 | } |
275 | |
276 | return status; |
277 | } |