diff options
Diffstat (limited to 'coreutils/uniq.c')
-rw-r--r-- | coreutils/uniq.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/coreutils/uniq.c b/coreutils/uniq.c new file mode 100644 index 000000000..100f2be00 --- /dev/null +++ b/coreutils/uniq.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * uniq implementation for busybox | ||
4 | * | ||
5 | * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> | ||
6 | * | ||
7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
8 | */ | ||
9 | |||
10 | /* BB_AUDIT SUSv3 compliant */ | ||
11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */ | ||
12 | |||
13 | #include "busybox.h" | ||
14 | |||
15 | static const char uniq_opts[] = "f:s:" "cdu\0\1\2\4"; | ||
16 | |||
17 | static FILE *xgetoptfile_uniq_s(char **argv, int read0write2) | ||
18 | { | ||
19 | const char *n; | ||
20 | |||
21 | if ((n = *argv) != NULL) { | ||
22 | if ((*n != '-') || n[1]) { | ||
23 | return xfopen(n, "r\0w" + read0write2); | ||
24 | } | ||
25 | } | ||
26 | return (read0write2) ? stdout : stdin; | ||
27 | } | ||
28 | |||
29 | int uniq_main(int argc, char **argv) | ||
30 | { | ||
31 | FILE *in, *out; | ||
32 | unsigned long dups, skip_fields, skip_chars, i, uniq_flags; | ||
33 | const char *s0, *e0, *s1, *e1, *input_filename; | ||
34 | int opt; | ||
35 | |||
36 | uniq_flags = skip_fields = skip_chars = 0; | ||
37 | |||
38 | while ((opt = getopt(argc, argv, uniq_opts)) > 0) { | ||
39 | if ((opt == 'f') || (opt == 's')) { | ||
40 | unsigned long t = xatoul(optarg); | ||
41 | if (opt == 'f') { | ||
42 | skip_fields = t; | ||
43 | } else { | ||
44 | skip_chars = t; | ||
45 | } | ||
46 | } else if ((s0 = strchr(uniq_opts, opt)) != NULL) { | ||
47 | uniq_flags |= s0[4]; | ||
48 | } else { | ||
49 | bb_show_usage(); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | input_filename = *(argv += optind); | ||
54 | |||
55 | in = xgetoptfile_uniq_s(argv, 0); | ||
56 | if (*argv) { | ||
57 | ++argv; | ||
58 | } | ||
59 | out = xgetoptfile_uniq_s(argv, 2); | ||
60 | if (*argv && argv[1]) { | ||
61 | bb_show_usage(); | ||
62 | } | ||
63 | |||
64 | s1 = e1 = NULL; /* prime the pump */ | ||
65 | |||
66 | do { | ||
67 | s0 = s1; | ||
68 | e0 = e1; | ||
69 | dups = 0; | ||
70 | |||
71 | /* gnu uniq ignores newlines */ | ||
72 | while ((s1 = xmalloc_getline(in)) != NULL) { | ||
73 | e1 = s1; | ||
74 | for (i = skip_fields; i; i--) { | ||
75 | e1 = skip_whitespace(e1); | ||
76 | while (*e1 && !isspace(*e1)) { | ||
77 | ++e1; | ||
78 | } | ||
79 | } | ||
80 | for (i = skip_chars; *e1 && i; i--) { | ||
81 | ++e1; | ||
82 | } | ||
83 | |||
84 | if (!s0 || strcmp(e0, e1)) { | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | ++dups; /* Note: Testing for overflow seems excessive. */ | ||
89 | } | ||
90 | |||
91 | if (s0) { | ||
92 | if (!(uniq_flags & (2 << !!dups))) { | ||
93 | fprintf(out, "\0%d " + (uniq_flags & 1), dups + 1); | ||
94 | fprintf(out, "%s\n", s0); | ||
95 | } | ||
96 | free((void *)s0); | ||
97 | } | ||
98 | } while (s1); | ||
99 | |||
100 | die_if_ferror(in, input_filename); | ||
101 | |||
102 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
103 | } | ||