diff options
Diffstat (limited to 'coreutils/head.c')
-rw-r--r-- | coreutils/head.c | 154 |
1 files changed, 95 insertions, 59 deletions
diff --git a/coreutils/head.c b/coreutils/head.c index ad21e1b95..dab4de11b 100644 --- a/coreutils/head.c +++ b/coreutils/head.c | |||
@@ -1,9 +1,8 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * Mini head implementation for busybox | 3 | * head implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 1999 by Lineo, inc. and John Beppu | 5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> |
6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> | ||
7 | * | 6 | * |
8 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -21,82 +20,119 @@ | |||
21 | * | 20 | * |
22 | */ | 21 | */ |
23 | 22 | ||
23 | /* BB_AUDIT SUSv3 compliant */ | ||
24 | /* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */ | ||
25 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ | ||
26 | |||
24 | #include <stdio.h> | 27 | #include <stdio.h> |
25 | #include <getopt.h> | ||
26 | #include <stdlib.h> | 28 | #include <stdlib.h> |
27 | #include <string.h> | 29 | #include <limits.h> |
28 | #include <ctype.h> | 30 | #include <ctype.h> |
31 | #include <unistd.h> | ||
29 | #include "busybox.h" | 32 | #include "busybox.h" |
30 | 33 | ||
31 | static int head(int len, FILE *fp) | 34 | static const char head_opts[] = |
32 | { | 35 | "n:" |
33 | int i; | 36 | #ifdef CONFIG_FEATURE_FANCY_HEAD |
34 | char *input; | 37 | "c:qv" |
38 | #endif | ||
39 | ; | ||
35 | 40 | ||
36 | for (i = 0; i < len; i++) { | 41 | static const char header_fmt_str[] = "\n==> %s <==\n"; |
37 | if ((input = get_line_from_file(fp)) == NULL) | ||
38 | break; | ||
39 | fputs(input, stdout); | ||
40 | free(input); | ||
41 | } | ||
42 | return 0; | ||
43 | } | ||
44 | 42 | ||
45 | /* BusyBoxed head(1) */ | ||
46 | int head_main(int argc, char **argv) | 43 | int head_main(int argc, char **argv) |
47 | { | 44 | { |
45 | unsigned long count = 10; | ||
46 | unsigned long i; | ||
47 | #ifdef CONFIG_FEATURE_FANCY_HEAD | ||
48 | int count_bytes = 0; | ||
49 | int header_threshhold = 1; | ||
50 | #endif | ||
51 | |||
48 | FILE *fp; | 52 | FILE *fp; |
49 | int need_headers, opt, len = 10, status = EXIT_SUCCESS; | 53 | const char *fmt; |
54 | char *p; | ||
55 | int opt; | ||
56 | int c; | ||
57 | int retval = EXIT_SUCCESS; | ||
50 | 58 | ||
51 | if (( argc >= 2 ) && ( argv [1][0] == '-' ) && isdigit ( argv [1][1] )) { | 59 | /* Allow legacy syntax of an initial numeric option without -n. */ |
52 | len = atoi ( &argv [1][1] ); | 60 | if ((argc > 1) && (argv[1][0] == '-') |
53 | optind = 2; | 61 | /* && (isdigit)(argv[1][1]) */ |
62 | && (((unsigned int)(argv[1][1] - '0')) <= 9) | ||
63 | ) { | ||
64 | --argc; | ||
65 | ++argv; | ||
66 | p = (*argv) + 1; | ||
67 | goto GET_COUNT; | ||
54 | } | 68 | } |
55 | 69 | ||
56 | /* parse argv[] */ | 70 | while ((opt = getopt(argc, argv, head_opts)) > 0) { |
57 | while ((opt = getopt(argc, argv, "n:")) > 0) { | 71 | switch(opt) { |
58 | switch (opt) { | 72 | #ifdef CONFIG_FEATURE_FANCY_HEAD |
59 | case 'n': | 73 | case 'q': |
60 | len = atoi(optarg); | 74 | header_threshhold = INT_MAX; |
61 | if (len >= 0) | 75 | break; |
76 | case 'v': | ||
77 | header_threshhold = -1; | ||
62 | break; | 78 | break; |
63 | /* fallthrough */ | 79 | case 'c': |
64 | default: | 80 | count_bytes = 1; |
65 | show_usage(); | 81 | /* fall through */ |
82 | #endif | ||
83 | case 'n': | ||
84 | p = optarg; | ||
85 | GET_COUNT: | ||
86 | count = bb_xgetularg10(p); | ||
87 | break; | ||
88 | default: | ||
89 | bb_show_usage(); | ||
66 | } | 90 | } |
67 | } | 91 | } |
68 | 92 | ||
69 | /* get rest of argv[] or stdin if nothing's left */ | 93 | argv += optind; |
70 | if (argv[optind] == NULL) { | 94 | if (!*argv) { |
71 | head(len, stdin); | 95 | *--argv = "-"; |
72 | return status; | 96 | } |
73 | } | ||
74 | 97 | ||
75 | need_headers = optind != (argc - 1); | 98 | fmt = header_fmt_str + 1; |
76 | while (argv[optind]) { | 99 | #ifdef CONFIG_FEATURE_FANCY_HEAD |
77 | if (strcmp(argv[optind], "-") == 0) { | 100 | if (argc - optind <= header_threshhold) { |
78 | fp = stdin; | 101 | header_threshhold = 0; |
79 | argv[optind] = "standard input"; | 102 | } |
80 | } else { | 103 | #else |
81 | if ((fp = wfopen(argv[optind], "r")) == NULL) | 104 | if (argc <= optind + 1) { |
82 | status = EXIT_FAILURE; | 105 | fmt += 11; |
83 | } | 106 | } |
84 | if (fp) { | 107 | /* Now define some things here to avoid #ifdefs in the code below. |
85 | if (need_headers) { | 108 | * These should optimize out of the if conditions below. */ |
86 | printf("==> %s <==\n", argv[optind]); | 109 | #define header_threshhold 1 |
110 | #define count_bytes 0 | ||
111 | #endif | ||
112 | |||
113 | do { | ||
114 | if ((fp = bb_wfopen_input(*argv)) != NULL) { | ||
115 | if (fp == stdin) { | ||
116 | *argv = (char *) bb_msg_standard_input; | ||
87 | } | 117 | } |
88 | head(len, fp); | 118 | if (header_threshhold) { |
89 | if (ferror(fp)) { | 119 | bb_printf(fmt, *argv); |
90 | perror_msg("%s", argv[optind]); | ||
91 | status = EXIT_FAILURE; | ||
92 | } | 120 | } |
93 | if (optind < argc - 1) | 121 | i = count; |
94 | putchar('\n'); | 122 | while (i && ((c = getc(fp)) != EOF)) { |
95 | if (fp != stdin) | 123 | if (count_bytes || (c == '\n')) { |
96 | fclose(fp); | 124 | --i; |
125 | } | ||
126 | putchar(c); | ||
127 | } | ||
128 | if (bb_fclose_nonstdin(fp)) { | ||
129 | bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */ | ||
130 | retval = EXIT_FAILURE; | ||
131 | } | ||
132 | bb_xferror_stdout(); | ||
97 | } | 133 | } |
98 | optind++; | 134 | fmt = header_fmt_str; |
99 | } | 135 | } while (*++argv); |
100 | 136 | ||
101 | return status; | 137 | bb_fflush_stdout_and_exit(retval); |
102 | } | 138 | } |