blob: 126eaeef99dd672d243bfab68ce86fd993c79da0 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
John Beppuabb47722000-01-06 00:48:21 +00002/*
Manuel Novoa III cad53642003-03-19 09:13:01 +00003 * uniq implementation for busybox
John Beppuabb47722000-01-06 00:48:21 +00004 *
Manuel Novoa III 84b93f72005-09-15 08:06:42 +00005 * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org>
John Beppuabb47722000-01-06 00:48:21 +00006 *
Bernhard Reutner-Fischerab187822005-10-26 10:47:26 +00007 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
John Beppuabb47722000-01-06 00:48:21 +00008 */
9
Manuel Novoa III cad53642003-03-19 09:13:01 +000010/* BB_AUDIT SUSv3 compliant */
11/* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */
12
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000013#include "libbb.h"
John Beppuabb47722000-01-06 00:48:21 +000014
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000015static FILE *xgetoptfile_uniq_s(char **argv, int read0write2)
Rob Landley14efdc52005-09-07 04:18:36 +000016{
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000017 const char *n;
Rob Landley14efdc52005-09-07 04:18:36 +000018
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000019 n = *argv;
20 if (n != NULL) {
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000021 if ((*n != '-') || n[1]) {
Rob Landleyd921b2e2006-08-03 15:41:12 +000022 return xfopen(n, "r\0w" + read0write2);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000023 }
24 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000025 return (read0write2) ? stdout : stdin;
Rob Landley14efdc52005-09-07 04:18:36 +000026}
27
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000028int uniq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000029int uniq_main(int argc UNUSED_PARAM, char **argv)
John Beppuabb47722000-01-06 00:48:21 +000030{
Manuel Novoa III cad53642003-03-19 09:13:01 +000031 FILE *in, *out;
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000032 const char *s0, *e0, *s1, *e1, *input_filename;
Denis Vlasenko96b99b82008-05-03 07:21:27 +000033 unsigned long dups;
34 unsigned skip_fields, skip_chars, max_chars;
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000035 unsigned opt;
Denis Vlasenko96b99b82008-05-03 07:21:27 +000036 unsigned i;
John Beppuabb47722000-01-06 00:48:21 +000037
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000038 enum {
39 OPT_c = 0x1,
40 OPT_d = 0x2,
41 OPT_u = 0x4,
42 OPT_f = 0x8,
43 OPT_s = 0x10,
Denis Vlasenko96b99b82008-05-03 07:21:27 +000044 OPT_w = 0x20,
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000045 };
Manuel Novoa III cad53642003-03-19 09:13:01 +000046
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000047 skip_fields = skip_chars = 0;
Denis Vlasenko1a6adbd2009-03-09 16:43:28 +000048 max_chars = INT_MAX;
Matt Kraaie0bcce02000-09-27 02:29:39 +000049
Denis Vlasenko96b99b82008-05-03 07:21:27 +000050 opt_complementary = "f+:s+:w+";
51 opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars);
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000052 argv += optind;
53
54 input_filename = *argv;
Manuel Novoa III cad53642003-03-19 09:13:01 +000055
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000056 in = xgetoptfile_uniq_s(argv, 0);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000057 if (*argv) {
58 ++argv;
59 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000060 out = xgetoptfile_uniq_s(argv, 2);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000061 if (*argv && argv[1]) {
62 bb_show_usage();
63 }
Matt Kraaie0bcce02000-09-27 02:29:39 +000064
Denis Vlasenko96b99b82008-05-03 07:21:27 +000065 s1 = e1 = NULL; /* prime the pump */
Manuel Novoa III cad53642003-03-19 09:13:01 +000066
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000067 do {
68 s0 = s1;
69 e0 = e1;
70 dups = 0;
71
72 /* gnu uniq ignores newlines */
Denis Vlasenko8ee649a2008-03-26 20:04:27 +000073 while ((s1 = xmalloc_fgetline(in)) != NULL) {
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000074 e1 = s1;
Denis Vlasenkof0ed3762006-10-26 23:21:47 +000075 for (i = skip_fields; i; i--) {
Rob Landleyea224be2006-06-18 20:20:07 +000076 e1 = skip_whitespace(e1);
Bernhard Reutner-Fischerde17ece2007-04-10 09:38:35 +000077 e1 = skip_non_whitespace(e1);
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000078 }
Denis Vlasenkof0ed3762006-10-26 23:21:47 +000079 for (i = skip_chars; *e1 && i; i--) {
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000080 ++e1;
81 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000082
Denis Vlasenko96b99b82008-05-03 07:21:27 +000083 if (!s0 || strncmp(e0, e1, max_chars)) {
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000084 break;
Manuel Novoa III cad53642003-03-19 09:13:01 +000085 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000086
Denis Vlasenko96b99b82008-05-03 07:21:27 +000087 ++dups; /* note: testing for overflow seems excessive. */
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000088 }
89
90 if (s0) {
Denis Vlasenko4caa09a2007-03-31 10:19:11 +000091 if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_e) */
Denis Vlasenko96b99b82008-05-03 07:21:27 +000092 fprintf(out, "\0%ld " + (opt & 1), dups + 1); /* 1 == OPT_c */
Denis Vlasenkof0ed3762006-10-26 23:21:47 +000093 fprintf(out, "%s\n", s0);
Manuel Novoa III cad53642003-03-19 09:13:01 +000094 }
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000095 free((void *)s0);
Manuel Novoa III cad53642003-03-19 09:13:01 +000096 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000097 } while (s1);
Manuel Novoa III cad53642003-03-19 09:13:01 +000098
Denis Vlasenkof0ed3762006-10-26 23:21:47 +000099 die_if_ferror(in, input_filename);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000100
Denis Vlasenkof0ed3762006-10-26 23:21:47 +0000101 fflush_stdout_and_exit(EXIT_SUCCESS);
John Beppuabb47722000-01-06 00:48:21 +0000102}