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 "libbb.h"
|
---|
14 |
|
---|
15 | static const char uniq_opts[] ALIGN1 = "cdu" "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 | n = *argv;
|
---|
22 | if (n != NULL) {
|
---|
23 | if ((*n != '-') || n[1]) {
|
---|
24 | return xfopen(n, "r\0w" + read0write2);
|
---|
25 | }
|
---|
26 | }
|
---|
27 | return (read0write2) ? stdout : stdin;
|
---|
28 | }
|
---|
29 |
|
---|
30 | int uniq_main(int argc, char **argv);
|
---|
31 | int uniq_main(int argc, char **argv)
|
---|
32 | {
|
---|
33 | FILE *in, *out;
|
---|
34 | unsigned long dups, skip_fields, skip_chars, i;
|
---|
35 | const char *s0, *e0, *s1, *e1, *input_filename;
|
---|
36 | unsigned opt;
|
---|
37 |
|
---|
38 | enum {
|
---|
39 | OPT_c = 0x1,
|
---|
40 | OPT_d = 0x2,
|
---|
41 | OPT_u = 0x4,
|
---|
42 | OPT_f = 0x8,
|
---|
43 | OPT_s = 0x10,
|
---|
44 | };
|
---|
45 |
|
---|
46 | skip_fields = skip_chars = 0;
|
---|
47 |
|
---|
48 | opt = getopt32(argv, "cduf:s:", &s0, &s1);
|
---|
49 | if (opt & OPT_f)
|
---|
50 | skip_fields = xatoul(s0);
|
---|
51 | if (opt & OPT_s)
|
---|
52 | skip_chars = xatoul(s1);
|
---|
53 | argv += optind;
|
---|
54 |
|
---|
55 | input_filename = *argv;
|
---|
56 |
|
---|
57 | in = xgetoptfile_uniq_s(argv, 0);
|
---|
58 | if (*argv) {
|
---|
59 | ++argv;
|
---|
60 | }
|
---|
61 | out = xgetoptfile_uniq_s(argv, 2);
|
---|
62 | if (*argv && argv[1]) {
|
---|
63 | bb_show_usage();
|
---|
64 | }
|
---|
65 |
|
---|
66 | s1 = e1 = NULL; /* prime the pump */
|
---|
67 |
|
---|
68 | do {
|
---|
69 | s0 = s1;
|
---|
70 | e0 = e1;
|
---|
71 | dups = 0;
|
---|
72 |
|
---|
73 | /* gnu uniq ignores newlines */
|
---|
74 | while ((s1 = xmalloc_getline(in)) != NULL) {
|
---|
75 | e1 = s1;
|
---|
76 | for (i = skip_fields; i; i--) {
|
---|
77 | e1 = skip_whitespace(e1);
|
---|
78 | e1 = skip_non_whitespace(e1);
|
---|
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 (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_e) */
|
---|
93 | fprintf(out, "\0%d " + (opt & 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 | }
|
---|