12 |
|
|
13 |
#include "libbb.h" |
#include "libbb.h" |
14 |
|
|
|
static FILE *xgetoptfile_uniq_s(char **argv, int read0write2) |
|
|
{ |
|
|
const char *n; |
|
|
|
|
|
n = *argv; |
|
|
if (n != NULL) { |
|
|
if ((*n != '-') || n[1]) { |
|
|
return xfopen(n, "r\0w" + read0write2); |
|
|
} |
|
|
} |
|
|
return (read0write2) ? stdout : stdin; |
|
|
} |
|
|
|
|
15 |
int uniq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int uniq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
16 |
int uniq_main(int argc UNUSED_PARAM, char **argv) |
int uniq_main(int argc UNUSED_PARAM, char **argv) |
17 |
{ |
{ |
18 |
FILE *in, *out; |
const char *input_filename; |
|
const char *s0, *e0, *s1, *e1, *input_filename; |
|
|
unsigned long dups; |
|
19 |
unsigned skip_fields, skip_chars, max_chars; |
unsigned skip_fields, skip_chars, max_chars; |
20 |
unsigned opt; |
unsigned opt; |
21 |
unsigned i; |
char *cur_line; |
22 |
|
const char *cur_compare; |
23 |
|
|
24 |
enum { |
enum { |
25 |
OPT_c = 0x1, |
OPT_c = 0x1, |
26 |
OPT_d = 0x2, |
OPT_d = 0x2, /* print only dups */ |
27 |
OPT_u = 0x4, |
OPT_u = 0x4, /* print only uniq */ |
28 |
OPT_f = 0x8, |
OPT_f = 0x8, |
29 |
OPT_s = 0x10, |
OPT_s = 0x10, |
30 |
OPT_w = 0x20, |
OPT_w = 0x20, |
31 |
}; |
}; |
32 |
|
|
33 |
skip_fields = skip_chars = 0; |
skip_fields = skip_chars = 0; |
34 |
max_chars = -1; |
max_chars = INT_MAX; |
35 |
|
|
36 |
opt_complementary = "f+:s+:w+"; |
opt_complementary = "f+:s+:w+"; |
37 |
opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars); |
opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars); |
38 |
argv += optind; |
argv += optind; |
39 |
|
|
40 |
input_filename = *argv; |
input_filename = argv[0]; |
41 |
|
if (input_filename) { |
42 |
in = xgetoptfile_uniq_s(argv, 0); |
const char *output; |
43 |
if (*argv) { |
|
44 |
++argv; |
if (input_filename[0] != '-' || input_filename[1]) { |
45 |
} |
close(STDIN_FILENO); /* == 0 */ |
46 |
out = xgetoptfile_uniq_s(argv, 2); |
xopen(input_filename, O_RDONLY); /* fd will be 0 */ |
47 |
if (*argv && argv[1]) { |
} |
48 |
bb_show_usage(); |
output = argv[1]; |
49 |
|
if (output) { |
50 |
|
if (argv[2]) |
51 |
|
bb_show_usage(); |
52 |
|
if (output[0] != '-' || output[1]) { |
53 |
|
// Won't work with "uniq - FILE" and closed stdin: |
54 |
|
//close(STDOUT_FILENO); |
55 |
|
//xopen3(output, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
56 |
|
xmove_fd(xopen3(output, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO); |
57 |
|
} |
58 |
|
} |
59 |
} |
} |
60 |
|
|
61 |
s1 = e1 = NULL; /* prime the pump */ |
cur_compare = cur_line = NULL; /* prime the pump */ |
62 |
|
|
63 |
do { |
do { |
64 |
s0 = s1; |
unsigned i; |
65 |
e0 = e1; |
unsigned long dups; |
66 |
|
char *old_line; |
67 |
|
const char *old_compare; |
68 |
|
|
69 |
|
old_line = cur_line; |
70 |
|
old_compare = cur_compare; |
71 |
dups = 0; |
dups = 0; |
72 |
|
|
73 |
/* gnu uniq ignores newlines */ |
/* gnu uniq ignores newlines */ |
74 |
while ((s1 = xmalloc_fgetline(in)) != NULL) { |
while ((cur_line = xmalloc_fgetline(stdin)) != NULL) { |
75 |
e1 = s1; |
cur_compare = cur_line; |
76 |
for (i = skip_fields; i; i--) { |
for (i = skip_fields; i; i--) { |
77 |
e1 = skip_whitespace(e1); |
cur_compare = skip_whitespace(cur_compare); |
78 |
e1 = skip_non_whitespace(e1); |
cur_compare = skip_non_whitespace(cur_compare); |
79 |
} |
} |
80 |
for (i = skip_chars; *e1 && i; i--) { |
for (i = skip_chars; *cur_compare && i; i--) { |
81 |
++e1; |
++cur_compare; |
82 |
} |
} |
83 |
|
|
84 |
if (!s0 || strncmp(e0, e1, max_chars)) { |
if (!old_line || strncmp(old_compare, cur_compare, max_chars)) { |
85 |
break; |
break; |
86 |
} |
} |
87 |
|
|
88 |
++dups; /* note: testing for overflow seems excessive. */ |
free(cur_line); |
89 |
|
++dups; /* testing for overflow seems excessive */ |
90 |
} |
} |
91 |
|
|
92 |
if (s0) { |
if (old_line) { |
93 |
if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_e) */ |
if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_u) */ |
94 |
fprintf(out, "\0%ld " + (opt & 1), dups + 1); /* 1 == OPT_c */ |
if (opt & OPT_c) { |
95 |
fprintf(out, "%s\n", s0); |
/* %7lu matches GNU coreutils 6.9 */ |
96 |
|
printf("%7lu ", dups + 1); |
97 |
|
} |
98 |
|
printf("%s\n", old_line); |
99 |
} |
} |
100 |
free((void *)s0); |
free(old_line); |
101 |
} |
} |
102 |
} while (s1); |
} while (cur_line); |
103 |
|
|
104 |
die_if_ferror(in, input_filename); |
die_if_ferror(stdin, input_filename); |
105 |
|
|
106 |
fflush_stdout_and_exit(EXIT_SUCCESS); |
fflush_stdout_and_exit(EXIT_SUCCESS); |
107 |
} |
} |