Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/coreutils/tail.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.5/mindi-busybox/coreutils/tail.c
r821 r1765 25 25 */ 26 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <ctype.h> 31 #include <unistd.h> 32 #include <fcntl.h> 33 #include <sys/stat.h> 34 #include "busybox.h" 27 #include "libbb.h" 35 28 36 29 static const struct suffix_mult tail_suffixes[] = { 37 30 { "b", 512 }, 38 31 { "k", 1024 }, 39 { "m", 10 48576},40 { NULL, 0}32 { "m", 1024*1024 }, 33 { } 41 34 }; 42 35 43 static int status; 36 struct globals { 37 bool status; 38 }; 39 #define G (*(struct globals*)&bb_common_bufsiz1) 44 40 45 41 static void tail_xprint_header(const char *fmt, const char *filename) 46 42 { 47 /* If we get an output error, there is really no sense in continuing. */ 48 if (dprintf(STDOUT_FILENO, fmt, filename) < 0) { 43 if (fdprintf(STDOUT_FILENO, fmt, filename) < 0) 49 44 bb_perror_nomsg_and_die(); 50 }51 }52 53 /* len should probably be size_t */54 static void tail_xbb_full_write(const char *buf, size_t len)55 {56 /* If we get a write error, there is really no sense in continuing. */57 if (bb_full_write(STDOUT_FILENO, buf, len) < 0) {58 bb_perror_nomsg_and_die();59 }60 45 } 61 46 … … 63 48 { 64 49 ssize_t r; 65 off_t current, end;50 off_t current, end; 66 51 struct stat sbuf; 67 52 … … 70 55 end = sbuf.st_size; 71 56 lseek(fd, end < current ? 0 : current, SEEK_SET); 72 if ((r = safe_read(fd, buf, count)) < 0) { 57 r = safe_read(fd, buf, count); 58 if (r < 0) { 73 59 bb_perror_msg(bb_msg_read_error); 74 status = EXIT_FAILURE;60 G.status = EXIT_FAILURE; 75 61 } 76 62 … … 78 64 } 79 65 80 static const char tail_opts[] = 81 "fn:c:" 82 #if ENABLE_FEATURE_FANCY_TAIL 83 "qs:v" 84 #endif 85 ; 86 87 static const char header_fmt[] = "\n==> %s <==\n"; 88 66 static const char header_fmt[] ALIGN1 = "\n==> %s <==\n"; 67 68 static unsigned eat_num(const char *p) 69 { 70 if (*p == '-') p++; 71 else if (*p == '+') { p++; G.status = EXIT_FAILURE; } 72 return xatou_sfx(p, tail_suffixes); 73 } 74 75 int tail_main(int argc, char **argv); 89 76 int tail_main(int argc, char **argv) 90 77 { 91 long count = 10; 92 unsigned int sleep_period = 1; 93 int from_top = 0; 94 int follow = 0; 78 unsigned count = 10; 79 unsigned sleep_period = 1; 80 bool from_top; 95 81 int header_threshhold = 1; 96 int count_bytes = 0; 82 const char *str_c, *str_n; 83 USE_FEATURE_FANCY_TAIL(const char *str_s;) 97 84 98 85 char *tailbuf; … … 100 87 int taillen = 0; 101 88 int newline = 0; 102 103 int *fds, nfiles, nread, nwrite, seen, i, opt; 89 int nfiles, nread, nwrite, seen, i, opt; 90 91 int *fds; 104 92 char *s, *buf; 105 93 const char *fmt; 106 94 107 #if !ENABLE_DEBUG_YANK_SUSv2 || ENABLE_FEATURE_FANCY_TAIL95 #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL 108 96 /* Allow legacy syntax of an initial numeric option without -n. */ 109 if (argc >=2 && ((argv[1][0] == '+') || ((argv[1][0] == '-') 110 /* && (isdigit)(argv[1][1]) */ 111 && (((unsigned int)(argv[1][1] - '0')) <= 9)))) 112 { 113 optind = 2; 114 optarg = argv[1]; 115 goto GET_COUNT; 116 } 97 if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-') 98 && isdigit(argv[1][1]) 99 ) { 100 /* replacing arg[0] with "-n" can segfault, so... */ 101 argv[1] = xasprintf("-n%s", argv[1]); 102 #if 0 /* If we ever decide to make tail NOFORK */ 103 char *s = alloca(strlen(argv[1]) + 3); 104 sprintf(s, "-n%s", argv[1]); 105 argv[1] = s; 117 106 #endif 118 119 while ((opt = getopt(argc, argv, tail_opts)) > 0) { 120 switch (opt) { 121 case 'f': 122 follow = 1; 123 break; 124 case 'c': 125 count_bytes = 1; 126 /* FALLS THROUGH */ 127 case 'n': 128 #if !ENABLE_DEBUG_YANK_SUSv2 || ENABLE_FEATURE_FANCY_TAIL 129 GET_COUNT: 107 } 130 108 #endif 131 count = bb_xgetlarg10_sfx(optarg, tail_suffixes); 132 /* Note: Leading whitespace is an error trapped above. */ 133 if (*optarg == '+') { 134 from_top = 1; 135 } else { 136 from_top = 0; 137 } 138 if (count < 0) { 139 count = -count; 140 } 141 break; 109 110 opt = getopt32(argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"), 111 &str_c, &str_n USE_FEATURE_FANCY_TAIL(,&str_s)); 112 #define FOLLOW (opt & 0x1) 113 #define COUNT_BYTES (opt & 0x2) 114 //if (opt & 0x1) // -f 115 if (opt & 0x2) count = eat_num(str_c); // -c 116 if (opt & 0x4) count = eat_num(str_n); // -n 142 117 #if ENABLE_FEATURE_FANCY_TAIL 143 case 'q': 144 header_threshhold = INT_MAX; 145 break; 146 case 's': 147 sleep_period =bb_xgetularg10_bnd(optarg, 0, UINT_MAX); 148 break; 149 case 'v': 150 header_threshhold = 0; 151 break; 118 if (opt & 0x8) header_threshhold = INT_MAX; // -q 119 if (opt & 0x10) sleep_period = xatou(str_s); // -s 120 if (opt & 0x20) header_threshhold = 0; // -v 152 121 #endif 153 default: 154 bb_show_usage(); 155 } 156 } 122 argc -= optind; 123 argv += optind; 124 from_top = G.status; 157 125 158 126 /* open all the files */ 159 fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1)); 160 161 argv += optind; 127 fds = xmalloc(sizeof(int) * (argc + 1)); 162 128 nfiles = i = 0; 163 164 if ( (argc -= optind)== 0) {129 G.status = EXIT_SUCCESS; 130 if (argc == 0) { 165 131 struct stat statbuf; 166 132 167 133 if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) { 168 follow = 0; 169 } 170 /* --argv; */ 134 opt &= ~1; /* clear FOLLOW */ 135 } 171 136 *argv = (char *) bb_msg_standard_input; 172 goto DO_STDIN; 173 } 174 137 } 175 138 do { 176 if ((argv[i][0] == '-') && !argv[i][1]) { 177 DO_STDIN: 178 fds[nfiles] = STDIN_FILENO; 179 } else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) { 180 bb_perror_msg("%s", argv[i]); 181 status = EXIT_FAILURE; 139 FILE* fil = fopen_or_warn_stdin(argv[i]); 140 if (!fil) { 141 G.status = EXIT_FAILURE; 182 142 continue; 183 143 } 184 argv[nfiles] = argv[i];185 ++nfiles;144 fds[nfiles] = fileno(fil); 145 argv[nfiles++] = argv[i]; 186 146 } while (++i < argc); 187 147 188 if (!nfiles) {148 if (!nfiles) 189 149 bb_error_msg_and_die("no files"); 190 }191 150 192 151 tailbufsize = BUFSIZ; 193 152 194 153 /* tail the files */ 195 if (from_top < count_bytes) { /* Each is 0 or 1, so true iff 0 < 1. */ 196 /* Hence, !from_top && count_bytes */ 154 if (!from_top && COUNT_BYTES) { 197 155 if (tailbufsize < count) { 198 156 tailbufsize = count + BUFSIZ; … … 210 168 * Beware of backing up too far. See example in wc.c. 211 169 */ 212 if ( (!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) {170 if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) { 213 171 continue; 214 172 } … … 228 186 nwrite = nread; 229 187 if (seen < count) { 230 if ( count_bytes) {188 if (COUNT_BYTES) { 231 189 nwrite -= (count - seen); 232 190 seen = count; … … 235 193 do { 236 194 --nwrite; 237 if ( (*s++ == '\n') && (++seen == count)) {195 if (*s++ == '\n' && ++seen == count) { 238 196 break; 239 197 } … … 241 199 } 242 200 } 243 tail_xbb_full_write(buf + nread - nwrite, nwrite);201 xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite); 244 202 } else if (count) { 245 if ( count_bytes) {203 if (COUNT_BYTES) { 246 204 taillen += nread; 247 205 if (taillen > count) { … … 263 221 newline += nbuf; 264 222 taillen += nread; 265 266 223 } else { 267 224 int extra = 0; 268 if (buf[nread-1] != '\n') { 225 226 if (buf[nread-1] != '\n') 269 227 extra = 1; 270 }271 272 228 k = newline + nbuf + extra - count; 273 229 s = tailbuf; … … 278 234 ++s; 279 235 } 280 281 236 taillen += nread - (s - tailbuf); 282 237 memmove(tailbuf, s, taillen); … … 293 248 294 249 if (!from_top) { 295 tail_xbb_full_write(tailbuf, taillen);250 xwrite(STDOUT_FILENO, tailbuf, taillen); 296 251 } 297 252 … … 303 258 fmt = NULL; 304 259 305 while (follow) {260 if (FOLLOW) while (1) { 306 261 sleep(sleep_period); 307 262 i = 0; … … 315 270 fmt = NULL; 316 271 } 317 tail_xbb_full_write(buf, nread);272 xwrite(STDOUT_FILENO, buf, nread); 318 273 } 319 274 } while (++i < nfiles); 320 275 } 321 322 return status; 323 } 276 if (ENABLE_FEATURE_CLEAN_UP) { 277 free(fds); 278 } 279 return G.status; 280 }
Note:
See TracChangeset
for help on using the changeset viewer.