blob: 26afc00f4779bfce78b97a7a8eb229375195a1cb [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
Rob Landleyea224be2006-06-18 20:20:07 +000013#include "busybox.h"
John Beppuabb47722000-01-06 00:48:21 +000014
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000015static const char uniq_opts[] = "f:s:" "cdu\0\1\2\4";
Rob Landley14efdc52005-09-07 04:18:36 +000016
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000017static FILE *xgetoptfile_uniq_s(char **argv, int read0write2)
Rob Landley14efdc52005-09-07 04:18:36 +000018{
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000019 const char *n;
Rob Landley14efdc52005-09-07 04:18:36 +000020
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000021 if ((n = *argv) != NULL) {
22 if ((*n != '-') || n[1]) {
Rob Landleyd921b2e2006-08-03 15:41:12 +000023 return xfopen(n, "r\0w" + read0write2);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000024 }
25 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000026 return (read0write2) ? stdout : stdin;
Rob Landley14efdc52005-09-07 04:18:36 +000027}
28
Erik Andersene49d5ec2000-02-08 19:58:47 +000029int uniq_main(int argc, 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 84b93f72005-09-15 08:06:42 +000032 unsigned long dups, skip_fields, skip_chars, i, uniq_flags;
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000033 const char *s0, *e0, *s1, *e1, *input_filename;
Manuel Novoa III cad53642003-03-19 09:13:01 +000034 int opt;
John Beppuabb47722000-01-06 00:48:21 +000035
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000036 uniq_flags = skip_fields = skip_chars = 0;
Manuel Novoa III cad53642003-03-19 09:13:01 +000037
38 while ((opt = getopt(argc, argv, uniq_opts)) > 0) {
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000039 if ((opt == 'f') || (opt == 's')) {
40 int t = bb_xgetularg10(optarg);
41 if (opt == 'f') {
42 skip_fields = t;
43 } else {
44 skip_chars = t;
45 }
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000046 } else if ((s0 = strchr(uniq_opts, opt)) != NULL) {
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000047 uniq_flags |= s0[4];
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000048 } else {
49 bb_show_usage();
50 }
Eric Andersen5b5db382000-12-09 16:37:53 +000051 }
Matt Kraaie0bcce02000-09-27 02:29:39 +000052
Manuel Novoa III cad53642003-03-19 09:13:01 +000053 input_filename = *(argv += optind);
54
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000055 in = xgetoptfile_uniq_s(argv, 0);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000056 if (*argv) {
57 ++argv;
58 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000059 out = xgetoptfile_uniq_s(argv, 2);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000060 if (*argv && argv[1]) {
61 bb_show_usage();
62 }
Matt Kraaie0bcce02000-09-27 02:29:39 +000063
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000064 s1 = e1 = NULL; /* prime the pump */
Manuel Novoa III cad53642003-03-19 09:13:01 +000065
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000066 do {
67 s0 = s1;
68 e0 = e1;
69 dups = 0;
70
71 /* gnu uniq ignores newlines */
72 while ((s1 = bb_get_chomped_line_from_file(in)) != NULL) {
73 e1 = s1;
74 for (i=skip_fields ; i ; i--) {
Rob Landleyea224be2006-06-18 20:20:07 +000075 e1 = skip_whitespace(e1);
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000076 while (*e1 && !isspace(*e1)) {
77 ++e1;
78 }
79 }
80 for (i = skip_chars ; *e1 && i ; i--) {
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000081 ++e1;
82 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000083
84 if (!s0 || strcmp(e0, e1)) {
85 break;
Manuel Novoa III cad53642003-03-19 09:13:01 +000086 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000087
88 ++dups; /* Note: Testing for overflow seems excessive. */
89 }
90
91 if (s0) {
92 if (!(uniq_flags & (2 << !!dups))) {
93 bb_fprintf(out, "\0%d " + (uniq_flags & 1), dups + 1);
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000094 bb_fprintf(out, "%s\n", s0);
Manuel Novoa III cad53642003-03-19 09:13:01 +000095 }
Manuel Novoa III 415f6c92005-09-08 06:02:49 +000096 free((void *)s0);
Manuel Novoa III cad53642003-03-19 09:13:01 +000097 }
Manuel Novoa III 84b93f72005-09-15 08:06:42 +000098 } while (s1);
Manuel Novoa III cad53642003-03-19 09:13:01 +000099
Rob Landleyd921b2e2006-08-03 15:41:12 +0000100 xferror(in, input_filename);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000101
102 bb_fflush_stdout_and_exit(EXIT_SUCCESS);
John Beppuabb47722000-01-06 00:48:21 +0000103}